diff options
Diffstat (limited to 'activerecord/lib')
-rw-r--r-- | activerecord/lib/active_record/associations/collection_association.rb | 42 | ||||
-rw-r--r-- | activerecord/lib/active_record/railties/controller_runtime.rb | 10 |
2 files changed, 35 insertions, 17 deletions
diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb index 4429c655a2..525ac65722 100644 --- a/activerecord/lib/active_record/associations/collection_association.rb +++ b/activerecord/lib/active_record/associations/collection_association.rb @@ -387,25 +387,35 @@ module ActiveRecord records end - def merge_target_lists(loaded, existing) - return loaded if existing.empty? - return existing if loaded.empty? - - loaded.map do |f| - i = existing.index(f) - if i - existing.delete_at(i).tap do |t| - keys = ["id"] + t.changes.keys + (f.attribute_names - t.attribute_names) - # FIXME: this call to attributes causes many NoMethodErrors - attributes = f.attributes - (attributes.keys - keys).each do |k| - t.send("#{k}=", attributes[k]) - end + # We have some records loaded from the database (persisted) and some that are + # in-memory (memory). The same record may be represented in the persisted array + # and in the memory array. + # + # So the task of this method is to merge them according to the following rules: + # + # * The final array must not have duplicates + # * The order of the persisted array is to be preserved + # * Any changes made to attributes on objects in the memory array are to be preserved + # * Otherwise, attributes should have the value found in the database + def merge_target_lists(persisted, memory) + return persisted if memory.empty? + return memory if persisted.empty? + + persisted.map! do |record| + mem_record = memory.delete(record) + + if mem_record + (record.attribute_names - mem_record.changes.keys).each do |name| + mem_record[name] = record[name] end + + mem_record else - f + record end - end + existing + end + + persisted + memory end # Do the relevant stuff to insert the given record into the association collection. diff --git a/activerecord/lib/active_record/railties/controller_runtime.rb b/activerecord/lib/active_record/railties/controller_runtime.rb index bc6ca936c0..9e3b3429e4 100644 --- a/activerecord/lib/active_record/railties/controller_runtime.rb +++ b/activerecord/lib/active_record/railties/controller_runtime.rb @@ -2,13 +2,21 @@ require 'active_support/core_ext/module/attr_internal' module ActiveRecord module Railties - module ControllerRuntime + module ControllerRuntime #:nodoc: extend ActiveSupport::Concern protected attr_internal :db_runtime + def process_action(action, *args) + # We also need to reset the runtime before each action + # because of queries in middleware or in cases we are streaming + # and it won't be cleaned up by the method below. + ActiveRecord::LogSubscriber.reset_runtime + super + end + def cleanup_view_runtime if ActiveRecord::Base.connected? db_rt_before_render = ActiveRecord::LogSubscriber.reset_runtime |