ActiveRecord - 用警告替换模型验证错误

时间:2010-07-27 09:58:29

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

我希望能够在rails中保存/更新模型时用警告替换字段错误。基本上我想只是编写一个包装器,围绕验证方法生成错误,保存模型,也许可以在警告哈希中使用(就像错误哈希一样):

class Person < ActiveRecord::Base
  # normal validation
  validates_presence_of :name

  # validation with warning
  validates_numericality_of :age, 
                            :only_integer => true, 
                            :warning => true # <-- only warn
end

>>> p = Person.new(:name => 'john', :age => 2.2)
>>> p.save
=> true # <-- able to save to db
>>> p.warnings.map { |field, message| "#{field} - #{message}" }
["age - is not a number"] # <-- have access to warning content

知道如何实现这个吗?我能够将:warning => false默认值添加到ActiveRecord::Validations::ClassMethods::DEFAULT_VALIDATION_OPTIONS 通过扩展模块,但我正在寻找有关如何实现其余部分的一些见解。感谢。

3 个答案:

答案 0 :(得分:5)

validation_scopes gem使用了一些不错的元编程魔法来为你提供验证的所有常用功能以及除object.errors之外的上下文中的ActiveRecord :: Errors对象。

例如,您可以说:

validation_scope :warnings do |s|
  s.validates_presence_of :some_attr
end

上面的验证将像往常一样在object.valid?上触发,但如果some_attr不存在,则不会阻止对object.save上的数据库的保存。任何关联的ActiveRecord :: Errors对象都可以在object.warnings中找到。

以通常方式指定的没有作用域的验证仍将按预期运行,阻止数据库保存并将错误对象分配给object.errors。

作者简要介绍了宝石的发展on his blog

答案 1 :(得分:4)

我不知道它是否已准备好用于Rails 3,但此插件可以满足您的需求:

http://softvalidations.rubyforge.org/

编辑添加:

要使用ActiveModel更新此基本功能,我想出了以下内容:

#/config/initializer/soft_validate.rb:
module ActiveRecord
  class Base
    def warnings
      @warnings ||= ActiveModel::Errors.new(self)
    end
    def complete?
      warnings.clear
      valid?
      warnings.empty?
    end
  end
end

#/lib/soft_validate_validator.rb
class SoftValidateValidator < ActiveModel::EachValidator
  def validate(record)
    record.warnings.add_on_blank(attributes, options)
  end
end

它添加了一个新的错误类似对象 warnings 和一个帮助方法完成?,你可以将它添加到这样的模型中:

class FollowupReport < ActiveRecord::Base
  validates :suggestions, :soft_validate => true
end

答案 2 :(得分:1)

我制作了自己的宝石来解决Rails 4.1+的问题:https://github.com/s12chung/active_warnings

class BasicModel
  include ActiveWarnings

  attr_accessor :name
  def initialize(name); @name = name; end

  warnings do
    validates :name, absence: true
  end
end

model = BasicModel.new("some_name")
model.safe? # .invalid? equivalent, but for warnings
model.warnings # .errors equivalent