diff --git a/lib/validates_timeliness/conversion.rb b/lib/validates_timeliness/conversion.rb index d6f30d6..b4b707c 100644 --- a/lib/validates_timeliness/conversion.rb +++ b/lib/validates_timeliness/conversion.rb @@ -2,6 +2,9 @@ module ValidatesTimeliness module Conversion def type_cast_value(value, type) + return nil if value.nil? + + value.in_time_zone if value.acts_like?(:time) && @timezone_aware value = case type when :time dummy_time(value) @@ -10,8 +13,6 @@ module ValidatesTimeliness when :datetime value.to_time end - rescue - nil end def dummy_time(value) @@ -20,30 +21,25 @@ module ValidatesTimeliness else [0,0,0] end - Time.send(ValidatesTimeliness.default_timezone, *(ValidatesTimeliness.dummy_date_for_time_type + time)) + values = ValidatesTimeliness.dummy_date_for_time_type + time + @timezone_aware ? Time.zone.local(*values) : Time.send(ValidatesTimeliness.default_timezone, *values) end - def evaluate_option_value(value, record, timezone_aware=false) + def evaluate_option_value(value, record) case value - when Time - timezone_aware ? value.in_time_zone : value - when Date + when Time, Date value when String - if ValidatesTimeliness.use_plugin_parser - ValidatesTimeliness::Parser.parse(value, :datetime, :timezone_aware => timezone_aware, :strict => false) - else - timezone_aware ? Time.zone.parse(value) : value.to_time(ValidatesTimeliness.default_timezone) - end + parse(value) when Symbol if !record.respond_to?(value) && restriction_shorthand?(value) ValidatesTimeliness.restriction_shorthand_symbols[value].call else - evaluate_option_value(record.send(value), record, timezone_aware) + evaluate_option_value(record.send(value), record) end when Proc result = value.arity > 0 ? value.call(record) : value.call - evaluate_option_value(result, record, timezone_aware) + evaluate_option_value(result, record) else value end @@ -53,5 +49,15 @@ module ValidatesTimeliness ValidatesTimeliness.restriction_shorthand_symbols.keys.include?(symbol) end + def parse(value) + if ValidatesTimeliness.use_plugin_parser + ValidatesTimeliness::Parser.parse(value, @type, :timezone_aware => @timezone_aware, :strict => false) + else + @timezone_aware ? Time.zone.parse(value) : value.to_time(ValidatesTimeliness.default_timezone) + end + rescue ArgumentError, TypeError + nil + end + end end diff --git a/lib/validates_timeliness/validator.rb b/lib/validates_timeliness/validator.rb index 597e781..dc01181 100644 --- a/lib/validates_timeliness/validator.rb +++ b/lib/validates_timeliness/validator.rb @@ -38,17 +38,19 @@ module ValidatesTimeliness end def validate_each(record, attr_name, value) - raw_value = attribute_raw_value(record, attr_name) || value + raw_value = record._timeliness_raw_value_for(attr_name) || value return if (@allow_nil && raw_value.nil?) || (@allow_blank && raw_value.blank?) - timezone_aware = record.class.timeliness_attribute_timezone_aware?(attr_name) - value = type_cast(value) + @timezone_aware = record.class.timeliness_attribute_timezone_aware?(attr_name) + value = parse(value) if value.is_a?(String) + value = type_cast_value(value, @type) return record.errors.add(attr_name, :"invalid_#{@type}") if value.blank? @restrictions_to_check.each do |restriction| begin - restriction_value = type_cast(evaluate_option_value(options[restriction], record, timezone_aware)) + restriction_value = type_cast_value(evaluate_option_value(options[restriction], record), @type) + unless value.send(RESTRICTIONS[restriction], restriction_value) return record.errors.add(attr_name, restriction, :message => options[:"#{restriction}_message"], :restriction => format_error_value(restriction_value)) end @@ -60,18 +62,11 @@ module ValidatesTimeliness end end - def attribute_raw_value(record, attr_name) - record._timeliness_raw_value_for(attr_name) - end - - def type_cast(value) - type_cast_value(value, @type) - end - def format_error_value(value) format = I18n.t(@type, :scope => 'validates_timeliness.error_value_formats') value.strftime(format) end + end end diff --git a/spec/validates_timeliness/conversion_spec.rb b/spec/validates_timeliness/conversion_spec.rb index 81449a3..fffc4d6 100644 --- a/spec/validates_timeliness/conversion_spec.rb +++ b/spec/validates_timeliness/conversion_spec.rb @@ -126,8 +126,9 @@ describe ValidatesTimeliness::Conversion do end it 'should return Time value is current zone from string time value if timezone aware' do + @timezone_aware = true value = '2010-01-01 12:00:00' - evaluate_option_value(value, person, true).should == Time.zone.local(2010,1,1,12,0,0) + evaluate_option_value(value, person).should == Time.zone.local(2010,1,1,12,0,0) end it 'should return Time value in default zone from proc which returns string time' do @@ -142,9 +143,10 @@ describe ValidatesTimeliness::Conversion do end it 'should return Time value in current zone attribute method symbol which returns string time value if timezone aware' do + @timezone_aware = true value = '2010-01-01 12:00:00' person.birth_time = value - evaluate_option_value(:birth_time, person, true).should == Time.zone.local(2010,1,1,12,0,0) + evaluate_option_value(:birth_time, person).should == Time.zone.local(2010,1,1,12,0,0) end context "restriction shorthand" do