【问题标题】:Association Help In RailsRails 中的关联帮助
【发布时间】:2017-01-12 00:14:08
【问题描述】:

我正在制作电影评论应用程序。用户可以滚动浏览已创建的不同评论并将它们保存到列表中。在我的控制台中,我无法访问用户的列表评论。用户列表评论。我错过了什么?提前致谢!!

这是我目前的模型和关联。

用户模型

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

列表模型

belongs_to :user
has_many :reviews

审查模型

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

架构:列表

user_id
review_id

【问题讨论】:

  • 请将您的问题简化为您在寻找什么......?
  • 很抱歉。我正在尝试在我的应用程序中创建一个列表,其中包括来自我的评论模型的评论。每个用户都有一个列表,可以有多个评论。我被困在如何建立关联上。我的列表表是带有 review_id 和 user_id 的连接表。目前,当我尝试访问用户列表中的评论时,我收到了这个错误 - o 这样的列:reviews.list_id
  • 这样更有意义吗?很抱歉造成混乱。
  • 我认为你应该替换 has_many :reviews on list model for has_and_belongs_to_many。

标签: ruby-on-rails ruby join associations inner-join


【解决方案1】:

在您的架构中,列表具有一个用户 ID 和一个评论 ID。因此,列表只能拥有其中之一。但是您希望一个用户只有一个列表,而该列表有很多评论。

然后它变得更加复杂,因为一个列表可以有很多评论。但是由于许多不同的用户可以将评论放入他们自己的列表中,因此一条评论可能会出现在多个列表中。简而言之,列出has_and_belongs_to_many :reviews 并查看has_and_belongs_to_many :lists。这意味着您需要在某个地方放置表达这种关系的列表 ID 和评论 ID 对 - 它称为 连接表。约定只是连接相关两个表的两个名称以获得连接表的名称 - 所以如果我们有表 listsreviews,我们需要一个名为 lists_reviews 的连接表(你可以覆盖它但是遵循约定更容易)。

最低限度的 Rails 迁移是:

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

考虑到这一点,并且考虑到 #has_one 你应该把 #belongs_to 也放在它所拥有的东西中,所以 List 应该 belong_to :user,我们得到:

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

所有这些都被转储到一个空的 Rails shell 中,我们可以在控制台上对其进行测试:

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>]>

...它有效。

【讨论】:

  • 一条要跟进的评论 - 以上也意味着您可以将 has_one 更改为 has_many 并因此更改为 has_many :reviews, :through =&gt; :lists,注意 lists 上的复数形式。现在用户将拥有列表,而不仅仅是一个列表。您不需要更改数据,但您将拥有user.lists 而不是user.list。你会做例如user.list[0].reviews 而不仅仅是 user.list.reviewsuser.reviews 将返回用户拥有的每个列表中每个评论的完整集合。您可能永远不想为一个用户允许多个列表,但很高兴知道这将是一个简单的更改!
  • 感谢所有这些安德鲁!很有帮助。
  • 不用担心,当我离开 Rails 一段时间/更有趣的关联时,我发现这种东西真的很有用。
【解决方案2】:

架构:列表

user_id
review_id

这意味着您的列表属于 - 一个用户,也属于 - 一个评论...但是您已经定义了这样的列表关联:

belongs_to :user
has_many :reviews

所以Rails 对为什么一个列表有一个review_id(这是一个belongs_to 关联的东西)感到困惑。并且正在查看 Review 模型,希望它会有一个 list_id 列...因为这就是您解决那个问题的方式...但是您的 Review 模型有很多列表,所以它无法解决问题。

您能告诉我们您真正希望发生的事情吗?这些东西应该如何关联?我们应该更改您定义的关联以匹配 id-columns 还是您可以更完整地指定模型之间的关系(例如使用对象图),然后我们可以告诉您如何更改您的 id-columns/associations 以匹配您的对象图?

【讨论】:

  • 好的,混淆部分是有道理的。我试图让用户拥有一个列表,其中可以包含任意数量的评论。
  • 另外,一条评论可以在多个用户的列表中。
【解决方案3】:

您需要为此使用has_and_belongs_to_many。看看http://guides.rubyonrails.org/association_basics.html#the-has-and-belongs-to-many-association

问题在于您的 List 模型有_many 个评论,而您的 Review 模型有_many 个列表。如果两个模型彼此之间都具有 has_many 关系,那么如何在数据库中对其进行建模?也就是说,你会把外键放在哪里?无论哪个表具有外键,都只能与另一个表有belongs_to 关系。即它只能属于另一张表上的一个记录。

解决方案是使用连接表。在 Rails 中,它的名称通常类似于 lists_reviews。此连接表将有两个外键,一个用于列表表,一个用于评论。这样,每个表都可以与另一个表有一个 has_many 关系。在 Rails 中,您可以使用 has_and_belongs_to_many 来执行此操作。查看上面的链接了解更多信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多