I encountered a strange behavior when I run specs.
This code doesn’t work (baz.viewed is not updated) unless I uncomment line baz.reload.
describe "#..." do
it "..." do
baz = user.notifications.create!(title: "baz")
baz.update_attribute(:created_at, Time.now + 3.day)
# it sets `viewed` to `true` in the model to which `baz` is referred.
user.dismiss_latest_notification!
# baz.reload
baz.viewed.should == true
end
end
I don’t run specs using Spork or Guard, but this model isn’t reloaded anyway.
Why it might happening? Or, is it normal practice to invoke .reload methods in specs?
Let me make this case a bit clearer for you:
When the line
baz = user.notifications.create!(title: "baz")gets executed, two things happen:1- A new notification row is added to the DB.
2- An object is created in memory, representing this row, and may be referenced with the variable
baz.Note that
bazhas a viewed value of false (and so does the row in the meantime).Now I didn’t see the actual implementation of the method
But since you are not passing any variable to it I surely know you have a code in the spirit of:
The important line here is
An object is created in memory, representing the same row
bazdoes, but stored in another variable – latest_notification.Now you have two variables representing the same row in DB. When you perform the save on latest_notification the DB is updated with the right viewed value but the variable
bazis not updated in any manner to reflect this change. You have no choice but to force the update from the DB with the latest values by executingreloadon it.I think the right way to get rid of the reloading is to change the test a little bit:
Instead of
Use:
In my opinion, it better suits the purpose of this specific test.