即使验证失败,update_attributes也会更改属性

时间:2016-02-03 23:52:49

标签: ruby-on-rails database transactions update-attributes

例如,如果我在test.update_attributes prop1: 'test', prop2: 'test2'prop1具有阻止这些值的验证时运行prop2test.prop1仍然是'test'和{{1仍然是test.prop2。为什么会发生这种情况?我该如何解决?

3 个答案:

答案 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

its source

# 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内存副本仍会包含修改后的testprop1值。因此,我们需要使用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 将重新显示带有错误消息和填写的错误值的表单,供用户更正。因此,您确实希望在模型实例中提供不正确的值。