diff options
-rw-r--r-- | activerecord/lib/active_record/associations/preloader.rb | 52 | ||||
-rw-r--r-- | activerecord/lib/active_record/railtie.rb | 16 | ||||
-rw-r--r-- | activerecord/test/cases/associations/cascaded_eager_loading_test.rb | 10 | ||||
-rw-r--r-- | activerecord/test/cases/relation_test.rb | 2 | ||||
-rw-r--r-- | activesupport/lib/active_support/cache.rb | 8 | ||||
-rw-r--r-- | activesupport/test/silence_logger_test.rb | 2 |
6 files changed, 45 insertions, 45 deletions
diff --git a/activerecord/lib/active_record/associations/preloader.rb b/activerecord/lib/active_record/associations/preloader.rb index a8f94b574d..8997579527 100644 --- a/activerecord/lib/active_record/associations/preloader.rb +++ b/activerecord/lib/active_record/associations/preloader.rb @@ -98,12 +98,11 @@ module ActiveRecord # Loads all the given data into +records+ for the +association+. def preloaders_on(association, records, scope, polymorphic_parent = false) - if association.respond_to?(:to_hash) + case association + when Hash preloaders_for_hash(association, records, scope, polymorphic_parent) - elsif association.is_a?(Symbol) + when Symbol, String preloaders_for_one(association, records, scope, polymorphic_parent) - elsif association.respond_to?(:to_str) - preloaders_for_one(association.to_sym, records, scope, polymorphic_parent) else raise ArgumentError, "#{association.inspect} was not recognized for preload" end @@ -111,23 +110,21 @@ module ActiveRecord def preloaders_for_hash(association, records, scope, polymorphic_parent) association.flat_map { |parent, child| - loaders = preloaders_for_one parent, records, scope, polymorphic_parent - - recs = loaders.flat_map(&:preloaded_records).uniq - - reflection = records.first.class._reflect_on_association(parent) - polymorphic_parent = reflection && reflection.options[:polymorphic] - - loaders.concat Array.wrap(child).flat_map { |assoc| - preloaders_on assoc, recs, scope, polymorphic_parent - } - loaders + grouped_records(parent, records, polymorphic_parent).flat_map do |reflection, reflection_records| + loaders = preloaders_for_reflection(reflection, reflection_records, scope) + recs = loaders.flat_map(&:preloaded_records) + child_polymorphic_parent = reflection && reflection.options[:polymorphic] + loaders.concat Array.wrap(child).flat_map { |assoc| + preloaders_on assoc, recs, scope, child_polymorphic_parent + } + loaders + end } end # Loads all the given data into +records+ for a singular +association+. # - # Functions by instantiating a preloader class such as Preloader::HasManyThrough and + # Functions by instantiating a preloader class such as Preloader::Association and # call the +run+ method for each passed in class in the +records+ argument. # # Not all records have the same class, so group then preload group on the reflection @@ -138,12 +135,17 @@ module ActiveRecord # classes, depending on the polymorphic_type field. So we group by the classes as # well. def preloaders_for_one(association, records, scope, polymorphic_parent) - grouped_records(association, records, polymorphic_parent).flat_map do |reflection, klasses| - klasses.map do |rhs_klass, rs| - loader = preloader_for(reflection, rs).new(rhs_klass, rs, reflection, scope) - loader.run self - loader + grouped_records(association, records, polymorphic_parent) + .flat_map do |reflection, reflection_records| + preloaders_for_reflection reflection, reflection_records, scope end + end + + def preloaders_for_reflection(reflection, records, scope) + records.group_by { |record| record.association(reflection.name).klass }.map do |rhs_klass, rs| + loader = preloader_for(reflection, rs).new(rhs_klass, rs, reflection, scope) + loader.run self + loader end end @@ -151,11 +153,9 @@ module ActiveRecord h = {} records.each do |record| next unless record - next if polymorphic_parent && !record.class._reflect_on_association(association) - assoc = record.association(association) - next unless assoc.klass - klasses = h[assoc.reflection] ||= {} - (klasses[assoc.klass] ||= []) << record + reflection = record.class._reflect_on_association(association) + next if polymorphic_parent && !reflection || !record.association(association).klass + (h[reflection] ||= []) << record end h end diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb index 81ad9ef3a2..538659d6bd 100644 --- a/activerecord/lib/active_record/railtie.rb +++ b/activerecord/lib/active_record/railtie.rb @@ -168,21 +168,7 @@ end_error initializer "active_record.initialize_database" do ActiveSupport.on_load(:active_record) do self.configurations = Rails.application.config.database_configuration - - begin - establish_connection - rescue ActiveRecord::NoDatabaseError - warn <<-end_warning -Oops - You have a database configured, but it doesn't exist yet! - -Here's how to get started: - - 1. Configure your database in config/database.yml. - 2. Run `rails db:create` to create the database. - 3. Run `rails db:setup` to load your database schema. -end_warning - raise - end + establish_connection end end diff --git a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb index ba2104eb26..a9e22c7643 100644 --- a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb +++ b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb @@ -160,6 +160,16 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase end end + def test_preload_through_missing_records + post = Post.where.not(author_id: Author.select(:id)).preload(author: { comments: :post }).first! + assert_no_queries { assert_nil post.author } + end + + def test_eager_association_loading_with_missing_first_record + posts = Post.where(id: 3).preload(author: { comments: :post }).to_a + assert_equal posts.size, 1 + end + def test_eager_association_loading_with_recursive_cascading_four_levels_has_many_through source = Vertex.all.merge!(includes: { sinks: { sinks: { sinks: :sinks } } }, order: "vertices.id").first assert_equal vertices(:vertex_4), assert_no_queries { source.sinks.first.sinks.first.sinks.first } diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb index fbeb617b29..68161f6a84 100644 --- a/activerecord/test/cases/relation_test.rb +++ b/activerecord/test/cases/relation_test.rb @@ -232,7 +232,7 @@ module ActiveRecord assert_equal 3, nb_inner_join, "Wrong amount of INNER JOIN in query" # using `\W` as the column separator - assert queries.any? { |sql| %r[INNER\s+JOIN\s+#{Author.quoted_table_name}\s+\Wauthors_categorizations\W]i.match?(sql) }, "Should be aliasing the child INNER JOINs in query" + assert queries.any? { |sql| %r[INNER\s+JOIN\s+#{Regexp.escape(Author.quoted_table_name)}\s+\Wauthors_categorizations\W]i.match?(sql) }, "Should be aliasing the child INNER JOINs in query" end def test_relation_with_merged_joins_aliased_works diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb index a5d0c52b13..222ef2b515 100644 --- a/activesupport/lib/active_support/cache.rb +++ b/activesupport/lib/active_support/cache.rb @@ -596,9 +596,13 @@ module ActiveSupport # Merges the default options with ones specific to a method call. def merged_options(call_options) if call_options - options.merge(call_options) + if options.empty? + call_options + else + options.merge(call_options) + end else - options.dup + options end end diff --git a/activesupport/test/silence_logger_test.rb b/activesupport/test/silence_logger_test.rb index fc5c5c1161..bd0c6b7f86 100644 --- a/activesupport/test/silence_logger_test.rb +++ b/activesupport/test/silence_logger_test.rb @@ -6,7 +6,7 @@ require "logger" class LoggerSilenceTest < ActiveSupport::TestCase class MyLogger < ::Logger - include LoggerSilence + include ActiveSupport::LoggerSilence end setup do |