Skip to content

Instantly share code, notes, and snippets.

@rorcraft
Created June 21, 2011 00:08
Show Gist options
  • Save rorcraft/1036930 to your computer and use it in GitHub Desktop.
Save rorcraft/1036930 to your computer and use it in GitHub Desktop.
Factory_girl singleton monkey patch
# I put this as spec/support/factory_girl_singleton.rb
# this get required from spec_helper.rb
# creates a class variable for factories that should be only created once
class Factory
@@singletons = {}
def self.singleton(factory_key)
begin
@@singletons[factory_key] = Factory.create factory_key
rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique
end
return @@singletons[factory_key]
end
end
# Usage example
# ---------------------------
# User belongs to school
Factory.define :user do |f|
f.sequence(:login) { |n| Faker::Internet.user_name }
f.school { Factory.singleton(:school) }
end
# School admin belongs to same school
Factory.define(:school_admin, :class => "User") do |f|
f.sequence(:login) { |n| Faker::Internet.user_name }
f.role "school_admin"
f.school { Factory.singleton(:school) }
end
@diego-aslz
Copy link

I think the reason is pretty obvious. The method proposed will only work in models that have an uniqueness validation (validates_uniqueness_of), and won't, for sure, be created twice since AR will complain about it. If the model doesn't have/need this kind of validation, the line:

@@singletons[factory_key] = FactoryGirl.create(factory_key)

Will always succeed and no exception will be raised. I did this:

module FactoryGirl
  @@singletons = {}
  def self.singleton(factory_key,factory=nil)
    @@singletons[factory_key] ||= FactoryGirl.create(factory || factory_key)
  end
end

This way, I can do this:

FactoryGirl.define do
  factory :person do
    name "Test"
    domain { FactoryGirl.singleton :domain }

    factory :another_person do
      domain { FactoryGirl.singleton :second_domain, :domain }
    end
  end

  factory :product do
    name "A product"
    domain { FactoryGirl.singleton :domain }
  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment