Changed multiparameter implementation to be more like AR 3.1 but backwards compatible

Specs improved to not make direct call to multiparameter method.
This commit is contained in:
Adam Meehan 2012-02-02 09:00:05 +11:00
parent 64a7440de4
commit 43f49076fb
2 changed files with 40 additions and 63 deletions

View File

@ -8,7 +8,8 @@ module ValidatesTimeliness
included do included do
alias_method_chain :instantiate_time_object, :timeliness alias_method_chain :instantiate_time_object, :timeliness
alias_method_chain :execute_callstack_for_multiparameter_attributes, :timeliness alias_method :execute_callstack_for_multiparameter_attributes, :execute_callstack_for_multiparameter_attributes_with_timeliness
alias_method :read_value_from_parameter, :read_value_from_parameter_with_timeliness
end end
private private
@ -34,29 +35,32 @@ module ValidatesTimeliness
invalid_multiparameter_date_or_time_as_string(values) invalid_multiparameter_date_or_time_as_string(values)
end end
def read_value_from_parameter_with_timeliness(name, values_from_param)
klass = (self.class.reflect_on_aggregation(name.to_sym) || column_for_attribute(name)).klass
values = values_from_param.is_a?(Hash) ? values_from_param.to_a.sort_by(&:first).map(&:last) : values_from_param
if values.empty? || values.all?{ |v| v.nil? }
nil
elsif klass == Time
instantiate_time_object(name, values)
elsif klass == Date
instantiate_date_object(name, values)
else
if respond_to?(:read_other_parameter_value)
read_date_parameter_value(name, values_from_param)
else
klass.new(*values)
end
end
end
def execute_callstack_for_multiparameter_attributes_with_timeliness(callstack) def execute_callstack_for_multiparameter_attributes_with_timeliness(callstack)
errors = [] errors = []
callstack.each do |name, values_with_empty_parameters| callstack.each do |name, values_with_empty_parameters|
begin begin
klass = (self.class.reflect_on_aggregation(name.to_sym) || column_for_attribute(name)).klass send(name + "=", read_value_from_parameter(name, values_with_empty_parameters))
values_with_empty_parameters = values_with_empty_parameters.to_a.sort_by { |v| v.first }.map { |v| v.last } if Hash === values_with_empty_parameters
values = values_with_empty_parameters.reject { |v| v.nil? }
if values.empty?
send(name + "=", nil)
else
value = if Time == klass
instantiate_time_object(name, values)
elsif Date == klass
instantiate_date_object(name, values_with_empty_parameters)
else
klass.new(*values)
end
send(name + "=", value)
end
rescue => ex rescue => ex
values = values_with_empty_parameters.is_a?(Hash) ? values_with_empty_parameters.values : values_with_empty_parameters
errors << ActiveRecord::AttributeAssignmentError.new("error on assignment #{values.inspect} to #{name}", ex, name) errors << ActiveRecord::AttributeAssignmentError.new("error on assignment #{values.inspect} to #{name}", ex, name)
end end
end end

View File

@ -1,61 +1,34 @@
require 'spec_helper' require 'spec_helper'
describe ValidatesTimeliness::Extensions::MultiparameterHandler do describe ValidatesTimeliness::Extensions::MultiparameterHandler do
let(:employee) { Employee.new }
context "time column" do context "time column" do
context "given an array callstack as in Rails 3.0 and before" do it 'should return string value for invalid date portion' do
it 'should return string value for invalid date portion' do employee = record_with_multiparameter_attribute(:birth_datetime, [2000, 2, 31, 12, 0, 0])
multiparameter_attribute(:birth_datetime, [2000, 2, 31, 12, 0, 0]) employee.birth_datetime_before_type_cast.should == '2000-02-31 12:00:00'
employee.birth_datetime_before_type_cast.should == '2000-02-31 12:00:00'
end
it 'should return Time value for valid datetimes' do
multiparameter_attribute(:birth_datetime, [2000, 2, 28, 12, 0, 0])
employee.birth_datetime_before_type_cast.should be_kind_of(Time)
end
end end
context "given a hash callstack as in Rails 3.1+" do it 'should return Time value for valid datetimes' do
it 'should return string value for invalid date portion' do employee = record_with_multiparameter_attribute(:birth_datetime, [2000, 2, 28, 12, 0, 0])
multiparameter_attribute(:birth_datetime, { 1 => 2000, 2 => 2, 3 => 31, 4 => 12, 5 => 0, 6 => 0 }) employee.birth_datetime_before_type_cast.should be_kind_of(Time)
employee.birth_datetime_before_type_cast.should == '2000-02-31 12:00:00'
end
it 'should return Time value for valid datetimes' do
multiparameter_attribute(:birth_datetime, { 1 => 2000, 2 => 2, 3 => 28, 4 => 12, 5 => 0, 6 => 0 })
employee.birth_datetime_before_type_cast.should be_kind_of(Time)
end
end end
end end
context "date column" do context "date column" do
context "given an array callstack as in Rails 3.0 and before" do it 'should return string value for invalid date' do
it 'should return string value for invalid date' do employee = record_with_multiparameter_attribute(:birth_date, [2000, 2, 31])
multiparameter_attribute(:birth_date, [2000, 2, 31]) employee.birth_date_before_type_cast.should == '2000-02-31'
employee.birth_date_before_type_cast.should == '2000-02-31'
end
it 'should return Date value for valid date' do
multiparameter_attribute(:birth_date, [2000, 2, 28])
employee.birth_date_before_type_cast.should be_kind_of(Date)
end
end end
context "given a hash callstack as in Rails 3.1+" do it 'should return Date value for valid date' do
it 'should return string value for invalid date' do employee = record_with_multiparameter_attribute(:birth_date, [2000, 2, 28])
multiparameter_attribute(:birth_date, { 1 => 2000, 2 => 2, 3 => 31 }) employee.birth_date_before_type_cast.should be_kind_of(Date)
employee.birth_date_before_type_cast.should == '2000-02-31'
end
it 'should return Date value for valid date' do
multiparameter_attribute(:birth_date, { 1 => 2000, 2 => 2, 3 => 28 })
employee.birth_date_before_type_cast.should be_kind_of(Date)
end
end end
end end
def multiparameter_attribute(name, values) def record_with_multiparameter_attribute(name, values)
employee.send(:execute_callstack_for_multiparameter_attributes, name.to_s => values) hash = {}
values.each_with_index {|value, index| hash["#{name}(#{index+1}i)"] = value.to_s }
Employee.new(hash)
end end
end end