2016-11-22 5 views
0

Welche Methode wird bevorzugt, um einen bestimmten Datensatz aus einer has_many-Beziehung für ein bestimmtes Modell in Rails auszuwählen? (Ich bin mit Rails 5.)Auswählen einer has_many-Beziehung in Rails

Ich habe ein Modell User und ein Modell Picture, die über den folgenden Code verwandt sind:

class User < ApplicationRecord 
    has_many :pictures, as: :imageable 
    # ... 
end 

class Picture < ApplicationRecord 
    belongs_to :imageable, polymorphic: true 
    # ... 
end 

Was soll ich tun, um zu ermöglichen, ein User ein setzen Profilbild von den Bildern zugeordnet, damit ich @user.profile_picture auf einem User Objekt aufrufen und das Profilbild abrufen kann.

+0

Sie müssten es in 'User' speichern, wahrscheinlich als' has_one' Beziehung. Sie können diese Beziehung 'profile_picture' nennen :) –

+0

Also' has_one: profile_picture, wie:: imageable'? Wie hält sich das in der DB? Muss ich ein 'ProfilePicture'-Modell erstellen? – mindseyeblind

+0

Ja, und vergessen Sie nicht die Migration für diese Beziehung. –

Antwort

0

Sie können eine zusätzliche Eins-zu-Eins-Beziehung hinzufügen.

# create by running: 
# rails g migration AddPrimaryPictureToUser 
class AddPrimaryPictureToUser < ActiveRecord::Migration[5.0] 
    def change 
    add_column :users, :primary_picture_id, :integer 
    add_index :users, :primary_picture_id 
    add_foreign_key :users, :pictures, column: :primary_picture_id 
    end 
end 

class User < ApplicationRecord 
    has_many :pictures, as: :imageable 
    # This should be belongs_to and not has_one as the foreign key column is 
    # on the users table 
    belongs_to :primary_picture, 
      class_name: 'Picture', 
      optional: true 
end 


class Picture < ApplicationRecord 
    belongs_to :imageable, polymorphic: true 
    has_one :primary_user, 
      foreign_key: 'primary_picture_id', 
      class_name: 'User' 
    # ... 
end 

Der Hauptgrund, es auf diese Weise gegen zum Beispiel einen boolean-Flag auf der pictures Tabelle zu tun, ist, dass eine separate Beziehung macht es einfach zu verbinden, die zur Vermeidung von N + 1 wichtig ist Abfragen, die ein Problem darstellen, wenn Sie eine Gruppe von Benutzern zusammen mit ihrem primären Image auflisten.

@users = User.includes(:primary_picture).all 
+0

Interessant. Können Sie die vom Kommentator vorgeschlagene Lösung überprüfen und mir die Vorteile/Nachteile jeder Architektur erklären? – mindseyeblind

+0

Die Verwendung von Polymorphie in dieser Eins-zu-Eins-Beziehung ist ein Fehler, da Sie keine direkte Verknüpfung zwischen Benutzern und ihrem primären Image durchführen können. Polymorphismus bedeutet auch, dass Sie die referenzielle Integrität verlieren, da die Beziehung nicht durch einen Fremdschlüssel unterstützt wird. – max

+0

Okay, danke! Warum wird 'optional: true' nur in' User' und nicht 'Picture' gesetzt? – mindseyeblind

Verwandte Themen