refactored attribute write method definitions in single definition and added write_date_time_attribute method to unify value writing

This commit is contained in:
Adam Meehan 2008-09-24 15:58:08 +10:00
parent 1b1d17ebd8
commit 8f950d5ac6

View File

@ -38,8 +38,8 @@ module ValidatesTimeliness
end
end
# Adds check for cached time attributes which have been type cast already
# and value can be used from cache. This prevents the raw time value from
# Adds check for cached date/time attributes which have been type cast already
# and value can be used from cache. This prevents the raw date/time value from
# being type cast using default Rails type casting when writing values
# to the database.
def read_attribute(attr_name)
@ -61,10 +61,35 @@ module ValidatesTimeliness
end
end
# Writes attribute value by storing raw value in attributes hash,
# then convert it with parser and cache it.
#
# If Rails 2.1 dirty attributes is enabled then the value is added to
# changed attributes if changed. Can't use the default dirty checking
# implementation as it chains the write_attribute method which deletes
# the attribute from the cache.
def write_date_time_attribute(attr_name, value)
attr_name = attr_name.to_s
column = column_for_attribute(attr_name)
old = read_attribute('#{attr_name}') if defined?(ActiveRecord::Dirty)
new = self.class.parse_date_time(value, column.type)
if self.class.send(:create_time_zone_conversion_attribute?, attr_name, column)
new = new.in_time_zone rescue nil
end
@attributes_cache[attr_name] = new
if defined?(ActiveRecord::Dirty) && !changed_attributes.include?(attr_name) && old != new
changed_attributes[attr_name] = (old.duplicable? ? old.clone : old)
end
@attributes[attr_name] = value
end
module ClassMethods
# Modified from AR to define Date and Time attribute reader and writer
# methods with strict time type casting.
# Override AR method to define attribute reader and writer method for
# date, time and datetime attributes to use plugin parser.
def define_attribute_methods
return if generated_methods?
columns_hash.each do |name, column|
@ -79,10 +104,8 @@ module ValidatesTimeliness
end
unless instance_method_already_implemented?("#{name}=")
if create_time_zone_conversion_attribute?(name, column)
define_write_method_for_time_zone_conversion(name.to_sym)
elsif [:date, :time, :datetime].include?(column.type)
define_write_method_for_dates_and_times(name.to_sym, column.type)
if [:date, :time, :datetime].include?(column.type)
define_write_method_for_dates_and_times(name.to_sym)
else
define_write_method(name.to_sym)
end
@ -94,29 +117,14 @@ module ValidatesTimeliness
end
end
# Define time attribute write method to store raw time value in
# attributes hash, then convert it with parser and cache it.
#
# If Rails 2.1 dirty attributes is enabled then the value is added to
# changed attributes if changed. Can't use the default dirty checking
# implementation as it chains the write_attribute method which deletes
# the attribute from the cache.
def define_write_method_for_time_zone_conversion(attr_name)
# Define write method for date, time and datetime columns
def define_write_method_for_dates_and_times(attr_name)
method_body = <<-EOV
def #{attr_name}=(time)
old = read_attribute('#{attr_name}')
@attributes['#{attr_name}'] = time
unless time.acts_like?(:time)
time = self.class.parse_date_time(time, :datetime)
end
time = time.in_time_zone rescue nil
if !changed_attributes.include?('#{attr_name}') && old != time
changed_attributes['#{attr_name}'] = (old.duplicable? ? old.clone : old)
end
@attributes_cache['#{attr_name}'] = time
def #{attr_name}=(value)
write_date_time_attribute('#{attr_name}', value)
end
EOV
evaluate_attribute_method attr_name, method_body, "#{attr_name}="
evaluate_attribute_method attr_name, method_body
end
# Define time attribute reader. If reloading then check if cached,
@ -141,23 +149,6 @@ module ValidatesTimeliness
evaluate_attribute_method attr_name, method_body
end
# Define write for date and time columns or when time zone conversion is
# off. This is the default for Rails 2.0
def define_write_method_for_dates_and_times(attr_name, type)
method_body = <<-EOV
def #{attr_name}=(value)
old = read_attribute('#{attr_name}') if defined?(ActiveRecord::Dirty)
new = self.class.parse_date_time(value, :#{type})
@attributes_cache['#{attr_name}'] = new
if defined?(ActiveRecord::Dirty) && !changed_attributes.include?('#{attr_name}') && old != new
changed_attributes['#{attr_name}'] = (old.duplicable? ? old.clone : old)
end
@attributes['#{attr_name}'] = value
end
EOV
evaluate_attribute_method attr_name, method_body
end
end
end