From aa42fb76b62fa7e792a8b25469dee1aae3de72a2 Mon Sep 17 00:00:00 2001 From: Adam Meehan Date: Sun, 30 Nov 2008 08:34:17 +1100 Subject: [PATCH] get the model to add errors to record returned from validation instead of validator --- .../validation_methods.rb | 11 ++-- lib/validates_timeliness/validator.rb | 57 ++++++++++--------- spec/validation_methods_spec.rb | 31 ---------- 3 files changed, 35 insertions(+), 64 deletions(-) diff --git a/lib/validates_timeliness/validation_methods.rb b/lib/validates_timeliness/validation_methods.rb index 0c20605..7410968 100644 --- a/lib/validates_timeliness/validation_methods.rb +++ b/lib/validates_timeliness/validation_methods.rb @@ -67,7 +67,9 @@ module ValidatesTimeliness configuration.delete(:allow_blank) validates_each(attr_names, configuration) do |record, attr_name, value| raw_value = record.send("#{attr_name}_before_type_cast") - validator.evaluate(record, attr_name, raw_value) + validator.call(record, attr_name, raw_value) + errors = validator.errors + add_errors(record, attr_name, errors) unless errors.empty? end end @@ -86,10 +88,9 @@ module ValidatesTimeliness end end - end - - def add_error(attr, message) - + def add_errors(record, attr_name, errors) + errors.each {|e| record.errors.add(attr_name, e) } + end end end diff --git a/lib/validates_timeliness/validator.rb b/lib/validates_timeliness/validator.rb index 566aa42..f9fadac 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_accessor :configuration + attr_accessor :configuration, :errors cattr_accessor :ignore_datetime_restriction_errors cattr_accessor :date_time_error_value_formats @@ -34,50 +34,31 @@ module ValidatesTimeliness defaults = { :on => :save, :type => :datetime, :allow_nil => false, :allow_blank => false } defaults.update(self.class.mapped_default_error_messages) @configuration = defaults.merge(configuration) + @errors = [] end # The main validation method which can be used directly or called through # the other specific type validation methods. - def evaluate(record, attr_name, value) + def call(record, attr_name, value) + @errors = [] return if (value.nil? && configuration[:allow_nil]) || (value.blank? && configuration[:allow_blank]) - record.errors.add(attr_name, configuration[:blank_message]) and return if value.blank? + @errors << configuration[:blank_message] and return if value.blank? begin unless time = record.class.parse_date_time(value, configuration[:type]) - record.errors.add(attr_name, configuration["invalid_#{configuration[:type]}_message".to_sym]) + @errors << configuration["invalid_#{configuration[:type]}_message".to_sym] return end validate_restrictions(record, attr_name, time) rescue Exception => e - record.errors.add(attr_name, configuration["invalid_#{configuration[:type]}_message".to_sym]) + @errors << configuration["invalid_#{configuration[:type]}_message".to_sym] end end private - def self.restriction_value(restriction, record, type) - case restriction - when Time, Date, DateTime - restriction - when Symbol - restriction_value(record.send(restriction), record, type) - when Proc - restriction_value(restriction.call(record), record, type) - else - record.class.parse_date_time(restriction, type, false) - end - end - - def self.restriction_type_cast_method(type) - case type - when :time then :to_dummy_time - when :date then :to_date - when :datetime then :to_time - end - end - # Validate value against the temporal restrictions. Restriction values # maybe of mixed type, so they are evaluated as a common type, which may # require conversion. The type used is defined by validation type. @@ -98,13 +79,33 @@ module ValidatesTimeliness next if compare.nil? compare = compare.send(type_cast_method) - record.errors.add(attr_name, configuration["#{option}_message".to_sym] % compare.strftime(display)) unless value.send(method, compare) + @errors << (configuration["#{option}_message".to_sym] % compare.strftime(display)) unless value.send(method, compare) rescue - record.errors.add(attr_name, "restriction '#{option}' value was invalid") unless self.ignore_datetime_restriction_errors + @errors << "restriction '#{option}' value was invalid" unless self.ignore_datetime_restriction_errors end end end + def self.restriction_value(restriction, record, type) + case restriction + when Time, Date, DateTime + restriction + when Symbol + restriction_value(record.send(restriction), record, type) + when Proc + restriction_value(restriction.call(record), record, type) + else + record.class.parse_date_time(restriction, type, false) + end + end + + def self.restriction_type_cast_method(type) + case type + when :time then :to_dummy_time + when :date then :to_date + when :datetime then :to_time + end + end # Map error message keys to *_message to merge with validation options def self.mapped_default_error_messages returning({}) do |messages| diff --git a/spec/validation_methods_spec.rb b/spec/validation_methods_spec.rb index 781a8f9..eed20f7 100644 --- a/spec/validation_methods_spec.rb +++ b/spec/validation_methods_spec.rb @@ -46,37 +46,6 @@ describe ValidatesTimeliness::ValidationMethods do end end - # describe "timeliness_restriction_value" do - # it "should return Time object when restriction is Time object" do - # restriction_value(Time.now, person, :datetime).should be_kind_of(Time) - # end - # - # it "should return Time object when restriction is string" do - # restriction_value("2007-01-01 12:00", person, :datetime).should be_kind_of(Time) - # end - # - # it "should return Time object when restriction is method symbol which returns Time object" do - # person.stub!(:datetime_attr).and_return(Time.now) - # restriction_value(:datetime_attr, person, :datetime).should be_kind_of(Time) - # end - # - # it "should return Time object when restriction is method symbol which returns string" do - # person.stub!(:datetime_attr).and_return("2007-01-01 12:00") - # restriction_value(:datetime_attr, person, :datetime).should be_kind_of(Time) - # end - # - # it "should return Time object when restriction is proc which returns Time object" do - # restriction_value(lambda { Time.now }, person, :datetime).should be_kind_of(Time) - # end - # - # it "should return Time object when restriction is proc which returns string" do - # restriction_value(lambda {"2007-01-01 12:00"}, person, :datetime).should be_kind_of(Time) - # end - # - # def restriction_value(*args) - # ActiveRecord::Base.send(:timeliness_restriction_value, *args) - # end - # end describe "with no restrictions" do before :all do