diff --git a/lib/validates_timeliness/validator.rb b/lib/validates_timeliness/validator.rb index f5a87a2d..5c99da31 100644 --- a/lib/validates_timeliness/validator.rb +++ b/lib/validates_timeliness/validator.rb @@ -3,7 +3,7 @@ module ValidatesTimeliness class Validator < ActiveModel::EachValidator - attr_reader :type, :attributes, :converter + attr_reader :type, :attributes RESTRICTIONS = { :is_at => :==, @@ -59,20 +59,20 @@ def validate_each(record, attr_name, value) raw_value = attribute_raw_value(record, attr_name) || value return if (@allow_nil && raw_value.nil?) || (@allow_blank && raw_value.blank?) - @converter = initialize_converter(record, attr_name) + converter = initialize_converter(record, attr_name) - value = @converter.parse(raw_value) if value.is_a?(String) || options[:format] - value = @converter.type_cast_value(value) + value = converter.parse(raw_value) if value.is_a?(String) || options[:format] + value = converter.type_cast_value(value) add_error(record, attr_name, :"invalid_#{@type}") and return if value.blank? - validate_restrictions(record, attr_name, value) + validate_restrictions(record, attr_name, value, converter) end - def validate_restrictions(record, attr_name, value) + def validate_restrictions(record, attr_name, value, converter) @restrictions_to_check.each do |restriction| begin - restriction_value = @converter.type_cast_value(@converter.evaluate(options[restriction], record)) + restriction_value = converter.type_cast_value(converter.evaluate(options[restriction], record)) unless value.send(RESTRICTIONS[restriction], restriction_value) add_error(record, attr_name, restriction, value: value, restriction_value: restriction_value) and break end diff --git a/spec/validates_timeliness/validator_spec.rb b/spec/validates_timeliness/validator_spec.rb index 4df22905..c7699111 100644 --- a/spec/validates_timeliness/validator_spec.rb +++ b/spec/validates_timeliness/validator_spec.rb @@ -43,6 +43,24 @@ expect(record.errors[:birth_date].first).to eq('is not a valid date') end + it 'should keep converters separate when validations overlap' do + Person.validates_datetime :birth_datetime, :birth_time, before: '2010-01-01 12:00:00', allow_nil: true + allow(Person).to receive(:skip_time_zone_conversion_for_attributes).and_return([:birth_time]) + + local_record = Person.new(birth_datetime: Time.utc(2010,1,1,11)) + utc_record = Person.new(birth_time: Time.utc(2010,1,1,11)) + validator = Person.validators.first + + allow(validator).to receive(:validate_restrictions).and_wrap_original do |original, record, *args| + if record.equal?(local_record) + expect(Thread.new { utc_record.valid? }.value).to eq(true) + end + original.call(record, *args) + end + + expect(local_record).not_to be_valid + end + describe ":allow_nil option" do it 'should not allow nil by default' do Person.validates_date :birth_date