From 9384fa43cc7bbb32a2683821eaa9383344f03ebd Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Fri, 22 Aug 2014 11:24:00 -0700 Subject: Cache the value of `changed_attributes` when calling `changes_applied` `changes_applied` calles `changes`, which will call `changed_attributes` multiple times in a loop. This method actually performs work now, so we should cache the results while looping over it when we know it cannot change. --- .../lib/active_record/attribute_methods/dirty.rb | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'activerecord') diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb index 01f126f1b3..2f02738f6d 100644 --- a/activerecord/lib/active_record/attribute_methods/dirty.rb +++ b/activerecord/lib/active_record/attribute_methods/dirty.rb @@ -54,7 +54,19 @@ module ActiveRecord end def changed_attributes - super.reverse_merge(attributes_changed_in_place).freeze + # This should only be set by methods which will call changed_attributes + # multiple times when it is known that the computed value cannot change. + if defined?(@cached_changed_attributes) + @cached_changed_attributes + else + super.reverse_merge(attributes_changed_in_place).freeze + end + end + + def changes + cache_changed_attributes do + super + end end private @@ -157,6 +169,13 @@ module ActiveRecord store_original_raw_attribute(attr) end end + + def cache_changed_attributes + @cached_changed_attributes = changed_attributes + yield + ensure + remove_instance_variable(:@cached_changed_attributes) + end end end end -- cgit v1.2.3