Skip to content

Commit

Permalink
Build the AttributeMutationTracker lazily
Browse files Browse the repository at this point in the history
For reads, we never need to construct this object. The double `defined?`
check is to avoid errors in tests
  • Loading branch information
sgrif committed Oct 2, 2015
1 parent c80b114 commit ede244e
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 14 deletions.
28 changes: 15 additions & 13 deletions activerecord/lib/active_record/attribute_methods/dirty.rb
Expand Up @@ -35,27 +35,22 @@ def save!(*)
# <tt>reload</tt> 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
Expand Down Expand Up @@ -85,7 +80,7 @@ def changed_attributes
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

Expand All @@ -100,17 +95,24 @@ def previous_changes
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(*)
Expand All @@ -127,7 +129,7 @@ def keys_for_partial_write

def store_original_attributes
@attributes = @attributes.map(&:forgetting_assignment)
@mutation_tracker = AttributeMutationTracker.new(@attributes)
@mutation_tracker = nil
end

def previous_mutation_tracker
Expand Down
2 changes: 1 addition & 1 deletion activerecord/lib/active_record/persistence.rb
Expand Up @@ -211,7 +211,7 @@ def destroy!
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?)
Expand Down

0 comments on commit ede244e

Please sign in to comment.