diff --git a/lib/validates_timeliness/validator.rb b/lib/validates_timeliness/validator.rb index fcd3c6b..a49654e 100644 --- a/lib/validates_timeliness/validator.rb +++ b/lib/validates_timeliness/validator.rb @@ -21,6 +21,8 @@ class Validator < ActiveModel::EachValidator RESTRICTION_ERROR_MESSAGE = "Error occurred validating %s for %s restriction:\n%s" + RESERVED_OPTIONS = RESTRICTIONS.keys + RESTRICTIONS.keys.map { |option| :"#{option}_message" } + def self.kind :timeliness end @@ -72,7 +74,7 @@ def validate_restrictions(record, attr_name, value) begin restriction_value = @converter.type_cast_value(@converter.evaluate(options[restriction], record)) unless value.send(RESTRICTIONS[restriction], restriction_value) - add_error(record, attr_name, restriction, restriction_value) and break + add_error(record, attr_name, restriction, value: value, restriction_value: restriction_value) and break end rescue => e unless ValidatesTimeliness.ignore_restriction_errors @@ -83,13 +85,20 @@ def validate_restrictions(record, attr_name, value) end end - def add_error(record, attr_name, message, value=nil) - value = format_error_value(value) if value - message_options = { message: options.fetch(:"#{message}_message", options[:message]), restriction: value } - record.errors.add(attr_name, message, **message_options) + def add_error(record, attr_name, message, restriction_value: nil, value: nil) + error_options = options.except(*RESERVED_OPTIONS).merge!( + restriction: format_error_value(restriction_value), + value: value + ) + + message_text = options[:"#{message}_message"] + error_options[:message] = message_text if message_text.present? + + record.errors.add(attr_name, message, **error_options) end def format_error_value(value) + return unless value format = I18n.t(@type, default: DEFAULT_ERROR_VALUE_FORMATS[@type], scope: 'validates_timeliness.error_value_formats') value.strftime(format) end diff --git a/spec/validates_timeliness/validator_spec.rb b/spec/validates_timeliness/validator_spec.rb index c016d31..4df2290 100644 --- a/spec/validates_timeliness/validator_spec.rb +++ b/spec/validates_timeliness/validator_spec.rb @@ -185,6 +185,26 @@ class PersonWithFormatOption end end + describe "custom option" do + it "should pass custom options to the error" do + Person.validates_datetime :birth_datetime, :on_or_before => Time.utc(2010,1,2,3,4,5), :custom => 'option' + + with_each_model_value(:birth_datetime, Time.utc(2010,1,2,3,4,5,10000), Person) do |record, value| + expect(record).to_not be_valid + expect(record.errors.where(:birth_datetime).first.options).to include(custom: 'option') + end + end + + it "should not pass config options to the error" do + Person.validates_datetime :birth_datetime, :on_or_before => Time.utc(2010,1,2,3,4,5), :custom => 'option' + + with_each_model_value(:birth_datetime, Time.utc(2010,1,2,3,4,5,10000), Person) do |record, value| + expect(record).to_not be_valid + expect(record.errors.where(:birth_datetime).first.options.keys).to_not include(:on_or_before) + end + end + end + describe "restriction value errors" do let(:person) { Person.new(:birth_date => Date.today) }