2017-01-12 13 views
0

Ich mache eine Film-Review-Anwendung. Ein Benutzer kann durch die verschiedenen erstellten Berichte blättern und sie in einer Liste speichern. In meiner Konsole kann ich nicht auf die Listenrezensionen des Benutzers zugreifen. User.list.reviews. Was vermisse ich? Danke im Voraus!!Association Hilfe In Rails

Hier sind meine aktuellen Modelle und Verbände.

Benutzermodell

has_one :list 
has_many reviews, :through => :list 

Liste Modell

belongs_to :user 
has_many :reviews 

Bewertung Modell

has_many :lists 
has_many :users, :through => :lists 

Schema: Liste

user_id 
review_id 
+0

Bitte vereinfachen Sie Ihre Frage als was suchen Sie ..? – Milind

+0

Entschuldigung. Ich versuche, eine Liste in meiner Anwendung zu erstellen, die Rezensionen aus meinem Bewertungsmodell enthält. Jeder Benutzer hat eine Liste, die mehrere Bewertungen haben kann. Ich bin fest, wie ich meine Assoziationen zu machen. Meine Liste Tabelle ist die verbundene Tabelle mit review_id und user_id. Derzeit, wenn ich versuche, auf die Bewertungen in einer Benutzerliste zuzugreifen, bekomme ich diesen Fehler - o solche Spalte: reviews.list_id – hangloos

+0

Macht das mehr Sinn? Entschuldigung für die Verwirrung. – hangloos

Antwort

2

In Ihrem Schema hat eine Liste eine Benutzer-ID und eine Überprüfungs-ID. Eine Liste kann also nur eines dieser Dinge haben. Aber Sie möchten, dass ein Benutzer nur eine Liste hat, während die Liste viele Bewertungen hat.

Es wird dann komplexer, weil eine Liste viele Bewertungen haben kann. Da jedoch viele verschiedene Benutzer Bewertungen in ihre eigenen Listen aufnehmen können, wird eine Überprüfung möglicherweise in mehreren Listen angezeigt. Kurz gesagt, Liste has_and_belongs_to_many :reviews und Überprüfung has_and_belongs_to_many :lists. Das bedeutet, dass Sie das Paar ID-ID und Überprüfungs-ID, das diese Beziehung ausdrückt, irgendwo anordnen müssen - es heißt Join-Tabelle. Die Konvention ist nur die beiden Namen der verbundenen zwei Tabellen verketten, um den Namen der Join-Tabelle zu erhalten - wenn wir die Tabellen lists und reviews haben, benötigen wir eine Join-Tabelle namens lists_reviews (Sie können dies überschreiben, aber es ist einfacher, einfach mit zu gehen Das Treffen).

würde eine absolute Minimum Rails Migration sein: Die

create_table :users do |t| 
end 

create_table :lists do |t| 
    t.belongs_to :user # Leads to "user_id" column 
end 

create_table :reviews do |t| 
end 

create_table :lists_reviews do |t| 
    t.belongs_to :list # Leads to a "list_id" column 
    t.belongs_to :review # Leads to a "review_id" column 
end 

gegeben, und da auch sie hat, mit #has_one du sollte #belongs_to in der Sache stellen, so Liste sollte belong_to :user, erhalten wir:

class User < ActiveRecord::Base # Rails <= v4 
    has_one :list 
    has_many :reviews, :through => :list 
end 

class List < ActiveRecord::Base 
    belongs_to :user 
    has_and_belongs_to_many :reviews 
end 

class Review < ActiveRecord::Base 
    has_and_belongs_to_many :lists 
    has_many :users, :through => :lists 
end 

Und damit alles in eine leere Rails abgeladen schälen wir es an der Konsole testen können:

u1 = User.new; u1.save! 
u2 = User.new; u2.save! 

l1 = List.new(user: u1); l1.save! 
l2 = List.new(user: u2); l2.save! 

r1 = Review.new; r1.save! 
r2 = Review.new; r2.save! 
r3 = Review.new; r3.save! 

l1.reviews << r1 
l1.reviews << r2 
l1.save! 

l2.reviews << r2 
l2.reviews << r3 
l2.save! 

u1.list 
# => #<List id: 1, user_id: 1> 
u1.list.reviews 
# => #<ActiveRecord::Associations::CollectionProxy [#<Review id: 1>, #<Review id: 2>]> 
u2.list 
# => #<List id: 2, user_id: 2> 
u2.list.reviews 

# => #<ActiveRecord::Associations::CollectionProxy [#<Review id: 2>, #<Review id: 3>]> 
l1.user 
# => #<User id: 1> 
l2.user 
# => #<User id: 2> 

r1.users 
=> #<ActiveRecord::Associations::CollectionProxy [#<User id: 1>]> 
r1.lists 
=> #<ActiveRecord::Associations::CollectionProxy [#<List id: 1, user_id: 1>]> 
r2.users 
=> #<ActiveRecord::Associations::CollectionProxy [#<User id: 1>, #<User id: 2>]> 
r2.lists 
=> #<ActiveRecord::Associations::CollectionProxy [#<List id: 1, user_id: 1>, #<List id: 2, user_id: 2>]> 
r3.users 
=> #<ActiveRecord::Associations::CollectionProxy [#<User id: 2>]> 
r3.lists 
=> #<ActiveRecord::Associations::CollectionProxy [#<List id: 2, user_id: 2>]> 

... es funktioniert.

+0

Ein Kommentar zu folgen - die oben bedeutet auch, können Sie, dass 'has_one' zu ​​einem' HAS_MANY'- verändern und damit 'has_many: Bewertungen,: durch =>: lists', den Plural auf' lists' Feststellung. Jetzt hat ein Benutzer Listen statt nur einer Liste. Sie müssten Ihre Daten nicht ändern, aber Sie hätten 'user.lists' anstelle von' user.list'. Sie würden z.B. 'user.list [0] .reviews' statt nur' user.list.reviews' und 'user.reviews' würden eine vollständige Sammlung aller Überprüfungen über jede dem Benutzer gehörende Liste zurückliefern. Vielleicht möchten Sie nie mehrere Listen für einen Benutzer zulassen, aber es ist schön zu wissen, dass es sich um eine einfache Änderung handelt! –

+0

Danke für all das Andrew! Sehr hilfreich. – hangloos

+0

Keine Sorge, ich finde diese Art von Ding wirklich nützliche Überarbeitung, wenn ich eine Weile von Rails/interessanteren Assoziationen weg bin. –

0

Schema: Liste

user_id 
review_id 

Dies bedeutet, dass Ihre Liste gehört zu einem Benutzer und auch gehört zu einer Bewertung ... aber Sie haben Ihre Liste Verbände definiert wie folgt aus:

belongs_to :user 
has_many :reviews 

Rails wird immer verwirrt, also warum eine Liste ein review_id hat (das ist eine belongs_to Vereinigung Sache ist). und schaut auf das Review-Modell, in der Hoffnung, es wird eine list_id Spalte haben ... weil das ist, wie Sie das lösen würden ... und dennoch hat Ihr Review-Modell viele Listen, so dass es das Problem nicht lösen kann.

Können Sie uns sagen, was Sie eigentlich gerne hätten? Wie sollten diese Dinge zusammenhängen? sollten wir die Assoziationen ändern, die Sie definiert haben, damit sie mit den ID-Spalten übereinstimmen, oder können Sie die Beziehungen zwischen Modellen (z. B. mit einem Objektdiagramm) vollständiger spezifizieren und dann können wir Ihnen sagen, wie Sie Ihre ID-Spalten/Assoziationen ändern Objekt-Diagramm?

+0

Ok, der verwirrende Teil macht Sinn. Ich versuche, einem Benutzer eine Liste zu geben, die beliebig viele Bewertungen enthalten kann. – hangloos

+0

Eine Überprüfung kann auch in der Liste mehrerer Benutzer enthalten sein. – hangloos

0

Sie müssen dafür einen has_and_belongs_to_many verwenden. Schauen Sie sich http://guides.rubyonrails.org/association_basics.html#the-has-and-belongs-to-many-association an.

Das Problem ist, dass Ihr List-Modell has_many Bewertungen hat und Ihr Review-Modell has_many-Listen. Wenn zwei Modelle eine has_many-Beziehung zueinander haben, wie können Sie dies in der Datenbank modellieren? Wo würden Sie den ausländischen Schlüssel anbringen? Welche Tabelle den Fremdschlüssel hat, kann nur eine Zugehörigkeitsliste zu der anderen Tabelle haben. d. h. es kann nur zu einen Datensatz auf der anderen Tabelle gehören.

Die Lösung hierfür ist eine Join-Tabelle zu verwenden. In Schienen hat dies normalerweise einen Namen wie lists_reviews. Diese Join-Tabelle hätte zwei Fremdschlüssel, einen für die Listentabelle und einen für Übersichten. Auf diese Weise kann jede Tabelle eine has_many-Beziehung zu der anderen haben. In Schienen können Sie dazu has_and_belongs_to_many verwenden. Überprüfen Sie den Link oben für mehr.