0

I have a standard counter cache set up on Gallery to track its Photos. The counter cache is named as per Rails default photos_count.

In my Gallery spec I test the counter cache like this:

  it "updates 'photos_count' counter cache" do

    gallery = create(:gallery_with_photos, with_photos_count: 3)
    gallery.reload # Fails without this
    expect(gallery.photos_count).to eq 3


    expect {
      gallery.photos.first.destroy
      gallery.reload # Fails without this
      }.to change{ gallery.photos_count }.by(-1)

    gallery.photos << create(:photo)

    expect {
      gallery.save!
      gallery.reload # Fails without this
      }.to change { gallery.photos_count }.by(1)

  end

This works, but only with the calls to gallery.reload. Why does this spec fail without the calls to reload. Each failure is because there is no change in photos_count.

Note with_photos_count is a transient attribute used by the factory.

Undistraction
  • 42,754
  • 56
  • 195
  • 331

1 Answers1

3

This happens because the counter update is executed after the query and you need to refetch the object from the database to see the effect.

It is only required in testing environments.

There is also a discussion already about this here: Rspec testing of counter_cache column's returning 0

Community
  • 1
  • 1
Rafal
  • 2,576
  • 2
  • 18
  • 13
  • Yes, I've read that question, however there is no use of `reload` in the second part of his answer. – Undistraction Jul 02 '14 at 18:07
  • The difference is that in the other example, the count is retrieved via `User.last.media_count`, which forces another query. Your example tests the cached value in the `gallery` instance. – zetetic Jul 04 '14 at 02:29