例如,如果我在test.update_attributes prop1: 'test', prop2: 'test2'
和prop1
具有阻止这些值的验证时运行prop2
,test.prop1
仍然是'test'
和{{1仍然是test.prop2
。为什么会发生这种情况?我该如何解决?
答案 0 :(得分:1)
根据the Rails docs for update_attributes
,它是update
的别名。其来源如下:
'test2'
因此,它包含在数据库事务中,这就是回滚发生的原因。但是,让我们查看# File activerecord/lib/active_record/persistence.rb, line 247
def update(attributes)
# The following transaction covers any possible database side-effects of the
# attributes assignment. For example, setting the IDs of a child collection.
with_transaction_returning_status do
assign_attributes(attributes)
save
end
end
。根据{{3}}:
assign_attributes
# File activerecord/lib/active_record/attribute_assignment.rb, line 23
def assign_attributes(new_attributes)
...
_assign_attribute(k, v)
...
end
所以,当你致电# File activerecord/lib/active_record/attribute_assignment.rb, line 53
def _assign_attribute(k, v)
public_send("#{k}=", v)
rescue NoMethodError
if respond_to?("#{k}=")
raise
else
raise UnknownAttributeError.new(self, k)
end
end
时,它基本归结为:
test.update_attributes prop1: 'test', prop2: 'test'
如果test.prop1 = 'test'
test.prop2 = 'test'
test.save
验证失败,我们的save
内存副本仍会包含修改后的test
和prop1
值。因此,我们需要使用prop2
并解决问题(即我们的数据库和内存版本都保持不变)。
tl; dr 在test.reload
电话失败后使用test.reload
。
答案 1 :(得分:0)
尝试将其包装在if语句中:
if test.update(test_params)
# your code here
else
# your code here
end
答案 2 :(得分:0)
这是按设计工作的。例如,update
控制器方法通常如下所示:
def update
@test = Test.find(params[:id])
if @test.update(test_attributes)
# redirect to index with success messsage
else
render :edit
end
private
def test_attributes
# params.require here
end
end
然后 render :edit
将重新显示带有错误消息和填写的错误值的表单,供用户更正。因此,您确实希望在模型实例中提供不正确的值。