Skip to content
Browse files

copy the columns hash to the active record instances, typecast using …

…columns looked up on the instance
  • Loading branch information...
1 parent 55cc16f commit 422cc57dab8ac2ddd2b3c5f453609aff9f86defb @tenderlove tenderlove committed Jan 25, 2012
View
13 activerecord/lib/active_record/attribute_methods/read.rb
@@ -92,6 +92,8 @@ def cacheable_column?(column)
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 @@ def external_attribute_access_code(attr_name, cast_code)
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 @@ def read_attribute(attr_name)
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
View
8 activerecord/lib/active_record/attribute_methods/serialization.rb
@@ -79,6 +79,14 @@ def attribute_cast_code(attr_name)
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)
View
79 activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
@@ -16,46 +16,59 @@ module TimeZoneConversion
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
View
2 activerecord/lib/active_record/core.rb
@@ -341,6 +341,8 @@ def init_internals
@attributes[pk] = nil unless @attributes.key?(pk)
+ @columns_hash = self.class.columns_hash.dup
+
@relation = nil
@aggregation_cache = {}
@association_cache = {}

0 comments on commit 422cc57

Please sign in to comment.
Something went wrong with that request. Please try again.