2010-06-02 66 views
1

我有一個帖子控制器,有很多評論。 帖子模型有一個名爲has_comments的字段,它是一個布爾值(所以我可以從數據庫中快速選擇只有有評論的帖子)。 要爲帖子創建新評論,我使用我的評論控制器的create操作。在Ruby on Rails中放置一段代碼的位置?

創建評論後,我需要更新我的帖子的has_comments字段,並將其設置爲true

我可以從我的評論控制器的create動作更新此字段,但這看起來不太合適 - 我覺得我應該真的使用該帖子的update動作,但我不確定是否正確致電它通過評論控制器的創建操作(通過send?)。

更新帖子的代碼應該在哪裏? 謝謝!

回答

2

爲什麼與另一列弄亂你的數據庫的接口程序?使用has_comments上的方法Post:

def has_comments 
    comments.size > 0 
end 

然後按照建議的方式實施counter_cache以減少查詢負載。

編輯:另外,實施反緩存後,您可以使用上發表named_scope檢索有註釋的所有帖子,使用單個查詢,如果是那樣的主要目標:

class Comment 
    belongs_to :post, :counter_cache => true 
end 

class Post 
    named_scope :with_comments, {:conditions=>"comments_count > 0"} 
end 

編輯:您還可以通過明智地使用以下方法避免着名的n + 1查詢問題:include:

posts = Post.find(:all, :include => :comments) 
+0

這也可以避免不一致(例如在刪除評論的情況下),否則您必須考慮 – averell 2010-06-02 16:07:36

+0

約定。使用一個新的列+回調是沉重而脆弱的,應該是一個簡單的方法。 – 2010-06-02 16:33:44

+0

那麼你將如何選擇所有有數據庫評論意見的帖子而不讀取所有帖子,然後計算每個帖子的評論,然後過濾結果?與簡單地更改列中的值相比,這會佔用更多的內存。不是嗎? – 2010-06-02 19:43:05

1

您可以在模型中使用before_save回調。

更好的方法是使用內置的:counter_cache選項,它會自動緩存每個帖子的評論數量。 (見http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#M001835下belongs_to的選項)

+0

謝謝。哪個模型可以將before_save回調放入?當創建/更新評論時,我認爲父母(即帖子模型)不會保存。但是將評論模型中的帖子(父母)更新的代碼不是很合適,是嗎?那麼,我有什麼後控制器的更新方法? – 2010-06-02 05:37:38

+0

你應該在before_save中加註釋。創建新評論時更新Post是可以的。基本上Rails在設置時會做同樣的事情:counter_cache for belongs_to(它在Comment模型中)。 – 2010-06-02 07:28:42

+1

其實,'before_save'不是正確的回調。我將使用after_save,並在'Comment'模型中使用,如下所述。因爲如果在保存時出現問題,您已經錯誤地更新了'has_comments'字段。 但是,使用':counter_cache'是一個非常好的解決方案,它將爲您處理所有繁重的工作。 – nathanvda 2010-06-02 09:58:46

1

使用after_save的在評論模型

def after_save 
    #this will set "has_comment" of the Specified Post to true if it's not true already 
    self.post.update_attribute('has_comment', true) unless self.post.has_comment 
end 
+0

謝謝。通過孩子的模型(評論模型)更新模型的父級(評論的帖子)是否合適?爲什麼我不會在這裏發送posts控制器的'update'方法? – 2010-06-02 05:43:47

+0

沒有更新方法會更新所有已存儲在數據庫中的數據並設置has_comment = true。更新方法的update_attributes調用所有回調(如果在Post模型中設置的話),而update_attribute不會,所以它會增加執行時間。 – Salil 2010-06-02 05:47:50