diff options
Diffstat (limited to 'activerecord/lib/active_record/attribute_methods')
6 files changed, 38 insertions, 44 deletions
diff --git a/activerecord/lib/active_record/attribute_methods/primary_key.rb b/activerecord/lib/active_record/attribute_methods/primary_key.rb index 7b7811a706..aa6704d5c9 100644 --- a/activerecord/lib/active_record/attribute_methods/primary_key.rb +++ b/activerecord/lib/active_record/attribute_methods/primary_key.rb @@ -18,7 +18,7 @@ module ActiveRecord # Sets the primary key value def id=(value) - write_attribute(self.class.primary_key, value) + write_attribute(self.class.primary_key, value) if self.class.primary_key end # Queries the primary key value @@ -53,8 +53,7 @@ module ActiveRecord end # Defines the primary key field -- can be overridden in subclasses. Overwriting will negate any effect of the - # primary_key_prefix_type setting, though. Since primary keys are usually protected from mass assignment, - # remember to let your database generate them or include the key in +attr_accessible+. + # primary_key_prefix_type setting, though. def primary_key @primary_key = reset_primary_key unless defined? @primary_key @primary_key diff --git a/activerecord/lib/active_record/attribute_methods/query.rb b/activerecord/lib/active_record/attribute_methods/query.rb index a8b23abb7c..0f9723febb 100644 --- a/activerecord/lib/active_record/attribute_methods/query.rb +++ b/activerecord/lib/active_record/attribute_methods/query.rb @@ -1,4 +1,3 @@ - module ActiveRecord module AttributeMethods module Query @@ -9,7 +8,7 @@ module ActiveRecord end def query_attribute(attr_name) - value = read_attribute(attr_name) + value = read_attribute(attr_name) { |n| missing_attribute(n, caller) } case value when true then true diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb index a7af086e43..1a4cb25dd7 100644 --- a/activerecord/lib/active_record/attribute_methods/read.rb +++ b/activerecord/lib/active_record/attribute_methods/read.rb @@ -8,7 +8,6 @@ module ActiveRecord extend ActiveSupport::Concern ATTRIBUTE_TYPES_CACHED_BY_DEFAULT = [:datetime, :timestamp, :time, :date] - ActiveRecord::Model.attribute_types_cached_by_default = ATTRIBUTE_TYPES_CACHED_BY_DEFAULT included do config_attribute :attribute_types_cached_by_default @@ -46,7 +45,7 @@ module ActiveRecord def define_method_attribute(attr_name) generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1 def __temp__ - read_attribute('#{attr_name}') { |n| missing_attribute(n, caller) } + read_attribute(:'#{attr_name}') { |n| missing_attribute(n, caller) } end alias_method '#{attr_name}', :__temp__ undef_method :__temp__ @@ -64,14 +63,22 @@ module ActiveRecord end end + ActiveRecord::Model.attribute_types_cached_by_default = ATTRIBUTE_TYPES_CACHED_BY_DEFAULT + # Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example, # "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)). def read_attribute(attr_name) + return unless attr_name + name_sym = attr_name.to_sym + # If it's cached, just return it - @attributes_cache.fetch(attr_name.to_s) { |name| + # We use #[] first as a perf optimization for non-nil values. See https://gist.github.com/3552829. + @attributes_cache[name_sym] || @attributes_cache.fetch(name_sym) { + name = attr_name.to_s + column = @columns_hash.fetch(name) { return @attributes.fetch(name) { - if name == 'id' && self.class.primary_key != name + if name_sym == :id && self.class.primary_key != name read_attribute(self.class.primary_key) end } @@ -82,7 +89,7 @@ module ActiveRecord } if self.class.cache_attribute?(name) - @attributes_cache[name] = column.type_cast(value) + @attributes_cache[name_sym] = column.type_cast(value) else column.type_cast value end diff --git a/activerecord/lib/active_record/attribute_methods/serialization.rb b/activerecord/lib/active_record/attribute_methods/serialization.rb index 33d7cc7f34..6395f92b4b 100644 --- a/activerecord/lib/active_record/attribute_methods/serialization.rb +++ b/activerecord/lib/active_record/attribute_methods/serialization.rb @@ -6,7 +6,7 @@ module ActiveRecord included do # Returns a hash of all the attributes that have been specified for serialization as # keys and their class restriction as values. - class_attribute :serialized_attributes, instance_writer: false + class_attribute :serialized_attributes, instance_accessor: false self.serialized_attributes = {} end @@ -41,6 +41,11 @@ module ActiveRecord end end + def serialized_attributes + ActiveSupport::Deprecation.warn("Instance level serialized_attributes method is deprecated, please use class level method.") + defined?(@serialized_attributes) ? @serialized_attributes : self.class.serialized_attributes + end + class Type # :nodoc: def initialize(column) @column = column @@ -93,16 +98,6 @@ module ActiveRecord attributes end - - private - - def attribute_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) @@ -114,7 +109,7 @@ module ActiveRecord end def read_attribute_before_type_cast(attr_name) - if serialized_attributes.include?(attr_name) + if self.class.serialized_attributes.include?(attr_name) super.unserialized_value else super 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 fa5b2ef336..b9a69cdb0a 100644 --- a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb +++ b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb @@ -34,21 +34,6 @@ 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 - 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) @@ -59,11 +44,14 @@ module ActiveRecord 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 - changed = read_attribute(:#{attr_name}) != time - write_attribute(:#{attr_name}, original_time) - #{attr_name}_will_change! if changed - @attributes_cache["#{attr_name}"] = time + zoned_time = time && time.in_time_zone rescue nil + rounded_time = round_usec(zoned_time) + rounded_value = round_usec(read_attribute("#{attr_name}")) + if (rounded_value != rounded_time) || (!rounded_value && original_time) + write_attribute("#{attr_name}", original_time) + #{attr_name}_will_change! + @attributes_cache[:"#{attr_name}"] = zoned_time + end end EOV generated_attribute_methods.module_eval(method_body, __FILE__, line) @@ -79,6 +67,12 @@ module ActiveRecord [:datetime, :timestamp].include?(column.type) end end + + private + def round_usec(value) + return unless value + value.change(:usec => 0) + end end end end diff --git a/activerecord/lib/active_record/attribute_methods/write.rb b/activerecord/lib/active_record/attribute_methods/write.rb index 50435921b1..5a39cb0125 100644 --- a/activerecord/lib/active_record/attribute_methods/write.rb +++ b/activerecord/lib/active_record/attribute_methods/write.rb @@ -25,13 +25,13 @@ module ActiveRecord def write_attribute(attr_name, value) attr_name = attr_name.to_s attr_name = self.class.primary_key if attr_name == 'id' && self.class.primary_key - @attributes_cache.delete(attr_name) + @attributes_cache.delete(attr_name.to_sym) column = column_for_attribute(attr_name) # If we're dealing with a binary column, write the data to the cache # so we don't attempt to typecast multiple times. if column && column.binary? - @attributes_cache[attr_name] = value + @attributes_cache[attr_name.to_sym] = value end if column || @attributes.has_key?(attr_name) |