How can I define a method on a FactoryGirl factory?
Asked Answered
D

3

10

How can I define a normal method for use in one of my FactoryGirl factories? For instance:

FactoryGirl.define do
  def silly_horse_name
   verbs = %w[brunches dribbles haggles meddles]
   nouns = %w[landmines hamlets vandals piglets]
   "#{verbs.sample} with #{nouns.sample}".titleize
  end

  factory :racehorse do
    name { silly_horse_name } # eg, "Brunches with Landmines"

    after_build do |horse, evaluator|
      puts "oh boy, I built #{silly_horse_name}!"
    end

  end
end

Doing it this way does not call silly_horse_name at all; if it's redefined to raise 'hey!', nothing happens.

I'm using FactoryGirl 2.5.2.

Danie answered 1/8, 2012 at 13:47 Comment(0)
B
4

The best solution I could find that didn't pollute the global namespace was to define it in a module. E.g.,

module FactoryHelpers
  extend self

  def silly_horse_name
    ...
  end
end

FactoryGirl.define do
  factory :racehorse do
    name { silly_horse_name }
  end
end

Source

Balbur answered 23/1, 2014 at 4:10 Comment(1)
Do you have to include the FactoryHelpers module in the factory somehow? Using the above, I see undefined method silly_horse_name for #<FactoryGirl::SyntaxRunner:0x007fd3b161cd30>Brundisium
I
2

OK, here's my two cents (please note that there are subtle differences to Steve's answer):

# /spec/factory_helpers.rb:

module FactoryHelpers
  extend self

  def silly_penguin_name # who says penguins can't be silly too?!
    ...
  end
end

# /spec/factories.rb:

require 'factory_helpers'

FactoryGirl.define do

  factory :racepenguin do
    name { FactoryHelpers.silly_penguin_name }
  end

end

By the way, I am on FactoryGirl version 4.8.0 and Rails version 4.2.0.

Interpose answered 21/2, 2017 at 12:7 Comment(0)
E
1

My suggestion would be to define that method on main. So just move it to the top of your file outside of the FactoryGirl.define block.

Eliseelisee answered 1/8, 2012 at 13:49 Comment(2)
That works. It's going into the global namespace, but it's only defined in the test environment, and if the name is unique enough, it may not matter.Danie
I don't like this solution at all, but tried and couldn't find another solution. What confuses me most about it is that The FG documentation implies this is possible by using this example: after(:build) { |user| do_something_to(user) }Lachrymal

© 2022 - 2024 — McMap. All rights reserved.