Rails 3 AR:保存和更新方法不保存数据库中更改的属性而不保存内存中的对象?

时间:2011-06-09 07:36:47

标签: ruby-on-rails-3 activerecord

考虑这种情况:

  1. butterfly = Butterfly.create(:color ='blue')
  2. Butterfly.update_all(:颜色= '红')
  3. 此时,正如预期的那样,butterfly(在内存中)为蓝色,而相应的数据库对象为红色。现在尝试更新数据库条目

    1. butterfly.update_attributes(:尺寸=> '大')
    2. 结果是size属性被更新但颜色不是。我们留下的情况是,即使在成功保存或update_attributes之后,数据库与内存中的对象不匹配。事实上,即使butterfly.update_attribute(:color, 'blue')也不足以强制改变数据库!我认为强制的唯一方法是更改​​首先将属性更新为其他内容(butterfly.update_attribute(:color,'anything')),然后将其更改回原始值。

      这是事情应该是这样的吗?

1 个答案:

答案 0 :(得分:6)

排序-的。

Model.update_all直接向底层数据库发出更新查询;它不会更新您在内存中已有的任何实例。同样,instance.update_attributes只更新 - 它不会从数据库中重新获取,因为它假定实例已经具有最新的属性值。

这个通常在Rails中起作用,实例通常是短暂的:它们只存在于请求的范围内,并且在大多数情况下,它们是直接操作的。

在您上面描述的情况中,您需要额外的步骤 - Model#reload将执行您想要的操作:

# 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'>

如果您正在使用update_all,那么最好先了解是否可以构建代码,以便在加载实例之前发生。