counter_cacheの実装の問題
-
28-09-2019 - |
質問
私は「レーキが中止されています! ... posts_countは、readonly 'エラーとマークされています。
ユーザーと投稿の2つのモデルがあります。
users has_many posts.
posts belongs_to :user, :counter_cache => true
post_count列をユーザーテーブルに追加し、ユーザーあたりの現在の投稿数を計算して記録する移行があります。
self.up
add_column :users, :posts_count, :integer, :default => 0
User.reset_column_information
User.all.each do |u|
u.update_attribute( :posts_count, u.posts.count)
end
end
移行を実行すると、エラーが発生します。もちろん、これはかなり明確なものです。投稿モデルからcounter_cache宣言を削除すると
belongs_to :user
移行は正常に動作します。これは明らかに、このように実際に実装できなかったため、意味がありません。何が足りないの?
解決
使用する必要があります User.reset_counters
これをする。さらに、使用することをお勧めします find_each
それ以外の each
それは一度にすべてではなくバッチでコレクションを繰り返すからです。
self.up
add_column :users, :posts_count, :integer, :default => 0
User.reset_column_information
User.find_each do |u|
User.reset_counters u.id, :posts
end
end
他のヒント
わかりました、ドキュメントは次のように述べています。
カウンターキャッシュ列は、Attr_readonlyを介して、Containing Modelの読み取り専用属性のリストに追加されます。
これが起こることだと思います。モデルの定義でカウンターを宣言するため、「post_count」属性を読み取り専用にします。次に、移行では、直接更新しようとすると、言及したエラーが発生します。
迅速な解決策は、モデルからcounter_cache宣言を削除し、移行を実行し(必要な列をデータベースに追加し、現在の投稿カウントで入力するため)、counter_cache宣言を再び付加することです。モデル。動作するはずですが、厄介であり、移行中に手動で介入する必要があります - 良い考えではありません。
私は見つけました このブログ投稿 これは、移行中の読み取り専用属性のモデルのリストを変更することを示唆しています。それは少しうるさいことですが、試してみたいと思うかもしれません。