Skip to content

Instantly share code, notes, and snippets.

@hiasinho
Last active May 27, 2020 18:31
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save hiasinho/0ed0567dfc091047dc26 to your computer and use it in GitHub Desktop.
Save hiasinho/0ed0567dfc091047dc26 to your computer and use it in GitHub Desktop.
FactoryGirl strategy for adding find & find_or_create
## http://stackoverflow.com/questions/7145256
module FactoryGirl
module Strategy
class Find
def association(runner)
runner.run
end
def result(evaluation)
build_class(evaluation).where(get_overrides(evaluation)).first
end
private
def build_class(evaluation)
evaluation.instance_variable_get(:@attribute_assigner).instance_variable_get(:@build_class)
end
def get_overrides(evaluation = nil)
return @overrides unless @overrides.nil?
evaluation.instance_variable_get(:@attribute_assigner).instance_variable_get(:@evaluator).instance_variable_get(:@overrides).clone
end
end
class FindOrCreate
def initialize
@strategy = FactoryGirl.strategy_by_name(:find).new
end
delegate :association, to: :@strategy
def result(evaluation)
found_object = @strategy.result(evaluation)
if found_object.nil?
@strategy = FactoryGirl.strategy_by_name(:create).new
@strategy.result(evaluation)
else
found_object
end
end
end
end
register_strategy(:find, Strategy::Find)
register_strategy(:find_or_create, Strategy::FindOrCreate)
end
@hiasinho
Copy link
Author

hiasinho commented Jan 5, 2015

Another solution for this question on stackoverflow.

@d-acuna
Copy link

d-acuna commented Sep 22, 2016

but, how to use this.? where import it?

@mklbtz
Copy link

mklbtz commented Mar 2, 2017

Late to the game, but...
Defining a strategy like this automatically allows you to use it everywhere you'd normally use create or build or build_stubbed. The calls to register_strategy are what do this. In other words, if you require this in your spec_helper.rb, you'll be able to do things like:

extend FactoryGirl::Syntax::Methods
require "factory_girl_strategy_find_or_create.rb"

user = find_or_create(:user, username: "mklbtz")

factory(:user) do
  # ...
  after(:find_or_create) do
    # ...
  end
end

@gee-forr
Copy link

gee-forr commented Apr 4, 2017

This is great, except it doesn't work with traits

@rodrigobdz
Copy link

For gem version 4.8.2 onwards the snippet should reference to FactoryBot.

@sdelrio0
Copy link

sdelrio0 commented Nov 9, 2017

Super helpful 👍 thanks

@vitali84
Copy link

Thanks!

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