【问题标题】:Can you reset an ActiveRecord instance if its validation fails?如果验证失败,您可以重置 ActiveRecord 实例吗?
【发布时间】:2014-11-08 20:21:38
【问题描述】:

假设您的用户的年龄属性不能为负数

class User < ActiveRecord::Base
  validates :age, numericality: { greater_than: 0 }
end

如果您尝试将属性更新为负数,验证将失败,但实例仍将具有负年龄值

#<User id: 1, age: 5, created_at: "2014-11-08 20:14:12", updated_at: "2014-11-08 20:14:12">
user.update_attributes!(:age => -5)
#<User id: 1, age: -5, created_at: "2014-11-08 20:14:12", updated_at: "2014-11-08 20:14:12">

除了捕获 ActiveRecord::RecordInvalid 并自己重置值之外,如果验证失败,他们还可以重置实例?

谢谢!

【问题讨论】:

    标签: ruby-on-rails ruby validation rails-activerecord


    【解决方案1】:

    如果验证失败,您可以致电model.reload。所以它看起来像:

    if @model.update_attributes(age: params[:age]) # params[:age] = -5 for example
      # model is valid and saved, continue...
    else # update_attributes return false and will not raise an exception if model is invalid
      # model is invalid, reloading...
      @model.reload
      # if we call @model.age now, it will return previous value
    end
    

    无论如何,即使模型在更新后变得无效,update_attributes 也会设置属性,尽管它不会将无效属性保存到数据库。但请记住,它会重置可能已在此调用中执行的所有其他更改,因此update_attributes(name: params[:name], age: params[age]) 将重置名称和年龄,即使名称是有效的。

    【讨论】:

      【解决方案2】:

      我会说你需要一个自定义验证器,例如:

      class MyValidator < ActiveModel::Validator
      
        def validate(record)
          unless record.age.to_i > 0
            record.errors[:name] << 'Invalid!'
            record.age = record.age_was # Rewrite new with old value
          end
        end
      end
      
      class Person
        include ActiveModel::Validations
        validates_with MyValidator
      end
      

      使用ActiveModel::Dirty 无需重新加载。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-06-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-21
        • 2011-05-06
        • 1970-01-01
        相关资源
        最近更新 更多