Search code examples
ruby-on-railsruby-on-rails-4callbackfactory

In Rails 4 and FactoryGirl, how do I override the base factory's "after(:build)" method?


I’m using Rails 4.2.3 with FactoryGirl. I have this factory for my users

FactoryGirl.define do
    …
  factory :user do
    after(:build) do |user, vars|
      print "in main user after build.\n"
      def user.publish
        # and here you can stub method response if you need
      end
    end

    …

    trait :with_callbacks do
      after(:build) do |user, vars|
        print "after build my user\n"
      end

      …
    end

I wanted to override my base “after(:build)” method, so I created the trait “with_callbacks.” But when I call my factory with my traits

create(:user, :my_user)

It seems like both “after(:build)” methods are getting called based on the output …

after build my user
in main user after build.

Is there a way to rig things so that I can override the base factory’s “after(:build)” method?


Solution

  • Not sure what you're trying to do, but another option would be to use a transient variable (called ignore in FactoryBot versions < 5.0) to control the behavior, which can be overwritten in a trait.

    Something like:

      transient do # use `ignore` in factory bot < 5.0
        with_callback_behavior { false }
      end
    
      after(:build) do |user, vars|
        if vars.with_callback_behavior
          puts "behavior for trait after build."
        else
          puts "behavior for main main after build."
        end
      end
      trait :with_callbacks do
        with_callback_behavior { true }
      end
    

    Of course, this means that

    build :user, :with_callbacks
    #=> "behavior for trait after build."
    

    is the same as

    build :user, with_callback_behavior: true
    #=> "behavior for trait after build."