Here’s a quick bit of info that will hopefully save somebody some time. ActiveRecord’s association methods are built around caching. This caching is disabled by default in development mode, but enabled in test and production modes. If you’re doing any kind of association updating in an ActiveRecord callback you may run into this caching and slam your head against your desk a few times.
Say we have a
Pledge class that belongs to a
Person class. People also have
Jobs and we want to (re)set their
job_id when a
Pledge is saved. Enter a virtual attribute and a callback:
class Person < ActiveRecord::Base has_many :pledges belongs_to :job end class Pledge < ActiveRecord::Base belongs_to :person attr_writer :job_id after_save do person.update_attribute(:job_id, @job_id) if @job_id.present? end end
This looks pretty straight forward. However, this simple test case will fail:
should "assign virtual job_id attribute to its person after save" do @pledge.job_id = 4 @pledge.save assert_equal 4, @pledge.person.job_id end
The associated person’s
job_id attribute never gets updated. After some experimentation, I realized that this code runs as expected in development mode. So, what gives? Caching gives, as I explained above.
Let’s fix this up to work regardless of ActiveRecord caching by forcing a trip to the database:
after_save do person(true).update_attribute(:job_id, @job_id) if @job_id.present? end
Ahh, that’s better. Read more on controlling ActiveRecord caching here.