报告记录validation警告和错误的有效方法?

我有一个Rails项目,就像在大多数应用程序中一样,我们有许多硬性和快速的validation规则,所有对象在持久化之前必须符合这些规则。 当然,ActiveModel的Validations是完美的 – 我们使用Rails默认值和我们自己的手动validation的组合。

但是,我们越来越多地反对用例,我们希望提醒用户注意这样的情况:尽管他们的数据在最严格的意义上是无效的,但是有些元素应该审查,但哪些不应该本身可以防止记录持久性发生。 几个例子,我的头顶:

  • 已经在所有CAPS中提交了一个post标题,这可能是有效的,但可能不是
  • 一个正文文本比一个建议的单词数量少于或多于x个单词

validation模块对于我们如何处理validation错误是一个很好的比喻 – 并且有很多匹配器已经可用 – 理想情况下我希望能够重用该基本代码,但是生成一系列warnings项和errors 。 这将使我们能够以不同的方式突出显示这些案例,而不是暗示可能违反房屋风格等同于更严重,严格执行的规则。

我查看了诸如activemodel-warnings之类的 gem,但是它们通过改变在validation记录时检查哪些匹配器,相应地扩展或缩小errors集合来工作。 同样地,我查看了内置:on参数以进行validation,看看我是否可以手动滚动,但是所有违规都会在错误集合中结束,而不是分开。

有没有人尝试过类似的东西? 我无法想象我是唯一一个想要实现这一目标的人,但我现在正在画一个空白……

下面是我为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) 

顶部的评论显示了如何使用它。 您可以将此代码放入初始化程序中,然后警告应该可用于所有ActiveRecord对象。 然后基本上只是添加一个warnings do阻止每个模型的顶部可以有警告,只需手动添加任意数量的警告。 在您调用.sensible?之前,此块不会被执行.sensible? 在模型上。

另请注意,由于警告不是validation错误,因此即使模型不“合理”(我称之为模型),模型在技术上仍然有效。