Disabling a FactoryGirl association within a trait
Asked Answered
P

2

5

In a Rails app, I'm using FactoryGirl to define a general factory plus several more specific traits. The general case and all but one of the traits have a particular association, but I'd like to define a trait where that association is not created/built. I can use an after callback to set the association's id to nil, but this doesn't stop the association record from being created in the first place.

Is there a way in a trait definition to completely disable the creation/building of an association that has been defined for the factory the trait belongs to?

For example:

FactoryGirl.define do
  factory :foo do
    attribute "value"
    association :bar

    trait :one do
      # This has the bar association
    end

    trait :two do
      association :bar, turn_off_somehow: true
      # foos created with trait :two will have bar_id = nil
      # and an associated bar will never be created
    end
  end
end
Papal answered 8/11, 2013 at 18:2 Comment(2)
Hmm, not sure if I understand this correctly. Are you saying that you want to prohibit Rails from calling callbacks that create other associated model instances when you create a model instance when you are using FactoryGirl to create that model instance??Forecastle
@dmtri.com: I added an example, does that help explain what I'm trying to do?Papal
M
6

An association in factory_girl is just an attribute like any other. Using association :bar sets the bar attribute, so you can disable it by overriding it with nil:

FactoryGirl.define do
  factory :foo do
    attribute "value"
    association :bar

    trait :one do
      # This has the bar association
    end

    trait :two do
      bar nil
    end
  end
end
Moonset answered 5/12, 2013 at 17:49 Comment(0)
A
2

I tried @Joe Ferris' answer but appears it does not work anymore in factory_bot 5.0.0. I found this related question that referred to the strategy: :null flag that can be passed to the association like:

FactoryGirl.define do
  factory :foo do
    attribute "value"
    association :bar

    trait :one do
      # This has the bar association
    end

    trait :two do
      association :bar, strategy: :null
    end
  end
end

It seems to do the trick now.

Source code looks like it just stops any callbacks like create or build so renders the association to nothing.

module FactoryBot
  module Strategy
    class Null
      def association(runner); end

      def result(evaluation); end
    end
  end
end
Arronarrondissement answered 13/2, 2019 at 22:44 Comment(1)
I believe you can also just do bar { nil } if the association allows it re: validationsArcherfish

© 2022 - 2024 — McMap. All rights reserved.