Use includes instead of eager_load for with_all_rich_text

`eager_load` performs a single query using a `LEFT OUTER JOIN` to load
the associations. Loading the associations in a join can result in many
rows that contain redundant data and it performs poorly at scale.

With `includes` a separate query is performed for each association,
unless a join is required by conditions.

Co-authored-by: Rafael Mendonça França <rafael@franca.dev>
This commit is contained in:
Petrik 2023-02-03 12:14:40 +01:00
parent af2bbd5f66
commit 3b49e47ce8
3 changed files with 16 additions and 3 deletions

@ -1,3 +1,7 @@
* Use `includes` instead of `eager_load` for `with_all_rich_text`.
*Petrik de Heus*
* Delegate `ActionText::Content#deconstruct` to `Nokogiri::XML::DocumentFragment#elements`
```ruby

@ -65,7 +65,7 @@ def #{name}=(body)
# Eager load all dependent RichText models in bulk.
def with_all_rich_text
eager_load(rich_text_association_names)
includes(rich_text_association_names)
end
def rich_text_association_names

@ -106,9 +106,18 @@ class ActionText::ModelTest < ActiveSupport::TestCase
end
test "eager loading all rich text" do
Message.create!(subject: "Subject", content: "<h1>Content</h1>", body: "<h2>Body</h2>")
2.times do
Message.create!(subject: "Subject", content: "<h1>Content</h1>", body: "<h2>Body</h2>")
end
message = assert_queries_count(3) do
# 3 queries:
# messages x 1
# action texts (content) x 1
# action texts (body) x 1
Message.with_all_rich_text.to_a.last
end
message = assert_queries_count(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