Reproduce the preloader regression in #41596

It's very peculiar, what seem to happen is that if some associations
are already loaded, the batching is done properly.
This commit is contained in:
Jean Boussier 2021-03-05 14:22:08 +01:00 committed by John Hawthorn
parent 9cc8375e06
commit c9a9dcd383
6 changed files with 99 additions and 0 deletions

View File

@ -27,6 +27,10 @@ require "models/parrot"
require "models/bird"
require "models/treasure"
require "models/price_estimate"
require "models/invoice"
require "models/discount"
require "models/line_item"
require "models/shipping_line"
class AssociationsTest < ActiveRecord::TestCase
fixtures :accounts, :companies, :developers, :projects, :developers_projects,
@ -435,6 +439,60 @@ class PreloaderTest < ActiveRecord::TestCase
end
end
def test_some_already_loaded_associations
item_discount = Discount.create(amount: 5)
shipping_discount = Discount.create(amount: 20)
invoice = Invoice.new
line_item = LineItem.new(amount: 20)
line_item.discount_applications << LineItemDiscountApplication.new(discount: item_discount)
invoice.line_items << line_item
shipping_line = ShippingLine.new(amount: 50)
shipping_line.discount_applications << ShippingLineDiscountApplication.new(discount: shipping_discount)
invoice.shipping_lines << shipping_line
invoice.save!
invoice.reload
# SELECT "line_items".* FROM "line_items" WHERE "line_items"."invoice_id" = ?
# SELECT "shipping_lines".* FROM shipping_lines WHERE "shipping_lines"."invoice_id" = ?
# SELECT "line_item_discount_applications".* FROM "line_item_discount_applications" WHERE "line_item_discount_applications"."line_item_id" = ?
# SELECT "shipping_line_discount_applications".* FROM "shipping_line_discount_applications" WHERE "shipping_line_discount_applications"."shipping_line_id" = ?
# SELECT "discounts".* FROM "discounts" WHERE "discounts"."id" IN (?, ?).
assert_queries(5) do
preloader = ActiveRecord::Associations::Preloader.new(records: [invoice], associations: [
line_items: { discount_applications: :discount },
shipping_lines: { discount_applications: :discount },
])
preloader.call
end
assert_no_queries do
assert_not_nil invoice.line_items.first.discount_applications.first.discount
assert_not_nil invoice.shipping_lines.first.discount_applications.first.discount
end
invoice.reload
invoice.line_items.map { |i| i.discount_applications.to_a }
# `line_items` and `line_item_discount_applications` are already preloaded, so we expect:
# SELECT "shipping_lines".* FROM shipping_lines WHERE "shipping_lines"."invoice_id" = ?
# SELECT "shipping_line_discount_applications".* FROM "shipping_line_discount_applications" WHERE "shipping_line_discount_applications"."shipping_line_id" = ?
# SELECT "discounts".* FROM "discounts" WHERE "discounts"."id" = ?.
assert_queries(3) do
preloader = ActiveRecord::Associations::Preloader.new(records: [invoice], associations: [
line_items: { discount_applications: :discount },
shipping_lines: { discount_applications: :discount },
])
preloader.call
end
assert_no_queries do
assert_not_nil invoice.line_items.first.discount_applications.first.discount
assert_not_nil invoice.shipping_lines.first.discount_applications.first.discount
end
end
def test_preload_through
comments = [
comments(:eager_sti_on_associations_s_comment1),

View File

@ -0,0 +1,4 @@
# frozen_string_literal: true
class Discount < ActiveRecord::Base
end

View File

@ -2,5 +2,6 @@
class Invoice < ActiveRecord::Base
has_many :line_items, autosave: true
has_many :shipping_lines, -> { from("shipping_lines") }, autosave: true
before_save { |record| record.balance = record.line_items.map(&:amount).sum }
end

View File

@ -2,4 +2,10 @@
class LineItem < ActiveRecord::Base
belongs_to :invoice, touch: true
has_many :discount_applications, class_name: "LineItemDiscountApplication"
end
class LineItemDiscountApplication < ActiveRecord::Base
belongs_to :line_item
belongs_to :discount
end

View File

@ -0,0 +1,11 @@
# frozen_string_literal: true
class ShippingLine < ActiveRecord::Base
belongs_to :invoice, touch: true
has_many :discount_applications, class_name: "ShippingLineDiscountApplication"
end
class ShippingLineDiscountApplication < ActiveRecord::Base
belongs_to :shipping_line
belongs_to :discount
end

View File

@ -313,6 +313,10 @@ ActiveRecord::Schema.define do
t.boolean :deleted
end
create_table :discounts, force: true do |t|
t.integer :amount
end
create_table :dl_keyed_belongs_tos, force: true, id: false do |t|
t.primary_key :belongs_key
t.references :destroy_async_parent
@ -547,6 +551,11 @@ ActiveRecord::Schema.define do
t.integer :amount
end
create_table :line_item_discount_applications, force: true do |t|
t.integer :line_item_id
t.integer :discount_id
end
create_table :lions, force: true do |t|
t.integer :gender
t.boolean :is_vegetarian, default: false
@ -922,6 +931,16 @@ ActiveRecord::Schema.define do
t.integer :shape_id
end
create_table :shipping_lines, force: true do |t|
t.integer :invoice_id
t.integer :amount
end
create_table :shipping_line_discount_applications, force: true do |t|
t.integer :shipping_line_id
t.integer :discount_id
end
create_table :ships, force: true do |t|
t.string :name
t.integer :pirate_id