Abraham P
Abraham P

Reputation: 15471

FactoryGirl not respecting callback order

Broken Case

I have the following class

 class Vehicle < ActiveRecord::Base
     belongs_to :manufacturer
     belongs_to :production_plant
     before_save :delegate_audit_number

     attr_accessible :manufacturer_id, :production_plant_id, :audit_number
     private

        def delegate_audit_number
          self.audit_number ||= self.manufacturer.audits.last.try(:number)
        end
 end

and the following factory

  FactoryGirl.define do
    factory :vehicle do
      association :production_plant, factory: :production_plant
      after(:validation) do |v|
        v.manufacturer_id = v.production_plant.manufacturer_id
      end
    end
  end

Then calling FactoryGirl.create(:vehicle) fails in the before_save with

          Failure/Error: @vehicle = FactoryGirl.create(:vehicle)
             NoMethodError:
               undefined method `audits' for nil:NilClass

By debugging, I have discovered two things:

1) the manufacturer method is nil in the before_save callback

2) The after_validation callback is never hit.

Working Case

Identical in every way to the broken case, except the before_save is moved out into an observer

class AuditNumberObserver < ActiveRecord::Observer
  observe :vehicle

  def before_save(entity)
    entity.audit_number ||= entity.manufacturer.audits.last.try(:number)
  end
end

Now it is my understanding (based on the following list in the documentation: http://guides.rubyonrails.org/v3.2.9/active_record_validations_callbacks.html#available-callbacks )

That after_validation should happen before before_save

Why is factory girl not respecting the callback chain in the first case? Why is factory girl respecting the callback chain in the second case? What is the difference?

Upvotes: 0

Views: 232

Answers (1)

backpackerhh
backpackerhh

Reputation: 2353

I think your problem is the use of after(:validation) in the factory.

According to FactoryGirl's README, this callback is not defined by the gem.

Upvotes: 1

Related Questions