【问题标题】:Rails 4: combining has_many :through association with polymorphic associationRails 4:结合 has_many :通过关联与多态关联
【发布时间】:2016-03-20 09:19:27
【问题描述】:

在我的 Rails 4 应用程序中,我有以下模型:

User
has_many :administrations
has_many :calendars, through: :administrations
has_many :comments
has_many :calendar_comments, through: :calendars, :source => :comments

Calendar
has_many :administrations
has_many :users, through: :administrations
has_many :posts
has_many :comments, through: posts
has_many :ads

Administration
belongs_to :user
belongs_to :calendar

Post
belongs_to :calendar
has_many :comments, as: :commentable

Ad
belongs_to :calendar
has_many :comments, as: :commentable

Comment
belongs_to :commentable, polymorphic: true
belongs_to :user

我需要从calendar 和ad belongs_to 访问comments、belong_to 和ad。

这就是我在Calendars#Index 操作中尝试做的事情:

@posts_comments = @user.calendar_comments.where(commentable_type: "Post").order("created_at DESC").limit(5)
@ads_comments = @user.calendar_comments.where(commentable_type: "Ad").order("created_at DESC").limit(5)

我的第一个猜测是在日历模型中添加has_many :comments, through: ads:

Calendar
has_many :administrations
has_many :users, through: :administrations
has_many :posts
has_many :comments, through: posts
has_many : ads
has_many :comments, through: ads

但这取消了has_many :comments, through: posts的效果,然后我不能再从calendarpostbelongs_to访问commentsbelong_to和post。

有没有办法让 BOTH has_many :comments, through: posts AND has_many :comments, through: ads 工作?

————

更新:根据this article和that Stack Overflow question,答案可能在于source:和source_type:的使用。

但不知道如何使用这些。

————

更新 2:下面的代码有意义吗?

class Calendar < ActiveRecord::Base
  has_many :administrations, dependent: :destroy
  has_many :users, through: :administrations
  has_many :posts, dependent: :destroy
  has_many :commented_posts, through: :comments, source: :commentable, source_type: 'Post'
  has_many :ads, dependent: :destroy
  has_many :commented_ads, through: :comments, source: :commentable, source_type: 'Ad'

————

更新 3:当我尝试上面的代码时,我收到以下错误消息:

Could not find the source association(s) :comments in model Calendar. Try 'has_many :calendar_comments, :through => :calendars, :source => <name>'. Is it one of administrations, users, posts, commented_posts, ads, commented_ads, invites, or pokes?

我尝试了以下方法:

class Calendar < ActiveRecord::Base
  has_many :administrations, dependent: :destroy
  has_many :users, through: :administrations
  has_many :posts, dependent: :destroy
  has_many :calendar_comments, :through => :calendars, :source => :post
  has_many :ads, dependent: :destroy
  has_many :calendar_comments, :through => :calendars, :source => :ad

————

更新 4:使用以下代码的新尝试失败:

class Calendar < ActiveRecord::Base
  has_many :administrations, dependent: :destroy
  has_many :users, through: :administrations
  has_many :posts, dependent: :destroy
  has_many :calendar_comments, :through => :commentable, :source => :post
  has_many :ads, dependent: :destroy
  has_many :calendar_comments, :through => :commentable, :source => :ad

还是不行,和上面一样的错误信息。

————

更新 5:根据 MrYoshiji 的回答,我现在有了

class Calendar < ActiveRecord::Base
  has_many :administrations, dependent: :destroy
  has_many :users, through: :administrations
  has_many :posts, dependent: :destroy
  has_many :posts_comments, through: :posts, source_type: 'Post'
  has_many :ads, dependent: :destroy
  has_many :ads_comments, through: :ads, source_type: 'Ad'

现在,User 模型中的 has_many :calendar_comments, through: :calendars, :source =&gt; :comments 不再工作。

我试过了:

has_many :comments
has_many :calendar_post_comments, through: :calendars, :source => :post_comments
has_many :calendar_ad_comments, through: :calendars, :source => :ad_comments

还是不行。

————

更新 6:我仍然被这个问题困扰,因为我无法找到让以下代码正常工作的方法:

@posts_comments = @user.calendar_comments.where(commentable_type: "Post").order("created_at DESC").limit(5)
@ads_comments = @user.calendar_comments.where(commentable_type: "Ad").order("created_at DESC").limit(5)

我尝试了很多不同的方法,到目前为止我能想到的最好的方法是:

class Calendar < ActiveRecord::Base
  has_many :administrations, dependent: :destroy
  has_many :users, through: :administrations
  has_many :posts, dependent: :destroy
  has_many :post_comments, through: :posts, source_type: 'Post'
  has_many :ads, dependent: :destroy
  has_many :ad_comments, through: :ads, source_type: 'Ad'
end

class User < ActiveRecord::Base
  has_many :administrations, dependent: :destroy
  has_many :calendars, through: :administrations
  has_many :comments
  has_many :calendar_post_comments, through: :calendars, :source => :post_comments
  has_many :calendar_ad_comments, through: :calendars, :source => :ad_comments
end

然后,我更新我的日历控制器如下:

def index
    @user = current_user
    @calendars = @user.calendars.all
    @posts_comments = @user.calendar_post_comments
                              .order("created_at DESC")
                              .limit(5)
    @ads_comments = @user.calendar_ad.comments
                              .order("created_at DESC")
                              .limit(5)
end

但这会返回以下错误:

NoMethodError at /calendars
undefined method `chain' for nil:NilClass
@posts_comments = @user.calendar_post_comments.order("created_at DESC").limit(5)

这里有什么问题?

【问题讨论】:

  • 你不能为不同的关系使用相同的关系名称(你应该将calendar_comments重命名为post_comments和ad_comments)。此外,您可以删除代码中所有不相关的部分(has_many :invites 在这里没有用处)

标签: ruby-on-rails ruby-on-rails-4 activerecord has-many-through polymorphic-associations


【解决方案1】:

您应该尝试以下方法:

class Calendar < ActiveRecord::Base
  # [ ... ]
  has_many :posts
  has_many :posts_comments, through: posts, source_type: 'Post'
  has_many :ads
  has_many :ads_comments, through: ads, source_type: 'Ad'

考虑到Ad 和Post 模型都具有以下特性:

has_many :comments, as: :commentable

【讨论】:

  • 好的,非常感谢。这对User 模型意味着什么?我目前有has_many :comments has_many :calendar_comments, through: :calendars, :source =&gt; :comments,但这不再有效。
  • 尝试用source_type: 'Comment'替换:source =&gt; :comments
  • 完成。现在,我得到:NoMethodError at /calendars undefined method 'post_comments' for #&lt;User:0x007fcb21741870&gt;。我猜这是因为我们没有在User 模型中声明post_comments 和ad_comments,对吧?
  • 你可以声明这两个,或者你可以简单地自己做逻辑,而不是在用户模型中声明has_many :posts_comments
猜你喜欢
  • 2014-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多