更新属性后ActiveRecord不保存

时间:2014-05-10 16:30:18

标签: ruby-on-rails json activerecord

我想知道这里是否有一些我不理解的东西,或者我是否遇到过ActiveRecord(4.1.1)中的错误。

我有一个包含一个属性的记录数据库,其中包含一些JSON字段。我拿一个并尝试更新它。

test = Submission.find(1)
test.update_attribute('json_data',similar_but_different_json(test.json_data))

我们假设方法similar_but_different_json对该JSON进行了一次小更新。在我的情况下,我正在修复由破损表单创建的一些数据错误。

执行此操作时,我没有收到任何错误,我在控制台中显示提交但未提交数据并返回true

为了实际更新记录,我必须这样做。

test = Submission.find(1)
old_json_data = test.json_data
test.json_data = ""
test.json_data = similar_but_different_json(old_json_data)
test.save

似乎正在发生的事情是ActiveRecord没有确定已经进行了必须保存的更改。这可能是为什么将字段设置为空字符串然后返回JSON允许记录保存?

3 个答案:

答案 0 :(得分:10)

will_change!

您也可以使用:

test.json_data_will_change!   # Goes before the save.

这将告诉ActiveModel属性json_data已经改变(即它的←那里有一个笑话)并且会在保存时正确更新该值。

有关详细信息,请参阅Rails is not saving an attribute that is changed

答案 1 :(得分:1)

我不明白为什么对象没有标记为脏。解决方法是使用update_columns

test.update_columns(json_data: similar_but_different_json(test.json_data))

它将直接在DB中执行UPDATE查询,无需任何验证,脏检查等...... json_data字段不能是只读的。

答案 2 :(得分:1)

ActiveModel(4.1.1版)无法跟踪属性的“内联”修改。

您的'similar_but_different_json'方法可能会对字符串进行内联修改。

在修改之前只需复制字符串。

test = Submission.find(1)
test_json_data_duplicate = test.json_data.dup 
test.update_attribute('json_data',similar_but_different_json(test_json_data_duplicate))

你什么时候......

test.json_data = ""

... ActiveModel可以捕获更改,因为您将其设置为恰好为空的新String对象。因此,当您调用update_attribute时,模型已经知道该属性已更改。

如果您尝试以内联方式清空字符串,那么您的技巧将无效。

test = Submission.find(1)
old_json_data = test.json_data
test.json_data.clear # Instead of test.json_data = ""
test.json_data = similar_but_different_json(old_json_data)
test.save

ActiveModel::Dirty