Sco*_*man 18 validation ruby-on-rails activemodel
我有一个Rails项目,就像在大多数应用程序中一样,我们有许多硬性和快速的验证规则,所有对象在持久化之前必须符合这些规则.当然,ActiveModel的Validations是完美的 - 我们使用Rails默认值和我们自己的手动验证的组合.
但是,我们越来越多地反对用例,我们希望提醒用户注意这样的情况:尽管他们的数据在最严格的意义上是无效的,但是他们应该审查哪些元素,但哪些不应该本身可防止记录持久性发生.几个例子,在我的头顶:
验证模块是我们如何处理验证错误的一个很好的比喻 - 并且有很多匹配器已经可用 - 理想情况下我希望能够重用该基本代码,但同时生成一组warnings
项目errors
.这将使我们能够以不同的方式突出显示这些案例,而不是暗示可能违反房屋风格等同于更严重,严格执行的规则.
我查看了诸如activemodel-warnings之类的 gem ,但它们通过改变在验证记录时检查哪些匹配器,相应地扩展或缩小errors
集合来工作.类似地,我查看:on
了验证的内置参数,看看我是否可以手动滚动,但是所有违规都会在错误集合中结束而不是分离出来.
有没有人尝试过类似的东西?我无法想象我是唯一一个想要实现这一目标的人,但我现在正在画一个空白......
pdo*_*obb 15
以下是我为Rails 3项目编写的一些代码,它完全符合您在这里所说的内容.
# Define a "warnings" validation bucket on ActiveRecord objects.
#
# @example
#
# class MyObject < ActiveRecord::Base
# warning do |vehicle_asset|
# unless vehicle_asset.description == 'bob'
# vehicle_asset.warnings.add(:description, "should be 'bob'")
# end
# end
# end
#
# THEN:
#
# my_object = MyObject.new
# my_object.description = 'Fred'
# my_object.sensible? # => false
# my_object.warnings.full_messages # => ["Description should be 'bob'"]
module Warnings
module Validations
extend ActiveSupport::Concern
include ActiveSupport::Callbacks
included do
define_callbacks :warning
end
module ClassMethods
def warning(*args, &block)
options = args.extract_options!
if options.key?(:on)
options = options.dup
options[:if] = Array.wrap(options[:if])
options[:if] << "validation_context == :#{options[:on]}"
end
args << options
set_callback(:warning, *args, &block)
end
end
# Similar to ActiveModel::Validations#valid? but for warnings
def sensible?
warnings.clear
run_callbacks :warning
warnings.empty?
end
# Similar to ActiveModel::Validations#errors but returns a warnings collection
def warnings
@warnings ||= ActiveModel::Errors.new(self)
end
end
end
ActiveRecord::Base.send(:include, Warnings::Validations)
Run Code Online (Sandbox Code Playgroud)
顶部的评论显示了如何使用它.您可以将此代码放入初始化程序中,然后警告应该可用于所有ActiveRecord对象.然后基本上只需warnings do
在每个模型的顶部添加一个可以发出警告的块,然后手动添加任意数量的警告.在调用.sensible?
模型之前,不会执行此块.
另请注意,由于警告不是验证错误,因此即使模型不"合理"(我称之为模型),模型在技术上仍然有效.
几年后,但在较新的 Rails 版本中,有一种更简单的方法:
attr_accessor :save_despite_warnings
def warnings
@warnings ||= ActiveModel::Errors.new(self)
end
before_save :check_for_warnings
def check_for_warnings
warnings.add(:notes, :too_long, count: 120) if notes.to_s.length > 120
!!save_despite_warnings
end
Run Code Online (Sandbox Code Playgroud)
然后你可以这样做:record.warnings.full_messages