caching - How do I force rails to not use a cached result for has_many through relations? -
i have following 3 models (massively simplified):
class < activerecord::base has_many :bs has_many :cs, :through => :bs end class b < activerecord::base belongs_to :a has_many :cs end class c < activerecord::base belongs_to :b end it seems a.cs gets cached first time used (per object) when i'd rather not.
here's console session highlights problem (the fluff has been edited out)
first, way should work
rails console 001 > b = b.create 002 > c = c.new 003 > c.b = b 004 > c.save 005 > = a.create 006 > a.bs << b 007 > a.cs => [#<c id: 1, b_id: 1>] this indeed expect. a.cs going nicely through a.bs relation.
and caching infuriations
008 > a2 = a.create 009 > a2.cs => [] 010 > a2.bs << b 011 > a2.cs => [] so first call a2.cs (resulting in db query) quite correctly returned no cs. second call, however, shows distinct lack of cs though jolly should there (no db queries occurred).
and test sanity not blame
012 > a.find(a2.id).cs => [#<c id: 1, b_id: 1>] again, db query performed both record , associated c's.
so, question: how force rails not use cached result? of course resign myself doing workaround (as shown in console step 12), since result in 2 queries when 1 necessary, i'd rather not.
i did more research issue. while using clear_association_cache convenient enough, adding after every operation invalidated cache did not feel dry. thought rails should able keep track of this. thankfully, there way!
i use example models: (has many b, has many c through b), b (belongs a, has many c), , c (belongs b).
we need use touch: true option belongs_to method. method updates updated_at attribute on parent model, more importantly triggers after_touch callback. callback allows automatically clear association cache instance of whenever related instance of b or c modified, created, or destroyed.
first modify belongs_to method calls b , c, adding touch:true
class b < activerecord::base belongs_to :a, touch: true has_many :cs end class c < activerecord::base belongs_to :b, touch: true end then add after_touch callback a
class < activerecord::base has_many :bs has_many :cs, through: :bs after_touch :clear_association_cache end now can safely hack away, creating sorts of methods modify/create/destroy instances of b , c, , instance of belong automatically have cache date without having remember call clear_association_cache on place.
depending on how use model b, may want add after_touch callback there well.
documentation belongs_to options , activerecord callbacks:
http://api.rubyonrails.org/classes/activerecord/callbacks.html
http://api.rubyonrails.org/classes/activerecord/associations/classmethods.html#method-i-belongs_to
hope helps!
Comments
Post a Comment