开发者

Rails 3 AR: Save and update methods do not save attributes changed in database but not object in memory?

开发者 https://www.devze.com 2023-03-11 20:43 出处:网络
Consider this scenario: butterfly = Butterfly.create(:color=\'blue\') Butterfly.update_all(:color=\'red\')

Consider this scenario:

  1. butterfly = Butterfly.create(:color='blue')
  2. Butterfly.update_all(:color='red')

At this point, as expected, butterfly (in memory) is blue while the corresponding database object is red. Now try to update the database entry

  1. butterfly.update_attributes(:size=>'big')

The result is that the size attribute is updated but the color is not. We're left with a situation where, even after a successful save or up开发者_JS百科date_attributes, the database does not match the object in memory. In fact, even butterfly.update_attribute(:color, 'blue') is not enough to force a change in the database! The only way I see to force is the change is by first updating the attribute to something else (butterfly.update_attribute(:color,'anything')) and then changing it back to the original value.

Is this the way things are supposed to be?


Sort-of.

Model.update_all issues an update query directly to the underlying database; it doesn't update any instances you already have in memory. Similarly, instance.update_attributes only updates—it doesn't re-fetch from the database, as it assumes that the instance has the most up-to-date attribute values already.

This usually works in Rails, instances are generally short-lived: they only exist within the scope of the request, and in most cases, they're being operated on directly.

In the situation you describe above, you need an extra step—Model#reload will do what you want:

# create our instance
@butterfly = Butterfly.create(color: 'blue') # => #<Butterfly id: 100, color: 'blue'>

Butterfly.update_all(color: 'red')

# We now have a mis-match between our instance and our database. Our instance 
# is still blue, but the database says it should be red. Reloading it...

@butterfly.reload # => #<Butterfly id: 100, color: 'red'>

# And we can now re-update our butterfly
@butterfly.update_attributes(size: 'big') # => #<Butterfly id: 100, color: 'red', size: 'big'>

If you're using update_all, it's a good idea to see if it's possible to structure your code so that it occurs before you load instances.

0

精彩评论

暂无评论...
验证码 换一张
取 消