Полиморфная ассоциация в обратном - PullRequest
1 голос
/ 17 марта 2010

Допустим, у меня есть две модели - одна называется Пост , а другая - Видео . Затем у меня есть третья модель - Комментарий - которая полиморфно связана с каждой из этих моделей.

Затем я легко могу сделать post.comments и video.comments , чтобы найти комментарии, связанные с записями этих моделей. Пока все просто.

Но что, если я захочу пойти другим путем и хочу найти ВСЕ посты и видео , которые были прокомментированы, и отобразить их в списке, отсортированном по дате комментарий был сделан? Это возможно?

Если это поможет, я работаю над бета-версией Rails 3.

Ответы [ 2 ]

2 голосов
/ 18 марта 2010

, вероятно, не лучшим образом, но у меня это сработало:

#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 }

надеюсь, что это работает и для вас.

EDIT

Я также предполагаю, что вы используете has_many :comments, :as => :commentable и belongs_to :commentable, :polymorphic => true, как предложил Кандада Боггу.

РЕДАКТИРОВАТЬ # 2

на самом деле, я думаю, что я сделал ошибку, и код выше не будет работать ... попробуйте это:

(Comment.find(:all, :order => "comment_date")).collect{ |x| x.commentable }
2 голосов
/ 17 марта 2010

Попробуйте это:

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

Теперь вы можете запускать следующие команды:

Post.with_comments
Video.with_comments

Редактировать Похоже, вы хотите один список с видео и сообщениями. Это довольно сложно, но выполнимо. Для каждой страницы вам нужно выполнить 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...