3

私の Rails 3 アプリには 2 つのモデルがあり、3 番目のモデルはモデルとモデルの間の結合テーブルであり、has_many 関係があります。基本的に、User と Show は SavedShow によって結合され、ユーザーがショーのリストを保存できるようにします。

class Show < ActiveRecord::Base
  has_many :saved_shows
  has_many :users, :through => :saved_shows
end

class User < ActiveRecord::Base
  has_many :saved_shows
  has_many :shows, :through => :saved_shows
end

class SavedShow < ActiveRecord::Base
  belongs_to :user, :counter_cache => :saved_shows_count
  belongs_to :show
end

counter_cache フィールド (shows_saved_count) は自動的にインクリメントされますが、デクリメントされないことに気付きました。この問題の核心は、ユーザーのリストからのショーの削除が delete によって行われ、counter_cache の更新がトリガーされないことにあるようです。

current_user.shows.delete(@show)

ただし、ここで destroy メソッドを呼び出すことはできません。これは、SavedShow の User/Show 関連付けを削除しただけでなく、Show オブジェクト自体も削除したためです。これは私が望んでいるものではありません。

この種のシナリオでの counter_cache は適切な用途ではありませんか?

これは 2009 年にバグとして議論されたようで、修正が議論されましたが、最新の Rails 3.0 でもまだ問題が発生しています。

モデルに独自のカスタム処理を記述するだけですが、フックできる after_delete コールバックがないようです (おそらく、これがデクリメントが最初に機能しない理由です)。現時点では、関連付けの削除が発生する可能性があるコード内の場所は 1 つだけなので、カウンターを更新するために手動で呼び出しを行いますが、これは counter_cache を使用した ActiceRecord 関連付けの根本的な欠点またはバグのようです。 、何かが足りないのではないかと思っています。

これが実際に counter_caches の真の問題である場合、最善の回避策は何でしょうか?

4

2 に答える 2

1

ここでも同じ問題がありますが、Rails 2.3. 次のようなタッチも追加されていることに注意してください。

belongs_to :user, :counter_cache => :saved_shows_count, :touch => true

Association.delete(object) のカウンター キャッシュも関連する updated_at フィールドも更新しません。

この問題を回避するには、通常、結合モデルを操作しますが、これにはいくつかの欠点もあります。

パッチはこちら: https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/2824-patch-has_many-through-doesnt-update-counter_cache-on-join-model-correctly#ticket- 2824-18

于 2010-11-17T19:48:22.950 に答える