more refactoring of validator

fixed bug when Date is restriction value for a datetime attribute so its cast to time in default timezone
This commit is contained in:
Adam Meehan 2008-12-05 18:25:44 +11:00
parent c224db7af8
commit 0c5cc1a536
3 changed files with 39 additions and 18 deletions

View File

@ -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)

View File

@ -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

View File

@ -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