From ede244e2367c7988fa02f5e3b956d88211bb5ade Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Fri, 2 Oct 2015 09:35:30 -0400 Subject: Build the `AttributeMutationTracker` lazily For reads, we never need to construct this object. The double `defined?` check is to avoid errors in tests --- .../lib/active_record/attribute_methods/dirty.rb | 28 ++++++++++++---------- activerecord/lib/active_record/persistence.rb | 2 +- 2 files changed, 16 insertions(+), 14 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb index 17ec4c2252..e8a782ed13 100644 --- a/activerecord/lib/active_record/attribute_methods/dirty.rb +++ b/activerecord/lib/active_record/attribute_methods/dirty.rb @@ -35,27 +35,22 @@ module ActiveRecord # reload the record and clears changed attributes. def reload(*) super.tap do - @mutation_tracker = AttributeMutationTracker.new(@attributes) + @mutation_tracker = nil @previous_mutation_tracker = nil @changed_attributes = HashWithIndifferentAccess.new end end - def init_internals - super - @mutation_tracker = AttributeMutationTracker.new(@attributes) - end - def initialize_dup(other) # :nodoc: super @attributes = self.class._default_attributes.map do |attr| attr.with_value_from_user(@attributes.fetch_value(attr.name)) end - @mutation_tracker = AttributeMutationTracker.new(@attributes) + @mutation_tracker = nil end def changes_applied - @previous_mutation_tracker = @mutation_tracker + @previous_mutation_tracker = mutation_tracker @changed_attributes = HashWithIndifferentAccess.new store_original_attributes end @@ -85,7 +80,7 @@ module ActiveRecord if defined?(@cached_changed_attributes) @cached_changed_attributes else - super.reverse_merge(@mutation_tracker.changed_values).freeze + super.reverse_merge(mutation_tracker.changed_values).freeze end end @@ -100,17 +95,24 @@ module ActiveRecord end def attribute_changed_in_place?(attr_name) - @mutation_tracker.changed_in_place?(attr_name) + mutation_tracker.changed_in_place?(attr_name) end private + def mutation_tracker + unless defined?(@mutation_tracker) + @mutation_tracker = nil + end + @mutation_tracker ||= AttributeMutationTracker.new(@attributes) + end + def changes_include?(attr_name) - super || @mutation_tracker.changed?(attr_name) + super || mutation_tracker.changed?(attr_name) end def clear_attribute_change(attr_name) - @mutation_tracker.forget_change(attr_name) + mutation_tracker.forget_change(attr_name) end def _update_record(*) @@ -127,7 +129,7 @@ module ActiveRecord def store_original_attributes @attributes = @attributes.map(&:forgetting_assignment) - @mutation_tracker = AttributeMutationTracker.new(@attributes) + @mutation_tracker = nil end def previous_mutation_tracker diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index 7b53f6e5a0..3f02f73a5a 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -211,7 +211,7 @@ module ActiveRecord def becomes(klass) became = klass.new became.instance_variable_set("@attributes", @attributes) - became.instance_variable_set("@mutation_tracker", @mutation_tracker) + became.instance_variable_set("@mutation_tracker", @mutation_tracker) if defined?(@mutation_tracker) became.instance_variable_set("@changed_attributes", attributes_changed_by_setter) became.instance_variable_set("@new_record", new_record?) became.instance_variable_set("@destroyed", destroyed?) -- cgit v1.2.3