From fe7310fc104bfbe5a096a006c8d0df9d02e6fea9 Mon Sep 17 00:00:00 2001 From: Adam Meehan Date: Sat, 3 May 2008 08:08:28 +1000 Subject: [PATCH] fixed read method to use value before type cast added AR version checks in specs include AR from vendor if in Rails app --- lib/validates_timeliness/attribute_methods.rb | 25 ++++++++++----- spec/attribute_methods_spec.rb | 31 +++++++++++++------ spec/spec_helper.rb | 9 +++++- 3 files changed, 47 insertions(+), 18 deletions(-) diff --git a/lib/validates_timeliness/attribute_methods.rb b/lib/validates_timeliness/attribute_methods.rb index 99bd3aa..6810c57 100644 --- a/lib/validates_timeliness/attribute_methods.rb +++ b/lib/validates_timeliness/attribute_methods.rb @@ -7,25 +7,34 @@ module ValidatesTimeliness module ClassMethods def define_read_method_for_time_zone_conversion(attr_name) - method_body = <<-EOV + method_body = <<-EOV def #{attr_name}(reload = false) cached = @attributes_cache['#{attr_name}'] return cached if cached && !reload - time = read_attribute('#{attr_name}') - unless time.acts_like?(:time) - time = time.to_time(:local) rescue nil + time = read_attribute_before_type_cast('#{attr_name}') + if time && time.acts_like?(:time) + # Rails 2.0.x compatibility check + time = time.respond_to?(:in_time_zone) ? time.in_time_zone : time + elsif time + # checks date is valid + time.to_date rescue time = nil + time = time.to_time(:local) if time end - @attributes_cache['#{attr_name}'] = time.acts_like?(:time) ? time.in_time_zone : time + @attributes_cache['#{attr_name}'] = time end EOV evaluate_attribute_method attr_name, method_body end + # TODO rails 2.0 time casting better with timezone def define_write_method_for_time_zone_conversion(attr_name) method_body = <<-EOV - def #{attr_name}=(time) - if time - time = time.in_time_zone if time.acts_like?(:time) + def #{attr_name}=(time) + if time && time.respond_to?(:in_time_zone) + time = time.in_time_zone + elsif time && time.acts_like?(:time) + # Rails 2.0.x compatibility + time = @@default_timezone == :utc ? time.to_time : time.to_time end write_attribute(:#{attr_name}, time) end diff --git a/spec/attribute_methods_spec.rb b/spec/attribute_methods_spec.rb index 1be5d79..5275cf5 100644 --- a/spec/attribute_methods_spec.rb +++ b/spec/attribute_methods_spec.rb @@ -23,24 +23,37 @@ describe ValidatesTimeliness::AttributeMethods do end it "should return Time object for attribute_before_type_cast when written as Time" do - @person.birth_date_and_time = time = Time.mktime(1980, 12, 25, 1, 2, 3) - @person.birth_date_and_time_before_type_cast.should == time + @person.birth_date_and_time = Time.mktime(1980, 12, 25, 1, 2, 3) + @person.birth_date_and_time_before_type_cast.should be_kind_of(Time) end it "should return Time object using attribute read method when written with string" do @person.birth_date_and_time = "1980-12-25 01:02:03" - @person.birth_date_and_time.should == Time.mktime(1980, 12, 25, 1, 2, 3) + @person.birth_date_and_time.should be_kind_of(Time) end - it "should read stored time with correct timezone" + if ActiveRecord::VERSION::STRING < '2.1' + it "should return stored time string as Time with correct timezone" do + @person.birth_date_and_time = "1980-12-25 01:02:03" + @person.birth_date_and_time.zone == Time.new.zone + end + end - it "should return nil when date is invalid" + unless ActiveRecord::VERSION::STRING < '2.1' + it "should return stored time string as Time with correct timezone" do + @person.birth_date_and_time = "1980-12-25 01:02:03" + @person.birth_date_and_time.zone == Time.zone + end + end + + it "should return nil when time is invalid" do + @person.birth_date_and_time = "1980-02-30 01:02:03" + @person.birth_date_and_time.should be_nil + end end describe "for Date columns" do before do - Person.define_read_method_for_time_zone_conversion(:birth_date) - Person.define_write_method_for_time_zone_conversion(:birth_date) @person = Person.new end @@ -59,12 +72,12 @@ describe ValidatesTimeliness::AttributeMethods do it "should return Date object for attribute_before_type_cast when written as Date" do @person.birth_date = date = Date.new(1980, 12, 25) - @person.birth_date_before_type_cast.should == date + @person.birth_date_before_type_cast.should be_kind_of(Date) end it "should return Date object using attribute read method when written with string" do @person.birth_date = "1980-12-25" - @person.birth_date.should == Date.new(1980, 12, 25) + @person.birth_date.should be_kind_of(Date) end it "should read stored time with correct timezone" diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 1ab5e8a..e1445f4 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -2,7 +2,14 @@ $: << File.dirname(__FILE__) + '/../lib' << File.dirname(__FILE__) require 'rubygems' require 'spec' -require 'active_record' + +if File.exists?(File.dirname(__FILE__) + '/../../../rails') + require 'activerecord/lib/active_record' + require 'activerecord/lib/active_record/version' +else + require 'active_record' + require 'active_record/version' +end require 'validates_timeliness'