From 8db4f20a380f6578bca45cc16b605a3dbc68ca7b Mon Sep 17 00:00:00 2001 From: Ryan McCarthy Date: Mon, 24 Jun 2024 08:20:55 -0700 Subject: [PATCH 1/2] Make pre_render compatible with all children of ActiveRecord::Relation Signed-off-by: Ryan McCarthy --- README.md | 7 +++++++ lib/blueprinter-activerecord/preloader.rb | 3 +-- test/nested_render_test.rb | 15 +++++++++++++-- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6317f4c..5c59221 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,13 @@ widgets = Widget.where(...) WidgetBlueprint.render(widgets, view: :extended) ``` +The query can also be an ActiveRecord::Associations::CollectionProxy: + +```ruby + project = Project.find(...) + WidgetBlueprint.render(project.widgets, view: :extended) +``` + If you **must** run the query first, there is a way: ```ruby diff --git a/lib/blueprinter-activerecord/preloader.rb b/lib/blueprinter-activerecord/preloader.rb index c4aea8f..45512fd 100644 --- a/lib/blueprinter-activerecord/preloader.rb +++ b/lib/blueprinter-activerecord/preloader.rb @@ -37,8 +37,7 @@ def initialize(auto: false, use: :preload, &auto_proc) # intelligently handles them. There are several unit tests which confirm this behavior. # def pre_render(object, blueprint, view, options) - case object.class.name - when "ActiveRecord::Relation", "ActiveRecord::AssociationRelation" + if object.is_a?(ActiveRecord::Relation) && !object.loaded? if object.preload_blueprint_method || auto || auto_proc&.call(object, blueprint, view, options) == true object.before_preload_blueprint = extract_preloads object blueprint_preloads = self.class.preloads(blueprint, view, object.model) diff --git a/test/nested_render_test.rb b/test/nested_render_test.rb index b755d32..8ec3b75 100644 --- a/test/nested_render_test.rb +++ b/test/nested_render_test.rb @@ -9,6 +9,7 @@ def setup customer2 = Customer.create!(name: "FOO") project1 = Project.create!(customer_id: customer1.id, name: "Project A") project2 = Project.create!(customer_id: customer2.id, name: "Project B") + project3 = Project.create!(customer_id: customer2.id, name: "Project C") category1 = Category.create!(name: "Foo") category2 = Category.create!(name: "Bar") ref_plan = RefurbPlan.create!(name: "Plan A") @@ -17,6 +18,7 @@ def setup Widget.create!(customer_id: customer1.id, project_id: project1.id, category_id: category1.id, name: "Widget A", battery1: battery1, battery2: battery2) Widget.create!(customer_id: customer1.id, project_id: project1.id, category_id: category2.id, name: "Widget B", battery1: battery1) Widget.create!(customer_id: customer2.id, project_id: project2.id, category_id: category1.id, name: "Widget C", battery1: battery1) + Widget.create!(customer_id: customer2.id, project_id: project3.id, category_id: category1.id, name: "Widget C", battery1: battery1) Blueprinter.configure do |config| config.extensions << BlueprinterActiveRecord::Preloader.new(auto: true) end @@ -24,6 +26,7 @@ def setup @sub = ActiveSupport::Notifications.subscribe 'sql.active_record' do |_name, _started, _finished, _uid, data| @queries << data.fetch(:sql) end + @test_customer = customer2 end def teardown @@ -40,7 +43,15 @@ def test_queries_with_auto assert_equal [ 'SELECT "projects".* FROM "projects"', 'SELECT "customers".* FROM "customers" WHERE "customers"."id" IN (?, ?)', - 'SELECT "widgets".* FROM "widgets" WHERE "widgets"."project_id" IN (?, ?)', + 'SELECT "widgets".* FROM "widgets" WHERE "widgets"."project_id" IN (?, ?, ?)', + ], @queries + end + + def test_queries_for_collection_proxies + ProjectBlueprint.render(@test_customer.projects.strict_loading, view: :extended_plus_with_widgets) + assert_equal [ + 'SELECT "projects".* FROM "projects" WHERE "projects"."customer_id" = ?', + 'SELECT "widgets".* FROM "widgets" WHERE "widgets"."project_id" IN (?, ?)' ], @queries end @@ -60,7 +71,7 @@ def test_queries_with_auto_and_nested_render_and_manual_preloads project_blueprint.render(q) assert_equal [ 'SELECT "projects".* FROM "projects"', - 'SELECT "widgets".* FROM "widgets" WHERE "widgets"."project_id" IN (?, ?)', + 'SELECT "widgets".* FROM "widgets" WHERE "widgets"."project_id" IN (?, ?, ?)', 'SELECT "categories".* FROM "categories" WHERE "categories"."id" IN (?, ?)', 'SELECT "customers".* FROM "customers" WHERE "customers"."id" IN (?, ?)', ], @queries From efe6db45f580432e009b388dca61e56512e91e71 Mon Sep 17 00:00:00 2001 From: Ryan McCarthy Date: Mon, 24 Jun 2024 14:34:37 -0700 Subject: [PATCH 2/2] Make CollectionProxy test valid Signed-off-by: Ryan McCarthy --- test/nested_render_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/nested_render_test.rb b/test/nested_render_test.rb index 8ec3b75..5f1dbb7 100644 --- a/test/nested_render_test.rb +++ b/test/nested_render_test.rb @@ -48,7 +48,7 @@ def test_queries_with_auto end def test_queries_for_collection_proxies - ProjectBlueprint.render(@test_customer.projects.strict_loading, view: :extended_plus_with_widgets) + ProjectBlueprint.render(@test_customer.projects, view: :extended_plus_with_widgets) assert_equal [ 'SELECT "projects".* FROM "projects" WHERE "projects"."customer_id" = ?', 'SELECT "widgets".* FROM "widgets" WHERE "widgets"."project_id" IN (?, ?)'