From 0c5cc1a536fac86c02446a0a8001af8084607575 Mon Sep 17 00:00:00 2001 From: Adam Meehan Date: Fri, 5 Dec 2008 18:25:44 +1100 Subject: [PATCH] more refactoring of validator fixed bug when Date is restriction value for a datetime attribute so its cast to time in default timezone --- .../rails/matchers/validate_timeliness.rb | 7 ++- .../validation_methods.rb | 3 +- lib/validates_timeliness/validator.rb | 47 ++++++++++++++----- 3 files changed, 39 insertions(+), 18 deletions(-) diff --git a/lib/validates_timeliness/spec/rails/matchers/validate_timeliness.rb b/lib/validates_timeliness/spec/rails/matchers/validate_timeliness.rb index 10c7bad..45d8b6d 100644 --- a/lib/validates_timeliness/spec/rails/matchers/validate_timeliness.rb +++ b/lib/validates_timeliness/spec/rails/matchers/validate_timeliness.rb @@ -12,11 +12,11 @@ module Spec def initialize(attribute, options) @expected, @options = attribute, options + @validator = ValidatesTimeliness::Validator.new(options) compile_error_messages end def compile_error_messages - validator = ValidatesTimeliness::Validator.new(options) messages = validator.send(:error_messages) @messages = messages.inject({}) {|h, (k, v)| h[k] = v.gsub(/ (\%s|\{\{\w*\}\})/, ''); h } end @@ -52,7 +52,7 @@ module Spec end private - attr_reader :actual, :expected, :record, :options, :messages, :last_failure + attr_reader :actual, :expected, :record, :options, :messages, :last_failure, :validator def test_option(option, modifier, settings={}) settings.reverse_merge!(:modify_on => :valid) @@ -71,8 +71,7 @@ module Spec def parse_and_cast(value) value = ValidatesTimeliness::Validator.send(:restriction_value, value, record, options[:type]) - cast_method = ValidatesTimeliness::Validator.send(:restriction_type_cast_method, options[:type]) - value.send(cast_method) rescue nil + validator.send(:type_cast_value, value) end def error_matching(value, match) diff --git a/lib/validates_timeliness/validation_methods.rb b/lib/validates_timeliness/validation_methods.rb index f5e17d0..dc37302 100644 --- a/lib/validates_timeliness/validation_methods.rb +++ b/lib/validates_timeliness/validation_methods.rb @@ -56,8 +56,7 @@ module ValidatesTimeliness configuration.delete(:allow_nil) configuration.delete(:allow_blank) validates_each(attr_names, configuration) do |record, attr_name, value| - raw_value = record.send("#{attr_name}_before_type_cast") - validator.call(record, attr_name, raw_value) + validator.call(record, attr_name) end end diff --git a/lib/validates_timeliness/validator.rb b/lib/validates_timeliness/validator.rb index b18c866..e128176 100644 --- a/lib/validates_timeliness/validator.rb +++ b/lib/validates_timeliness/validator.rb @@ -4,7 +4,7 @@ module ValidatesTimeliness # The validity of values can be restricted to be before or after certain dates # or times. class Validator - attr_reader :configuration, :type, :messages + attr_reader :configuration, :type def initialize(configuration) defaults = { :on => :save, :type => :datetime, :allow_nil => false, :allow_blank => false } @@ -14,19 +14,24 @@ module ValidatesTimeliness # The main validation method which can be used directly or called through # the other specific type validation methods. - def call(record, attr_name, value) - return if (value.nil? && configuration[:allow_nil]) || (value.blank? && configuration[:allow_blank]) + def call(record, attr_name) + value = record.send(attr_name) + raw_value = raw_value(record, attr_name) - add_error(record, attr_name, :blank) and return if value.blank? - - time = record.class.parse_date_time(value, type) - unless time - add_error(record, attr_name, "invalid_#{type}".to_sym) and return - end - validate_restrictions(record, attr_name, time) + return if (raw_value.nil? && configuration[:allow_nil]) || (raw_value.blank? && configuration[:allow_blank]) + + add_error(record, attr_name, :blank) and return if raw_value.blank? + + add_error(record, attr_name, "invalid_#{type}".to_sym) and return unless value + + validate_restrictions(record, attr_name, value) end private + + def raw_value(record, attr_name) + record.send("#{attr_name}_before_type_cast") + end # Validate value against the temporal restrictions. Restriction values # maybe of mixed type, so they are evaluated as a common type, which may @@ -38,14 +43,14 @@ module ValidatesTimeliness display = ValidatesTimeliness.error_value_formats[type] - value = value.send(type_cast_method) + value = type_cast_value(value) restriction_methods.each do |option, method| next unless restriction = configuration[option] begin compare = self.class.restriction_value(restriction, record, type) next if compare.nil? - compare = compare.send(type_cast_method) + compare = type_cast_value(compare) unless value.send(method, compare) add_error(record, attr_name, option, :restriction => compare.strftime(display)) @@ -64,6 +69,7 @@ module ValidatesTimeliness message = message % interpolate.values unless interpolate.empty? record.errors.add(attr_name, message) else + # use i18n support in AR for message or us custom message passed to validation method custom = custom_error_messages[message] record.errors.add(attr_name, custom || message, interpolate) end @@ -100,5 +106,22 @@ module ValidatesTimeliness end end + def type_cast_value(value) + case type + when :time + value.to_dummy_time + when :date + value.to_date + when :datetime + if value.is_a?(DateTime) || value.is_a?(Time) + value.to_time + else + value.to_time(ValidatesTimelines.default_timezone) + end + else + nil + end + end + end end