Ответ 1
Вот код, который я написал для проекта 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?
на модели.
Также обратите внимание, что поскольку предупреждения не являются ошибками проверки, модель все равно будет технически обоснованной, даже если она не "разумна" (как я ее называл).