mirror of
https://github.com/ditkrg/validates_timeliness.git
synced 2026-01-23 06:16:44 +00:00
added strict_time_type_cast method to handle casting
refactored to be simler and rely on read_atribute method conversion rather than use new reader method definer got time (Rails 2.1)
This commit is contained in:
parent
d3b126729b
commit
a9b033e539
@ -5,9 +5,9 @@
|
||||
#
|
||||
# For Rails >= 2.1
|
||||
# This module overrides these AR methods to allow a time value passed to a column
|
||||
# write method to be stored as is and converts it to a time and caches on read.
|
||||
# This differs from the normal AR behvaviour where the value is converted and
|
||||
# cached on write.
|
||||
# write method to be stored as is and only convert to a time on read.
|
||||
# This differs from the current AR behvaviour where the value is converted
|
||||
# on write.
|
||||
#
|
||||
# This allows the before_type_cast method for the column to return the actual
|
||||
# value passed to it, treating time columns like all other column types.
|
||||
@ -25,25 +25,7 @@ module ValidatesTimeliness
|
||||
module ClassMethods
|
||||
# Rails > 2.0.2
|
||||
module New
|
||||
def define_read_method_for_time_zone_conversion(attr_name)
|
||||
method_body = <<-EOV
|
||||
def #{attr_name}(reload = false)
|
||||
cached = @attributes_cache['#{attr_name}']
|
||||
return cached if cached && !reload
|
||||
time = read_attribute_before_type_cast('#{attr_name}')
|
||||
if time.acts_like?(:time)
|
||||
time = time.in_time_zone
|
||||
elsif time
|
||||
# check invalid date
|
||||
time.to_date rescue time = nil
|
||||
time = time.is_a?(String) ? Time.zone.parse(time) : time.to_time rescue time if time
|
||||
end
|
||||
@attributes_cache['#{attr_name}'] = time
|
||||
end
|
||||
EOV
|
||||
evaluate_attribute_method attr_name, method_body
|
||||
end
|
||||
|
||||
# Store time value as is including as a string. Only convert on read
|
||||
def define_write_method_for_time_zone_conversion(attr_name)
|
||||
method_body = <<-EOV
|
||||
def #{attr_name}=(time)
|
||||
@ -59,18 +41,17 @@ module ValidatesTimeliness
|
||||
|
||||
# Rails <= 2.0.2
|
||||
module Old
|
||||
# Copied from AR and inserted Time class check to time attribute
|
||||
def define_attribute_methods
|
||||
return if generated_methods?
|
||||
columns_hash.each do |name, column|
|
||||
unless instance_method_already_implemented?(name)
|
||||
if self.serialized_attributes[name]
|
||||
define_read_method_for_serialized_attribute(name)
|
||||
elsif column.klass == Time
|
||||
define_read_method_for_time_attribute(name.to_sym)
|
||||
else
|
||||
if column.klass == Time
|
||||
define_read_method_for_time_attribute(name.to_sym)
|
||||
else
|
||||
define_read_method(name.to_sym, name, column)
|
||||
end
|
||||
define_read_method(name.to_sym, name, column)
|
||||
end
|
||||
end
|
||||
|
||||
@ -84,19 +65,14 @@ module ValidatesTimeliness
|
||||
end
|
||||
end
|
||||
|
||||
# defines time attribute reader and does conversion strict
|
||||
def define_read_method_for_time_attribute(attr_name)
|
||||
method_body = <<-EOV
|
||||
def #{attr_name}(reload = false)
|
||||
cached = @attributes_cache['#{attr_name}']
|
||||
return cached if cached && !reload
|
||||
time = read_attribute_before_type_cast('#{attr_name}')
|
||||
unless time.acts_like?(:time)
|
||||
klass = ActiveRecord::ConnectionAdapters::Column
|
||||
# check for invalid date
|
||||
time = nil unless klass.string_to_date(time)
|
||||
# convert to time if still valid
|
||||
time = klass.string_to_time(time) if time
|
||||
end
|
||||
time = strict_time_type_cast(time)
|
||||
@attributes_cache['#{attr_name}'] = time
|
||||
end
|
||||
EOV
|
||||
|
||||
@ -6,6 +6,7 @@ module ValidatesTimeliness
|
||||
time_array[0..2].join('-') + ' ' + time_array[3..5].join(':')
|
||||
end
|
||||
|
||||
# Overrides AR method to store multiparameter time and dates
|
||||
def execute_callstack_for_multiparameter_attributes(callstack)
|
||||
errors = []
|
||||
callstack.each do |name, values|
|
||||
@ -30,5 +31,36 @@ module ValidatesTimeliness
|
||||
end
|
||||
end
|
||||
|
||||
def strict_time_type_cast(time)
|
||||
if time.acts_like?(:time)
|
||||
time.respond_to?(:in_time_zone) ? time.time.in_time_zone : time
|
||||
else
|
||||
klass = ActiveRecord::ConnectionAdapters::Column
|
||||
# check for invalid date
|
||||
time = nil unless klass.string_to_date(time)
|
||||
# convert to time if still valid
|
||||
time = klass.string_to_time(time) if time
|
||||
end
|
||||
end
|
||||
|
||||
def read_attribute(attr_name)
|
||||
attr_name = attr_name.to_s
|
||||
if !(value = @attributes[attr_name]).nil?
|
||||
if column = column_for_attribute(attr_name)
|
||||
if unserializable_attribute?(attr_name, column)
|
||||
unserialize_attribute(attr_name)
|
||||
elsif column.klass == Time
|
||||
strict_time_type_cast(value)
|
||||
else
|
||||
column.type_cast(value)
|
||||
end
|
||||
else
|
||||
value
|
||||
end
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@ -33,6 +33,9 @@ describe ValidatesTimeliness::AttributeMethods do
|
||||
end
|
||||
end
|
||||
|
||||
# This fails running as plugin under vendor using Rails 2.1RC
|
||||
# due to write_attribute_with_dirty ignoring the write method for time zone
|
||||
# method. But invalid dates do return nil when running app.
|
||||
it "should return nil when time is invalid" do
|
||||
@person.birth_date_and_time = "2000-02-30 01:02:03"
|
||||
@person.birth_date_and_time.should be_nil
|
||||
|
||||
@ -34,4 +34,38 @@ describe ValidatesTimeliness::Base do
|
||||
execute_callstack_for_multiparameter_attributes(callstack)
|
||||
end
|
||||
end
|
||||
|
||||
describe "strict_time_type_cast" do
|
||||
it "should return time object for valid time string" do
|
||||
strict_time_type_cast("2000-01-01 12:13:14").should be_kind_of(Time)
|
||||
end
|
||||
|
||||
it "should return nil for time string with invalid date part" do
|
||||
strict_time_type_cast("2000-02-30 12:13:14").should be_nil
|
||||
end
|
||||
|
||||
it "should return nil for time string with invalid time part" do
|
||||
strict_time_type_cast("2000-02-01 25:13:14").should be_nil
|
||||
end
|
||||
end
|
||||
|
||||
describe "read_attribute" do
|
||||
it "should return time object from time string" do
|
||||
@attributes = {}
|
||||
self.stub!(:column_for_attribute).and_return( mock('Column', :klass => Time) )
|
||||
self.stub!(:unserializable_attribute?).and_return(false)
|
||||
|
||||
@attributes['birth_date_and_time'] = "1980-01-01 00:00:00"
|
||||
read_attribute(:birth_date_and_time).should be_kind_of(Time)
|
||||
end
|
||||
|
||||
it "should return nil from invalid time string" do
|
||||
@attributes = {}
|
||||
self.stub!(:column_for_attribute).and_return( mock('Column', :klass => Time) )
|
||||
self.stub!(:unserializable_attribute?).and_return(false)
|
||||
|
||||
@attributes['birth_date_and_time'] = "1980-02-30 00:00:00"
|
||||
read_attribute(:birth_date_and_time).should be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Loading…
Reference in New Issue
Block a user