A fix for ActiveRecord 3.1.x and plugin parser not working together (issue #52)

This commit is contained in:
Adam Meehan 2012-01-26 22:44:01 +11:00
parent f5e2deeb73
commit f8aeeca0a9
5 changed files with 60 additions and 14 deletions

View File

@ -2,9 +2,9 @@ source 'http://rubygems.org'
gemspec
gem 'rails', '3.1.0'
gem 'rspec', '~> 2.6'
gem 'rspec-rails', '~> 2.6'
gem 'rails', '3.1.3'
gem 'rspec', '~> 2.8'
gem 'rspec-rails', '~> 2.8'
gem 'timecop'
gem 'rspec_tag_matchers'
gem 'ruby-debug', :platforms => [:ruby_18, :jruby]

View File

@ -33,11 +33,13 @@ module ValidatesTimeliness
def define_timeliness_write_method(attr_name)
method_body, line = <<-EOV, __LINE__ + 1
def #{attr_name}=(value)
original_value = value
@timeliness_cache ||= {}
@timeliness_cache["#{attr_name}"] = value
@timeliness_cache["#{attr_name}"] = original_value
#{ "if value.is_a?(String)\n#{timeliness_type_cast_code(attr_name, 'value')}\nend" if ValidatesTimeliness.use_plugin_parser }
super
super(value)
end
EOV
generated_timeliness_methods.module_eval(method_body, __FILE__, line)

View File

@ -3,12 +3,40 @@ module ValidatesTimeliness
module ActiveRecord
extend ActiveSupport::Concern
def self.use_plugin_cache?
::ActiveRecord::VERSION::STRING < '3.1.0'
end
included do
unless ValidatesTimeliness::ORM::ActiveRecord.use_plugin_cache?
# Just use the built-in before_type_cast retrieval
alias_method :_timeliness_raw_value_for, :read_attribute_before_type_cast
end
end
module ClassMethods
def define_attribute_methods
super
# Define write method and before_type_cast method
use_before_type_cast = ::ActiveRecord::VERSION::STRING < '3.1.0'
define_timeliness_methods(use_before_type_cast)
use_before_type_cast = ValidatesTimeliness::ORM::ActiveRecord.use_plugin_cache?
if use_before_type_cast || ValidatesTimeliness.use_plugin_parser
define_timeliness_methods(use_before_type_cast)
end
end
# ActiveRecord >= 3.1.x has correct before_type_cast implementation to support plugin, except parser
unless ValidatesTimeliness::ORM::ActiveRecord.use_plugin_cache?
def define_timeliness_write_method(attr_name)
method_body, line = <<-EOV, __LINE__ + 1
def #{attr_name}=(value)
original_value = value
if original_value.is_a?(String)\n#{timeliness_type_cast_code(attr_name, 'value')}\nend
super(value)
@attributes['#{attr_name}'] = original_value
end
EOV
generated_timeliness_methods.module_eval(method_body, __FILE__, line)
end
end
def timeliness_attribute_timezone_aware?(attr_name)
@ -30,10 +58,14 @@ module ValidatesTimeliness
end
end
def reload(*args)
_clear_timeliness_cache
super
# ActiveRecord >= 3.1.x needs no cached cleared
if use_plugin_cache?
def reload(*args)
_clear_timeliness_cache
super
end
end
end
end
end

View File

@ -31,7 +31,7 @@ describe ValidatesTimeliness::AttributeMethods do
it 'should cache attribute raw value' do
r = PersonWithCache.new
r.birth_datetime = date_string = '2010-01-01'
r._timeliness_raw_value_for(:birth_datetime).should == date_string
r._timeliness_raw_value_for('birth_datetime').should == date_string
end
it 'should not overwrite user defined methods' do

View File

@ -29,7 +29,7 @@ describe ValidatesTimeliness, 'ActiveRecord' do
it 'should cache attribute raw value' do
r = EmployeeWithCache.new
r.birth_datetime = date_string = '2010-01-01'
r._timeliness_raw_value_for(:birth_datetime).should == date_string
r._timeliness_raw_value_for('birth_datetime').should == date_string
end
context "with plugin parser" do
@ -83,7 +83,7 @@ describe ValidatesTimeliness, 'ActiveRecord' do
r.birth_date = '2010-01-01'
r.reload
r._timeliness_raw_value_for(:birth_date).should be_nil
r._timeliness_raw_value_for('birth_date').should be_nil
end
end
@ -106,5 +106,17 @@ describe ValidatesTimeliness, 'ActiveRecord' do
r = Employee.last
r.birth_datetime_before_type_cast.should match(/2010-01-01 00:00:00/)
end
context "with plugin parser" do
with_config(:use_plugin_parser, true)
it 'should return original value' do
r = Employee.new
r.birth_datetime = date_string = '2010-01-31'
r.birth_datetime_before_type_cast.should == date_string
end
end
end
end