diff --git a/actiontext/CHANGELOG.md b/actiontext/CHANGELOG.md index 57fff69f92..4af9e1e6f9 100644 --- a/actiontext/CHANGELOG.md +++ b/actiontext/CHANGELOG.md @@ -1,3 +1,7 @@ +* Add `with_all_rich_text` method to eager load all rich text associations on a model at once + + *Matt Swanson*, *DHH* + ## Rails 6.1.0.rc1 (November 02, 2020) ## * Declare `ActionText::FixtureSet.attachment` to generate an diff --git a/actiontext/lib/action_text/attribute.rb b/actiontext/lib/action_text/attribute.rb index daca26f63a..73f6bbefe1 100644 --- a/actiontext/lib/action_text/attribute.rb +++ b/actiontext/lib/action_text/attribute.rb @@ -45,6 +45,16 @@ module ActionText scope :"with_rich_text_#{name}", -> { includes("rich_text_#{name}") } scope :"with_rich_text_#{name}_and_embeds", -> { includes("rich_text_#{name}": { embeds_attachments: :blob }) } end + + # Eager load all dependent RichText models in bulk. + def with_all_rich_text + eager_load(rich_text_association_names) + end + + private + def rich_text_association_names + reflect_on_all_associations(:has_one).collect(&:name).select { |n| n.start_with?("rich_text_") } + end end end end diff --git a/actiontext/test/test_helper.rb b/actiontext/test/test_helper.rb index 150ccb3877..70bac495bc 100644 --- a/actiontext/test/test_helper.rb +++ b/actiontext/test/test_helper.rb @@ -22,6 +22,23 @@ if ActiveSupport::TestCase.respond_to?(:fixture_path=) end class ActiveSupport::TestCase + def assert_queries(expected_count) + ActiveRecord::Base.connection.materialize_transactions + + queries = [] + ActiveSupport::Notifications.subscribe("sql.active_record") do |*, sql:, name:, **| + queries << sql unless %w[ SCHEMA TRANSACTION ].include?(name) + end + + yield.tap do + assert_equal expected_count, queries.size, "#{queries.size} instead of #{expected_count} queries were executed. #{queries.inspect}" + end + end + + def assert_no_queries(&block) + assert_queries(0, &block) + end + private def create_file_blob(filename:, content_type:, metadata: nil) ActiveStorage::Blob.create_and_upload! io: file_fixture(filename).open, filename: filename, content_type: content_type, metadata: metadata diff --git a/actiontext/test/unit/model_test.rb b/actiontext/test/unit/model_test.rb index 1c5650e23a..a26cebab3d 100644 --- a/actiontext/test/unit/model_test.rb +++ b/actiontext/test/unit/model_test.rb @@ -86,4 +86,23 @@ class ActionText::ModelTest < ActiveSupport::TestCase assert_kind_of ActionText::RichText, message.content end end + + test "eager loading" do + Message.create!(subject: "Subject", content: "

Content

") + + message = assert_queries(2) { Message.with_rich_text_content.last } + assert_no_queries do + assert_equal "Content", message.content.to_plain_text + end + end + + test "eager loading all rich text" do + Message.create!(subject: "Subject", content: "

Content

", body: "

Body

") + + message = assert_queries(1) { Message.with_all_rich_text.last } + assert_no_queries do + assert_equal "Content", message.content.to_plain_text + assert_equal "Body", message.body.to_plain_text + end + end end