diff --git a/lib/validates_timeliness.rb b/lib/validates_timeliness.rb index c828446..f1c4a40 100644 --- a/lib/validates_timeliness.rb +++ b/lib/validates_timeliness.rb @@ -1,6 +1,7 @@ require 'validates_timeliness/base' require 'validates_timeliness/attribute_methods' require 'validates_timeliness/validations' +require 'validates_timeliness/validate_timeliness_matcher' ActiveRecord::Base.send(:include, ValidatesTimeliness::Base) ActiveRecord::Base.send(:include, ValidatesTimeliness::AttributeMethods) diff --git a/lib/validates_timeliness/attribute_methods.rb b/lib/validates_timeliness/attribute_methods.rb index d68639d..e17b9ce 100644 --- a/lib/validates_timeliness/attribute_methods.rb +++ b/lib/validates_timeliness/attribute_methods.rb @@ -1,4 +1,4 @@ -# For Rails 2.0.x: +# For Rails 2.0.2: # This module adds method to create reader method for Time attributes # to allow for invalid date checking. If date is invalid then returns nil for # time value. @@ -15,7 +15,7 @@ module ValidatesTimeliness module AttributeMethods def self.included(base) - if Rails::VERSION::STRING < '2.1' + if Rails::VERSION::STRING <= '2.0.2' base.extend ClassMethods::Old else base.extend ClassMethods::New @@ -23,7 +23,7 @@ module ValidatesTimeliness end module ClassMethods - # Rails >= 2.1 + # Rails > 2.0.2 module New def define_read_method_for_time_zone_conversion(attr_name) method_body = <<-EOV @@ -36,7 +36,7 @@ module ValidatesTimeliness elsif time # check invalid date time.to_date rescue time = nil - time = time.in_time_zone if time + time = time.is_a?(String) ? Time.zone.parse(time) : time.to_time rescue time if time end @attributes_cache['#{attr_name}'] = time end @@ -57,7 +57,7 @@ module ValidatesTimeliness end end # New - # Rails < 2.1 + # Rails <= 2.0.2 module Old def define_attribute_methods return if generated_methods? diff --git a/lib/validates_timeliness/validate_timeliness_matcher.rb b/lib/validates_timeliness/validate_timeliness_matcher.rb new file mode 100644 index 0000000..f1214d2 --- /dev/null +++ b/lib/validates_timeliness/validate_timeliness_matcher.rb @@ -0,0 +1,87 @@ +module Spec + module Rails + module Matchers + class ValidateTimeliness + def initialize(attribute, options) + @expected, @options = attribute, options + end + + def matches?(record) + @record = record + + valid = error_matching('2008-02-30', /valid/) && + error_matching('2008-01-01 25:00:00', /valid/) && + no_error_matching('2008-01-01 12:12:12', /valid/) + return false unless valid + + if after = options[:after] + valid = error_matching(after, /after/) && + no_error_matching(after + 1, /after/) + end + return false unless valid + + if before = options[:before] + valid = error_matching(before, /before/) && + no_error_matching(before - 1, /before/) + end + return false unless valid + + if on_or_after = options[:on_or_after] + valid = error_matching(on_or_after -1, /after/) && + no_error_matching(on_or_after, /after/) + end + return false unless valid + + if on_or_before = options[:on_or_before] + valid = error_matching(on_or_before + 1, /before/) && + no_error_matching(on_or_before, /before/) + end + return false unless valid + + return true + end + + def failure_message + "expected model to validate timeliness of #{expected.inspect} with #{last_failure}" + end + + def negative_failure_message + "expected not to validate timeliness of #{expected.inspect}" + end + + def description + "have validated timeliness of #{expected.inspect}" + end + + private + attr_reader :actual, :expected, :record, :options, :last_failure + + def error_matching(value, match) + record.send("#{expected}=", value) + record.valid? + errors = record.errors.on(expected) + pass = case errors + when String + match === errors + when Array + errors.any? {|error| match === error } + else + false + end + @last_failure = "value #{value} to have error matching #{match.inspect}" unless pass + pass + end + + def no_error_matching(value, match) + pass = !error_matching(value, match) + @last_failure = "value #{value} to not have error matching #{match.inspect}" unless pass + pass + end + end + + def validate_timeliness_of(attribute, options={}) + ValidateTimeliness.new(attribute, options) + end + end + end +end diff --git a/spec/attribute_methods_spec.rb b/spec/attribute_methods_spec.rb index 8540a11..de3692f 100644 --- a/spec/attribute_methods_spec.rb +++ b/spec/attribute_methods_spec.rb @@ -22,7 +22,7 @@ describe ValidatesTimeliness::AttributeMethods do @person.birth_date_and_time.should be_kind_of(Time) end - unless Rails::VERSION::STRING < '2.1' + unless Rails::VERSION::STRING <= '2.0.2' it "should return stored time string as Time with correct timezone" do Time.zone = TimeZone['Sydney'] # no I'm not from Sydney but there is no Melbourne timezone! @person.birth_date_and_time = "1980-12-25 01:02:03"