如何 return 使用 FactoryGirl 的现有对象

How to return an existing object with FactoryGirl

为了举例,我有一个化学元素模型

class Element < ActiveRecord::Base
  validates :name, presence: true, uniqueness: true
  validates :symbol, presence: true, uniqueness: true 
end

seeds.rb中我定义了所有已知元素

Element.where(name: "hydrogen" symbol: "H").first_or_create
...
Element.where(name: "ununoctium" symbol: "Uuo").first_or_create

我定义一个工厂

FactoryGirl.define do
  factory :element do
    name "hydrogen" 
    symbol "H"
  end
end

由于代码库依赖于所有种子元素的存在,我准备测试数据库

rake db:seed RAILS_ENV=test

现在我的工厂将永远无法运作

FactoryGirl.create(:element) #=> validation failed error

如何以首先尝试在数据库中查找可创建对象的方式编写工厂?

FactoryGirl.create(:element) #=> returns Element from db || Factory invocation  

为什么不这样做:

element = Element.find_by(name: "hydrogen") || FactoryGirl.create(:element, name: "hydrogen", symbol: "H")

为了后代,用五年的经验回答我自己的问题。

尝试使用 FactoryBot 的 initialize_with 挂钩作为 described in docs

factory :element do
  initialize_with do
    where(name: name, symbol: symbol).first_or_initialize
  end

  name "hydrogen" 
  symbol "H"
end

这个想法的一个转折点是放弃一般工厂,只为可数的 uniqueness-constrained 化学元素等资源命名工厂:

factory :element_hydrogen do
  initialize_with do
    where(name: "hydrogen", symbol: "H").first_or_initialize
  end
end