aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Patterson <aaron.patterson@gmail.com>2012-01-25 16:52:56 -0800
committerAaron Patterson <aaron.patterson@gmail.com>2012-02-07 13:51:52 -0800
commit422cc57dab8ac2ddd2b3c5f453609aff9f86defb (patch)
treea709036bd07f425c0e39d0544af2fe1df7f07d9b
parent55cc16f502399b69051e4ff5432569bbea45e9c0 (diff)
downloadrails-422cc57dab8ac2ddd2b3c5f453609aff9f86defb.tar.gz
rails-422cc57dab8ac2ddd2b3c5f453609aff9f86defb.tar.bz2
rails-422cc57dab8ac2ddd2b3c5f453609aff9f86defb.zip
copy the columns hash to the active record instances, typecast using columns looked up on the instance
-rw-r--r--activerecord/lib/active_record/attribute_methods/read.rb13
-rw-r--r--activerecord/lib/active_record/attribute_methods/serialization.rb8
-rw-r--r--activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb79
-rw-r--r--activerecord/lib/active_record/core.rb2
4 files changed, 66 insertions, 36 deletions
diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb
index c129dc8c52..73e473391a 100644
--- a/activerecord/lib/active_record/attribute_methods/read.rb
+++ b/activerecord/lib/active_record/attribute_methods/read.rb
@@ -92,6 +92,8 @@ module ActiveRecord
end
def internal_attribute_access_code(attr_name, cast_code)
+ cast_code = instance_cast_code(attr_name)
+
access_code = "v = @attributes.fetch(attr_name) { missing_attribute(attr_name, caller) };"
access_code << "v && #{cast_code};"
@@ -116,6 +118,10 @@ module ActiveRecord
def attribute_cast_code(attr_name)
columns_hash[attr_name].type_cast_code('v')
end
+
+ def instance_cast_code(attr_name)
+ "@columns_hash[attr_name].type_cast(v)"
+ end
end
# Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example,
@@ -124,10 +130,11 @@ module ActiveRecord
self.class.type_cast_attribute(attr_name, @attributes, @attributes_cache)
end
+
private
- def attribute(attribute_name)
- read_attribute(attribute_name)
- end
+ def attribute(attribute_name)
+ read_attribute(attribute_name)
+ end
end
end
end
diff --git a/activerecord/lib/active_record/attribute_methods/serialization.rb b/activerecord/lib/active_record/attribute_methods/serialization.rb
index 0c8e4e4b9a..fbace73f7a 100644
--- a/activerecord/lib/active_record/attribute_methods/serialization.rb
+++ b/activerecord/lib/active_record/attribute_methods/serialization.rb
@@ -79,6 +79,14 @@ module ActiveRecord
super
end
end
+
+ def instance_cast_code(attr_name)
+ if serialized_attributes.include?(attr_name)
+ "v.unserialized_value"
+ else
+ super
+ end
+ end
end
def type_cast_attribute_for_write(column, value)
diff --git a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
index 2f86e32f41..30ee0947b3 100644
--- a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
+++ b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
@@ -16,46 +16,59 @@ module ActiveRecord
module ClassMethods
protected
- # The enhanced read method automatically converts the UTC time stored in the database to the time
- # zone stored in Time.zone.
- def attribute_cast_code(attr_name)
- column = columns_hash[attr_name]
-
- if create_time_zone_conversion_attribute?(attr_name, column)
- typecast = "v = #{super}"
- time_zone_conversion = "v.acts_like?(:time) ? v.in_time_zone : v"
-
- "((#{typecast}) && (#{time_zone_conversion}))"
- else
- super
- end
+ # The enhanced read method automatically converts the UTC time stored in the database to the time
+ # zone stored in Time.zone.
+ def attribute_cast_code(attr_name)
+ column = columns_hash[attr_name]
+
+ if create_time_zone_conversion_attribute?(attr_name, column)
+ typecast = "v = #{super}"
+ time_zone_conversion = "v.acts_like?(:time) ? v.in_time_zone : v"
+
+ "((#{typecast}) && (#{time_zone_conversion}))"
+ else
+ super
end
+ end
- # Defined for all +datetime+ and +timestamp+ attributes when +time_zone_aware_attributes+ are enabled.
- # This enhanced write method will automatically convert the time passed to it to the zone stored in Time.zone.
- def define_method_attribute=(attr_name)
- if create_time_zone_conversion_attribute?(attr_name, columns_hash[attr_name])
- method_body, line = <<-EOV, __LINE__ + 1
- def #{attr_name}=(original_time)
- time = original_time
- unless time.acts_like?(:time)
- time = time.is_a?(String) ? Time.zone.parse(time) : time.to_time rescue time
- end
- time = time.in_time_zone rescue nil if time
- write_attribute(:#{attr_name}, original_time)
- @attributes_cache["#{attr_name}"] = time
+ # Defined for all +datetime+ and +timestamp+ attributes when +time_zone_aware_attributes+ are enabled.
+ # This enhanced write method will automatically convert the time passed to it to the zone stored in Time.zone.
+ def define_method_attribute=(attr_name)
+ if create_time_zone_conversion_attribute?(attr_name, columns_hash[attr_name])
+ method_body, line = <<-EOV, __LINE__ + 1
+ def #{attr_name}=(original_time)
+ time = original_time
+ unless time.acts_like?(:time)
+ time = time.is_a?(String) ? Time.zone.parse(time) : time.to_time rescue time
end
- EOV
- generated_attribute_methods.module_eval(method_body, __FILE__, line)
- else
- super
- end
+ time = time.in_time_zone rescue nil if time
+ write_attribute(:#{attr_name}, original_time)
+ @attributes_cache["#{attr_name}"] = time
+ end
+ EOV
+ generated_attribute_methods.module_eval(method_body, __FILE__, line)
+ else
+ super
end
+ end
private
- def create_time_zone_conversion_attribute?(name, column)
- time_zone_aware_attributes && !self.skip_time_zone_conversion_for_attributes.include?(name.to_sym) && column.type.in?([:datetime, :timestamp])
+ def instance_cast_code(attr_name)
+ column = columns_hash[attr_name]
+
+ if create_time_zone_conversion_attribute?(attr_name, column)
+ typecast = "v = #{super}"
+ time_zone_conversion = "v.acts_like?(:time) ? v.in_time_zone : v"
+
+ "((#{typecast}) && (#{time_zone_conversion}))"
+ else
+ super
end
+ end
+
+ def create_time_zone_conversion_attribute?(name, column)
+ time_zone_aware_attributes && !self.skip_time_zone_conversion_for_attributes.include?(name.to_sym) && column.type.in?([:datetime, :timestamp])
+ end
end
end
end
diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb
index a2ce620354..93b8e269fb 100644
--- a/activerecord/lib/active_record/core.rb
+++ b/activerecord/lib/active_record/core.rb
@@ -341,6 +341,8 @@ module ActiveRecord
@attributes[pk] = nil unless @attributes.key?(pk)
+ @columns_hash = self.class.columns_hash.dup
+
@relation = nil
@aggregation_cache = {}
@association_cache = {}