This post originated from an RSS feed registered with Ruby Buzz
by Obie Fernandez.
Original Post: counter_cache sneakiness
Feed Title: Obie On Rails (Has It Been 9 Years Already?)
Feed URL: http://jroller.com/obie/feed/entries/rss
Feed Description: Obie Fernandez talks about life as a technologist, mostly as ramblings about software development and consulting. Nowadays it's pretty much all about Ruby and Ruby on Rails.
class Firm < ActiveRecord::Base
has_many :votes
end
class Vote < ActiveRecord::Base
belongs_to :firm, :counter_cache => :vote_total
end
And this test case:
class FirmTest < Test::Unit::TestCase
fixtures :firms, :votes
def test_vote_total_should_increment_when_new_session_reports
firm = firms(:first)
assert_equal 4, firm.vote_total
firm.report('experimental','aaaaa','')
assert_equal 5, firm.vote_total
end
end
Why did I spend more time than I care to admit this evening trying to figure out if the :counter_cache option for belongs_to is broken?
The Answer
I'm guessing if you know the answer it's because you've been bitten by this little gotcha already. I figured it out by examining the test coverage for this feature of ActiveRecord:
The revised test for my code, which did finally pass:
def test_vote_total_should_increment_when_new_session_reports
firm = firms(:first)
assert_equal 4, firm.vote_total
firm.report('experimental','aaaaa','')
# Annoying that firm has to be reloaded here
# but in practice doesn't hurt anything, since requests that
# alter the total will be redirected, which reloads firm anyway.
assert_equal 5, firm.reload.vote_total
end
What do you think?
Is the need to invoke reload to pickup the up-to-date value for the counter cache a bug or a feature?