views:

179

answers:

1

If a model changes an attribute locally, then changes it back, ActiveRecord doesn't send the change to the DB. This is great for performance, but if something else changes the database, and I want to revert it to the original value, the change doesn't take:

model = Model.find(1)
model.update_attribute(:a, 1) # start it off at 1

# some code here that changes model.a to 2
model.a = 2 # I know it changed, reflecting my local model of the change

model.update_attribute(:a, 1) # try change it back, DOESN'T WORK

The last line doesn't work because AR thinks in the DB it's still 1, even though something else changed it to 2. How can I force an AR update, or update the cache directly if I know the new value?

Side note: the code that changes it is an update_all query that locks the record, but it has side effects that mess up the cache. Multiple machines read this table. If there's a better way to do this I'd love to know.

Model.update_all(["locked_by = ?", lock_name], ["id = ? AND locked_by IS NULL", id])
+1  A: 

Use the reload method for this.

model.reload(:select => "a")

OR

You can try the will_change! method(Its not clear how your change happens. But you can try this method).

model.update_attribute(:a, 1) # start it off at 1
model.a_will_change! #fore warn the model about the change
model.a = 2  #perform the change
model.update_attribute(:a, 1)
KandadaBoggu
Does this do a database operation? I know what the value should be, so I'd rather set the cache directly
phillee
Yes. It does. That's why I have reduced the number of fields selected.
KandadaBoggu
I have updated my answer to suggest an alternative approach.
KandadaBoggu