mirror of
https://github.com/ditkrg/validates_timeliness.git
synced 2026-01-24 23:06:42 +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
|
# For Rails >= 2.1
|
||||||
# This module overrides these AR methods to allow a time value passed to a column
|
# 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.
|
# write method to be stored as is and only convert to a time on read.
|
||||||
# This differs from the normal AR behvaviour where the value is converted and
|
# This differs from the current AR behvaviour where the value is converted
|
||||||
# cached on write.
|
# on write.
|
||||||
#
|
#
|
||||||
# This allows the before_type_cast method for the column to return the actual
|
# 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.
|
# value passed to it, treating time columns like all other column types.
|
||||||
@ -25,25 +25,7 @@ module ValidatesTimeliness
|
|||||||
module ClassMethods
|
module ClassMethods
|
||||||
# Rails > 2.0.2
|
# Rails > 2.0.2
|
||||||
module New
|
module New
|
||||||
def define_read_method_for_time_zone_conversion(attr_name)
|
# Store time value as is including as a string. Only convert on read
|
||||||
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
|
|
||||||
|
|
||||||
def define_write_method_for_time_zone_conversion(attr_name)
|
def define_write_method_for_time_zone_conversion(attr_name)
|
||||||
method_body = <<-EOV
|
method_body = <<-EOV
|
||||||
def #{attr_name}=(time)
|
def #{attr_name}=(time)
|
||||||
@ -59,18 +41,17 @@ module ValidatesTimeliness
|
|||||||
|
|
||||||
# Rails <= 2.0.2
|
# Rails <= 2.0.2
|
||||||
module Old
|
module Old
|
||||||
|
# Copied from AR and inserted Time class check to time attribute
|
||||||
def define_attribute_methods
|
def define_attribute_methods
|
||||||
return if generated_methods?
|
return if generated_methods?
|
||||||
columns_hash.each do |name, column|
|
columns_hash.each do |name, column|
|
||||||
unless instance_method_already_implemented?(name)
|
unless instance_method_already_implemented?(name)
|
||||||
if self.serialized_attributes[name]
|
if self.serialized_attributes[name]
|
||||||
define_read_method_for_serialized_attribute(name)
|
define_read_method_for_serialized_attribute(name)
|
||||||
|
elsif column.klass == Time
|
||||||
|
define_read_method_for_time_attribute(name.to_sym)
|
||||||
else
|
else
|
||||||
if column.klass == Time
|
define_read_method(name.to_sym, name, column)
|
||||||
define_read_method_for_time_attribute(name.to_sym)
|
|
||||||
else
|
|
||||||
define_read_method(name.to_sym, name, column)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -84,19 +65,14 @@ module ValidatesTimeliness
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# defines time attribute reader and does conversion strict
|
||||||
def define_read_method_for_time_attribute(attr_name)
|
def define_read_method_for_time_attribute(attr_name)
|
||||||
method_body = <<-EOV
|
method_body = <<-EOV
|
||||||
def #{attr_name}(reload = false)
|
def #{attr_name}(reload = false)
|
||||||
cached = @attributes_cache['#{attr_name}']
|
cached = @attributes_cache['#{attr_name}']
|
||||||
return cached if cached && !reload
|
return cached if cached && !reload
|
||||||
time = read_attribute_before_type_cast('#{attr_name}')
|
time = read_attribute_before_type_cast('#{attr_name}')
|
||||||
unless time.acts_like?(:time)
|
time = strict_time_type_cast(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
|
|
||||||
@attributes_cache['#{attr_name}'] = time
|
@attributes_cache['#{attr_name}'] = time
|
||||||
end
|
end
|
||||||
EOV
|
EOV
|
||||||
|
|||||||
@ -6,6 +6,7 @@ module ValidatesTimeliness
|
|||||||
time_array[0..2].join('-') + ' ' + time_array[3..5].join(':')
|
time_array[0..2].join('-') + ' ' + time_array[3..5].join(':')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Overrides AR method to store multiparameter time and dates
|
||||||
def execute_callstack_for_multiparameter_attributes(callstack)
|
def execute_callstack_for_multiparameter_attributes(callstack)
|
||||||
errors = []
|
errors = []
|
||||||
callstack.each do |name, values|
|
callstack.each do |name, values|
|
||||||
@ -30,5 +31,36 @@ module ValidatesTimeliness
|
|||||||
end
|
end
|
||||||
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
|
||||||
end
|
end
|
||||||
|
|||||||
@ -33,6 +33,9 @@ describe ValidatesTimeliness::AttributeMethods do
|
|||||||
end
|
end
|
||||||
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
|
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 = "2000-02-30 01:02:03"
|
||||||
@person.birth_date_and_time.should be_nil
|
@person.birth_date_and_time.should be_nil
|
||||||
|
|||||||
@ -34,4 +34,38 @@ describe ValidatesTimeliness::Base do
|
|||||||
execute_callstack_for_multiparameter_attributes(callstack)
|
execute_callstack_for_multiparameter_attributes(callstack)
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user