lib/validates_timeliness/validator.rb in adzap-validates_timeliness-1.1.7 vs lib/validates_timeliness/validator.rb in adzap-validates_timeliness-2.0.0
- old
+ new
@@ -1,17 +1,10 @@
module ValidatesTimeliness
class Validator
cattr_accessor :ignore_restriction_errors
- cattr_accessor :error_value_formats
-
self.ignore_restriction_errors = false
- self.error_value_formats = {
- :time => '%H:%M:%S',
- :date => '%Y-%m-%d',
- :datetime => '%Y-%m-%d %H:%M:%S'
- }
RESTRICTION_METHODS = {
:equal_to => :==,
:before => :<,
:after => :>,
@@ -19,12 +12,12 @@
:on_or_after => :>=,
:between => lambda {|v, r| (r.first..r.last).include?(v) }
}
VALID_OPTIONS = [
- :on, :if, :unless, :allow_nil, :empty, :allow_blank, :blank,
- :with_time, :with_date, :ignore_usec,
+ :on, :if, :unless, :allow_nil, :empty, :allow_blank,
+ :with_time, :with_date, :ignore_usec, :format,
:invalid_time_message, :invalid_date_message, :invalid_datetime_message
] + RESTRICTION_METHODS.keys.map {|option| [option, "#{option}_message".to_sym] }.flatten
attr_reader :configuration, :type
@@ -34,44 +27,58 @@
@type = @configuration.delete(:type)
validate_options(@configuration)
end
def call(record, attr_name, value)
- value = record.class.parse_date_time(value, type, false) if value.is_a?(String)
raw_value = raw_value(record, attr_name) || value
+ if value.is_a?(String) || configuration[:format]
+ strict = !configuration[:format].nil?
+ value = ValidatesTimeliness::Parser.parse(raw_value, type, :strict => strict, :format => configuration[:format])
+ end
+
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
+ if raw_value.blank?
+ add_error(record, attr_name, :blank)
+ return
+ end
+ if value.nil?
+ add_error(record, attr_name, "invalid_#{type}".to_sym)
+ return
+ end
+
validate_restrictions(record, attr_name, value)
end
-
+
+ def error_messages
+ @error_messages ||= self.class.default_error_messages.merge(custom_error_messages)
+ end
+
private
def raw_value(record, attr_name)
record.send("#{attr_name}_before_type_cast") rescue nil
end
def validate_restrictions(record, attr_name, value)
- value = if @configuration[:with_time] || @configuration[:with_date]
+ value = if configuration[:with_time] || configuration[:with_date]
restriction_type = :datetime
combine_date_and_time(value, record)
else
restriction_type = type
- self.class.type_cast_value(value, type, @configuration[:ignore_usec])
+ self.class.type_cast_value(value, type, configuration[:ignore_usec])
end
return if value.nil?
RESTRICTION_METHODS.each do |option, method|
next unless restriction = configuration[option]
begin
restriction = self.class.evaluate_option_value(restriction, restriction_type, record)
next if restriction.nil?
- restriction = self.class.type_cast_value(restriction, restriction_type, @configuration[:ignore_usec])
+ restriction = self.class.type_cast_value(restriction, restriction_type, configuration[:ignore_usec])
unless evaluate_restriction(restriction, value, method)
add_error(record, attr_name, option, interpolation_values(option, restriction))
end
rescue
@@ -85,11 +92,11 @@
def interpolation_values(option, restriction)
format = self.class.error_value_formats[type]
restriction = [restriction] unless restriction.is_a?(Array)
if defined?(I18n)
- message = custom_error_messages[option] || I18n.translate('activerecord.errors.messages')[option]
+ message = custom_error_messages[option] || I18n.t('activerecord.errors.messages')[option]
subs = message.scan(/\{\{([^\}]*)\}\}/)
interpolations = {}
subs.each_with_index {|s, i| interpolations[s[0].to_sym] = restriction[i].strftime(format) }
interpolations
else
@@ -108,70 +115,85 @@
end
end
def add_error(record, attr_name, message, interpolate=nil)
if defined?(I18n)
- # use i18n support in AR for message or use custom message passed to validation method
custom = custom_error_messages[message]
record.errors.add(attr_name, custom || message, interpolate || {})
else
message = error_messages[message] if message.is_a?(Symbol)
message = message % interpolate
record.errors.add(attr_name, message)
end
end
- def error_messages
- @error_messages ||= ValidatesTimeliness.default_error_messages.merge(custom_error_messages)
- end
-
def custom_error_messages
@custom_error_messages ||= configuration.inject({}) {|msgs, (k, v)|
if md = /(.*)_message$/.match(k.to_s)
msgs[md[1].to_sym] = v
end
msgs
}
end
-
+
def combine_date_and_time(value, record)
if type == :date
date = value
- time = @configuration[:with_time]
+ time = configuration[:with_time]
else
- date = @configuration[:with_date]
+ date = configuration[:with_date]
time = value
end
date, time = self.class.evaluate_option_value(date, :date, record), self.class.evaluate_option_value(time, :time, record)
return if date.nil? || time.nil?
- record.class.send(:make_time, [date.year, date.month, date.day, time.hour, time.min, time.sec, time.usec])
+ ValidatesTimeliness::Parser.make_time([date.year, date.month, date.day, time.hour, time.min, time.sec, time.usec])
end
def validate_options(options)
- invalid_for_type = ([:time, :date, :datetime] - [@type]).map {|k| "invalid_#{k}_message".to_sym }
- invalid_for_type << :with_date unless @type == :time
- invalid_for_type << :with_time unless @type == :date
+ invalid_for_type = ([:time, :date, :datetime] - [type]).map {|k| "invalid_#{k}_message".to_sym }
+ invalid_for_type << :with_date unless type == :time
+ invalid_for_type << :with_time unless type == :date
options.assert_valid_keys(VALID_OPTIONS - invalid_for_type)
end
# class methods
class << self
+ def default_error_messages
+ if defined?(I18n)
+ I18n.t('activerecord.errors.messages')
+ else
+ ::ActiveRecord::Errors.default_error_messages
+ end
+ end
+
+ def error_value_formats
+ if defined?(I18n)
+ I18n.t('validates_timeliness.error_value_formats')
+ else
+ @@error_value_formats
+ end
+ end
+
+ def error_value_formats=(formats)
+ @@error_value_formats = formats
+ end
+
def evaluate_option_value(value, type, record)
case value
- when Time, Date, DateTime
+ when Time, Date
value
when Symbol
evaluate_option_value(record.send(value), type, record)
when Proc
evaluate_option_value(value.call(record), type, record)
when Array
value.map {|r| evaluate_option_value(r, type, record) }.sort
when Range
evaluate_option_value([value.first, value.last], type, record)
else
- record.class.parse_date_time(value, type, false)
+ ValidatesTimeliness::Parser.parse(value, type, :strict => false)
end
end
def type_cast_value(value, type, ignore_usec=false)
if value.is_a?(Array)
@@ -190,10 +212,10 @@
end
else
nil
end
if ignore_usec && value.is_a?(Time)
- ::ActiveRecord::Base.send(:make_time, Array(value).reverse[4..9])
+ ValidatesTimeliness::Parser.make_time(Array(value).reverse[4..9])
else
value
end
end
end