Calling methods from a FactoryGirl model in a dependent attribute
Asked Answered
A

1

6

I have a model similar to the following:

class Foo
  attr_accessor :attribute_a  # Really an ActiveRecord attribute
  attr_accessor :attribute_b  # Also an ActiveRecord attribute

  def determine_attribute_b
    self.attribute_b = some_biz_logic(attribute_a)
  end
end

In FactoryGirl 1.3, I had a factory that looked like this:

Factory.define :foo do |foo|
  foo.attribute_a = "some random value"
  foo.attribute_b { |f| f.determine_attribute_b }
end

This worked just fine. attribute_b was an attribute dependent on the code block, which would be passed a real instance of Foo into the variable f, complete with a properly set attribute_a to work off of.

I just upgraded to FactoryGirl 2.3.2, and this technique no longer works. The f variable from the equivalent code to above is no longer an instance of Foo, but instead a FactoryGirl::Proxy::Create. This class appears to be able to read the attributes previously set (such that the Dependent Attributes example in the docs still works). However, it can't call actual methods from the built class.

Is there a way I can use the technique from the old version of FactoryGirl? I want to be able to define an attribute and set its value using the result of an instance method of the built class.

Amagasaki answered 4/1, 2012 at 23:7 Comment(0)
T
4

You can use the callbacks after_create and after_build like this:

FactoryGirl.define do
  factory :foo do
    attribute_a "some random value"
    after_build do |obj|
      obj.attribute_b = obj.determine_attribute_b
    end
  end
end

Keep in mind this new FactoryGirl syntax.

Theomancy answered 16/1, 2012 at 15:56 Comment(3)
By the way - may be you should consider calling determine_attribute_b on before_create callback in you model. It seems reasonable as soon as you setting attribute_b in factory for your tests.Theomancy
not a bad idea, but in my real-life code, I can't do that. There's cases when I want to set it independently in the controller code.Amagasaki
current syntax is after(:build) doTace

© 2022 - 2024 — McMap. All rights reserved.