1

我正在使用Ruby on Rails 3.2.2,我想設置一個計數器緩存值爲「自定義」。也就是說,在這個時候(在我的移民文件),我嘗試使用下面的代碼:如何將計數器緩存值設置爲給定值?

def up 
    add_column :articles, :comments_count, :integer, :default => 0 

    Article.reset_column_information 

    Article.find_each do |article| 
    # Note: The following code doesn't work (when I migrate the database it 
    # raises the error "comments_count is marked as readonly"). 
    Article.update_column(:comments_count, article.custom_comments.count) 
    end 
end 

換句話說,我想設置:comments_count(計數器緩存數據庫表列) 爲自定義值(在我的情況該值article.custom_comments.count - :該custom_comments不是一個ActiveRecord協會,但在Article模型類規定的方法,它返回一個整數值爲好)has_many關聯有關秒。

也許,我可以/應該使用類似

Article.reset_column_information 

Article.find_each do |article| 
    Article.reset_counters(article.id, ...) 
end 

但似乎reset_counters方法離不開has_many協會工作。

如何將:comments_count計數器緩存值設置爲與「自定義關聯」相關的給定值?

回答

0

您將comments_count描述爲計數器緩存,但計數器緩存嚴格定義爲has_many關係中的關聯記錄數,您說這不是。

如果獲得所需值的唯一方法是通過Article上的方法,那麼您將不得不迭代所有Article對象並更新每個對象。

Article.find_each do |article| 
    article.update_attribute(:comments_count, article.custom_comments.count) 
end 

這是非常低效的,因爲它加載和保存每個對象。 如果custom_comments(你沒有真正解釋)的定義是你可以在SQL中表達的東西,那麼在數據庫中執行這個更新無疑會更快。這可能是這個樣子:

CREATE TEMP TABLE custom_comment_counts_temp AS 
    SELECT articles.id as id, count(comments.id) as custom_comments 
    FROM articles 
    LEFT JOIN comments ON articles.id = comments.article_id 
    WHERE <whatever condition indicates custom comments> 
    GROUP BY articles.id; 

CREATE INDEX ON custom_comments_counts_temp(id); 

UPDATE articles SET comments_count = (SELECT custom_comments FROM custom_comment_counts_temp WHERE custom_comment_counts_temp.id = articles.id); 

DROP TABLE custom_comment_counts_temp; 

(假設PostgreSQL的 - 如果你使用MySQL或其它數據庫,它可能會有所不同。如果你不使用關係型數據庫的話,那可能不是。是可能的)

此外,因爲它不是根據Rails的相當狹窄的定義計數器緩存,你需要寫一些回調是保持這些值進行更新 - 可能是一個after_save回調的評論,這樣的事情:

comment.rb:

after_save :set_article_custom_comments 


def set_article_custom_comments 
    a = self.article 
    a.update_attribute(:comments_count, a.custom_comments.count) 
end 
+0

計數器緩存的問題是它使用默認範圍。這意味着如果你想計算一些孩子被軟刪除的東西,計數就會是0.然後當你恢復這個對象時,大概你會恢復孩子們。但計數器緩存仍然是0。 – Mohamad

相關問題