find_or_initialize_by在FactoryGirl(find_or_initiali

2019-10-19 18:42发布

我在想,如果有一个相当于find_or_initialize_by在解决德以下问题FactoryGirl:

我们的目标是,该模型使用了具有同一个国家的两个表。 我不想使用该国的顺序(因为我发现了电子邮件)。

有一个关于国家唯一性约束,但我的主要问题是,它创建国家两次相同的记录时,我再次呼吁FactoryGirl.create(:点击)

因此,在验证失败的考验。

Rspec的:

# models/click_spec.rb
describe Click do
    it "should have a valid constructor" do
        FactoryGirl.create(:click).should be_valid
    end
end

工厂:

# factories/countries.rb
FactoryGirl.define do
    factory :country do
        name "United States"
        slug "us"
    end
end

# factories/offers.rb
FactoryGirl.define do
    factory :offer do
        association :country, factory: :country
        # Other columns
    end
end

# factories/users.rb
FactoryGirl.define do
    factory :user do
        association :country, factory: :country
        # Other columns
    end
end

# factories/clicks.rb
FactoryGirl.define do
    factory :click do
        association :offer, factory: :offer
        association :user, factory: :user
        # Other columns
    end
end

模型:

class Country < ActiveRecord::Base
    validates :name, :slug,
    presence: true,
    uniqueness: { case_sensitive: false }

    validates :slug,
    length: { is: 2 }

end

Answer 1:

你应该能够使通过这项工作initialize_with

FactoryGirl.define do
  factory :country do
    name "United States"
    slug "us"
    initialize_with { Country.find_or_create_by_name(name) }
  end
end

这将始终使用同一个国家。 您可能要嵌套的工厂,让其他工厂使用不同的名称:

FactoryGirl.define do
  factory :country do
    initialize_with { Country.find_or_create_by_name(name) }
    factory :united_states do
      name "United States"
      slug "us"
    end
  end
end


Answer 2:

我面临着类似的问题,还与Country我的应用程序的模型。 这里就是我所做的。

为了确保FactoryBot的buildcreate仍然表现为它应该,我们应该只覆盖的逻辑to_create ,这样做:

factory :country do
  to_create do |instance|
    instance.attributes = Country.create_with(name: instance.name).find_or_create_by(slug: instance.slug).attributes
    instance.reload
  end

  name { "United States" }
  slug { "us" }
end

查询解释说:

Country
.create_with(name: instance.name) # if not found, create with this `name` (and `slug` defined below)
.find_or_create_by(slug: instance.slug) # find by primary key `slug'

这确保build保持它的“建筑/初始化对象”的默认行为,不执行任何数据库读取或写入所以它总是快。 只有逻辑create被覆盖,如果存在获取,而不是试图总是创造新纪录的现有记录。

原帖上https://stackoverflow.com/a/55235861/3956879 。

看看我的文章解释这一点。



文章来源: find_or_initialize_by in FactoryGirl