From 1b81d5dc258e5f1ad25c5109cb4bf3f6be83deb4 Mon Sep 17 00:00:00 2001 From: Josh Clayton Date: Thu, 3 Feb 2022 21:41:09 -0500 Subject: [PATCH] Fix strategy tracking through associations What? ===== Within FactoryBot::Evaluator, the build strategy was reported either as a class OR symbol. A side-effect of this is misreporting within ActiveSupport::Notifications hooks, since the instrumentation payload may have strategies listed as e.g. `:create` or `FactoryBot::Strategy::Create`, even though they semantically represent the same information. This introduces a new instance method for all strategies, `to_sym`, to be called rather than `class`. --- lib/factory_bot/evaluator.rb | 2 +- lib/factory_bot/strategy/attributes_for.rb | 4 ++++ lib/factory_bot/strategy/build.rb | 4 ++++ lib/factory_bot/strategy/create.rb | 4 ++++ lib/factory_bot/strategy/null.rb | 4 ++++ lib/factory_bot/strategy/stub.rb | 4 ++++ .../activesupport_instrumentation_spec.rb | 14 ++++++++++++++ 7 files changed, 35 insertions(+), 1 deletion(-) diff --git a/lib/factory_bot/evaluator.rb b/lib/factory_bot/evaluator.rb index e2628a4..70e7ef2 100644 --- a/lib/factory_bot/evaluator.rb +++ b/lib/factory_bot/evaluator.rb @@ -24,7 +24,7 @@ module FactoryBot def association(factory_name, *traits_and_overrides) overrides = traits_and_overrides.extract_options! strategy_override = overrides.fetch(:strategy) { - FactoryBot.use_parent_strategy ? @build_strategy.class : :create + FactoryBot.use_parent_strategy ? @build_strategy.to_sym : :create } traits_and_overrides += [overrides.except(:strategy)] diff --git a/lib/factory_bot/strategy/attributes_for.rb b/lib/factory_bot/strategy/attributes_for.rb index c4273a0..9b0b8df 100644 --- a/lib/factory_bot/strategy/attributes_for.rb +++ b/lib/factory_bot/strategy/attributes_for.rb @@ -8,6 +8,10 @@ module FactoryBot def result(evaluation) evaluation.hash end + + def to_sym + :attributes_for + end end end end diff --git a/lib/factory_bot/strategy/build.rb b/lib/factory_bot/strategy/build.rb index e652852..d18bb8f 100644 --- a/lib/factory_bot/strategy/build.rb +++ b/lib/factory_bot/strategy/build.rb @@ -10,6 +10,10 @@ module FactoryBot evaluation.notify(:after_build, instance) end end + + def to_sym + :build + end end end end diff --git a/lib/factory_bot/strategy/create.rb b/lib/factory_bot/strategy/create.rb index 1e66e58..c9371f4 100644 --- a/lib/factory_bot/strategy/create.rb +++ b/lib/factory_bot/strategy/create.rb @@ -13,6 +13,10 @@ module FactoryBot evaluation.notify(:after_create, instance) end end + + def to_sym + :create + end end end end diff --git a/lib/factory_bot/strategy/null.rb b/lib/factory_bot/strategy/null.rb index 893826f..758b031 100644 --- a/lib/factory_bot/strategy/null.rb +++ b/lib/factory_bot/strategy/null.rb @@ -6,6 +6,10 @@ module FactoryBot def result(evaluation) end + + def to_sym + :null + end end end end diff --git a/lib/factory_bot/strategy/stub.rb b/lib/factory_bot/strategy/stub.rb index 8ff1ff4..a2f9aef 100644 --- a/lib/factory_bot/strategy/stub.rb +++ b/lib/factory_bot/strategy/stub.rb @@ -41,6 +41,10 @@ module FactoryBot end end + def to_sym + :stub + end + private def next_id diff --git a/spec/acceptance/activesupport_instrumentation_spec.rb b/spec/acceptance/activesupport_instrumentation_spec.rb index 0f133d1..6ad0687 100644 --- a/spec/acceptance/activesupport_instrumentation_spec.rb +++ b/spec/acceptance/activesupport_instrumentation_spec.rb @@ -16,6 +16,10 @@ describe "using ActiveSupport::Instrumentation to track factory interaction" do let(:user_factory) { FactoryBot::Internal.factory_by_name("user") } before do define_model("User", email: :string) + define_model("Post", user_id: :integer) do + belongs_to :user + end + FactoryBot.define do factory :user do email { "john@example.com" } @@ -24,6 +28,12 @@ describe "using ActiveSupport::Instrumentation to track factory interaction" do after(:build) { Kernel.sleep(0.1) } end end + + factory :post do + trait :with_user do + user + end + end end end @@ -55,6 +65,9 @@ describe "using ActiveSupport::Instrumentation to track factory interaction" do FactoryBot.build_list(:user, 5) FactoryBot.create_list(:user, 2) FactoryBot.attributes_for(:slow_user) + user = FactoryBot.create(:user) + FactoryBot.create(:post, user: user) + FactoryBot.create_list(:post, 2, :with_user) end expect(tracked_invocations[:slow_user][:build]).to eq(2) @@ -62,5 +75,6 @@ describe "using ActiveSupport::Instrumentation to track factory interaction" do expect(tracked_invocations[:slow_user][:factory]).to eq(slow_user_factory) expect(tracked_invocations[:user][:build]).to eq(5) expect(tracked_invocations[:user][:factory]).to eq(user_factory) + expect(tracked_invocations[:user][:create]).to eq(5) end end