2010-09-13 98 views
1

的時間戳我有意見平常多態關聯來獲得最新項目:的Rails:查詢基於多態關聯

class Book < ActiveRecord::Base 
    has_many :comments, :as => :commentable 
end 

class Article < ActiveRecord::Base 
    has_many :comments, :as => :commentable 
end 

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

我希望能夠定義Book.recently_commented,和文章。 recent_commented基於評論的created_at時間戳。現在我正在尋找一個非常難看的find_by_SQL查詢來完成嵌套選擇。看起來好像有一個更好的方式可以在Rails中使用,而不需要使用SQL。

任何想法?謝謝。

對於它的價值,這裏的SQL:

select * from 
    (select books.*,comments.created_at as comment_date 
    from books inner join comments on books.id = comments.commentable_id 
    where comments.commentable_type='Book' order by comment_date desc) as p 
group by id order by null; 

回答

1

不知道你的方法看起來像以前,但我會從開始:

class Book < ActiveRecord::Base 

    def self.recently_commented 
    self.find(:all, 
       :include => :comments, 
       :conditions => ['comments.created_at > ?', 5.minutes.ago]) 
    end 
end 

這應該找出所有有過在最後5分鐘他們創造了一個註釋的書籍。 (你可能也想增加一個限制)。

我還很想創建一個基類此功能,以避免重複代碼:

class Commentable < ActiveRecord::Base 
    self.abstract_class = true 

    has_many :comments, :as => :commentable 

    def self.recently_commented 
    self.find(:all, 
       :include => :comments, 
       :conditions => ['comments.created_at > ?', Time.now - 5.minutes]) 
    end 
end 

class Book < Commentable 
end 

class Article < Commentable 
end 

此外,你可能想看看使用插件來實現這一目標。例如。 acts_as_commentable

+2

你可以重構Time.now - 5.分鐘由5.minutes.ago :) – hellvinz 2010-09-13 16:54:55

+0

謝謝,這讓我在那裏!我正在使用acts_as_commentable,所以我的下一個任務是將其添加到插件中,因此我不必爲每種類型重複該操作。 – 2010-09-13 18:30:33

+0

沒問題。更新以包含'.ago'的細化。 – Shadwell 2010-09-13 19:01:41

2

有時,它只是最好將字段添加到您的評論的對象。就像也許是一個datetime類型的commented_at字段。當對某個對象發表評論時,只需更新該值即可。

雖然可以使用SQL來完成它,但commented_at方法可能證明具有更高的可擴展性。

+0

是的,這可能是我最終走向的方式。代碼將更容易理解。 – 2010-09-13 16:43:12

+0

快速更新 - 出於性能原因,將commented_at字段添加到對象變得必要。在'註釋'回調中,我還禁用了record_timestamps,以便在註釋該對象時不更改updated_at。 – 2012-12-10 16:21:36