简体   繁体   English

反向的多态关联

[英]Polymorphic association in reverse

Let's say that I have two models - one called Post and one other called Video . 假设我有两个模型 - 一个叫Post ,另一个叫Video I then have a third model - Comment - that is polymorphically associated to to each of these models. 然后我有第三个模型 - 评论 - 与每个模型的多态关联。

I can then easily do post.comments and video.comments to find comments assosciated to records of these models. 然后,我可以轻松地发布post.comvideo.com以查找与这些模型的记录相关的评论。 All easy so far. 到目前为止都很容易。

But what if I want to go the other way and I want to find ALL posts and videos that have been commented on and display these in a list sorted on the date that the comment was made? 但是,如果我想转向其他方式并且我想查找已经评论过的所有帖子视频并将其显示在按评论发布日期排序的列表中,该怎么办? Is this possible? 这可能吗?

If it helps I'm working on Rails 3 beta. 如果它有助于我正在开发Rails 3 beta。

Try this: 尝试这个:

class Post < ActiveRecord::Base
  has_many :comments, :as => :commentable
  named_scope :with_comments, :joins => :comments, 
                              :order => "comments.created_at DESC"
end

class Video < ActiveRecord::Base
  has_many :comments, :as => :commentable
  named_scope :with_comments, :joins => :comments, 
                              :order => "comments.created_at DESC"
end

class Comment < ActiveRecord::Base
  belongs_to :commentable, :polymorphic => true
end

Now you can run these commands: 现在您可以运行以下命令:

Post.with_comments
Video.with_comments

Edit It looks like you want a single list with Videos and Posts. 编辑看起来您想要一个包含视频和帖子的列表。 This is quite tricky, but doable. 这很棘手,但可行。 For every page you will have to execute 3 queries. 对于每个页面,您将必须执行3个查询。

def commented_videos_posts(page = 1, page_size = 30)
  # query 1: get the lastest comments for posts and videos
  comments = Comment.find_all_by_commentable_type(["Post", "Video"], 
               :select => "commentable_type, commentable_id, 
                              MAX(created_at) AS created_at",
               :group => "commentable_type, commentable_id"
               :order => "created_at DESC", 
               :limit => page_size, :offset => (page-1)*page_size)

  # get the video and post ids
  post_ids, video_ids = [], []
  comments.each do |c|
    post_ids << c.commentable_id if c.commentable_type == "Post"
    video_ids << c.commentable_id if c.commentable_type == "Video"
  end

  posts, videos = {}, {}

  # query 2: get posts
  Post.all(post_ids).each{|p| posts[p.id] = p }
  # query 3: get videos
  Video.all(video_ids).each{|v| videos[v.id] = v }

  # form one list of videos and posts
  comments.collect do |c| 
    c.commentable_type == "Post" ? posts[c.commentable_id] :
                                   videos[c.commentable_id]
  end
end

probably not the best way, but this worked for me: 可能不是最好的方式,但这对我有用:

#get all posts and videos
posts_and_videos = Comment.all.collect{ |c| c.commentable }

#order by last comment date
posts_and_videos_ordered = posts_and_videos.sort{ |x,y| x.comment_date <=> y.comment_date }

hope this works for you too. 希望这也适合你。

EDIT 编辑

i'm also assuming you're using has_many :comments, :as => :commentable and belongs_to :commentable, :polymorphic => true like KandadaBoggu suggested. 我也假设你正在使用has_many :comments, :as => :commentablebelongs_to :commentable, :polymorphic => true就像KandadaBoggu建议的那样。

EDIT #2 编辑#2

actually, i think i made a mistake and the code above won't work... try this: 实际上,我认为我犯了一个错误,上面的代码将无法正常工作...试试这个:

(Comment.find(:all, :order => "comment_date")).collect{ |x| x.commentable }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM