将多个 FactorGirl 模型与一个主"公司"模型相关联



我在RSPEC中使用了很多工厂女孩,但本月我的任务是在我们的测试套件中实现Cucumber故事。我想我可能有一个不太确定的问题。

我们的"主"账户模型称为"公司"。用户、员工等都属于这个范畴。一些直接通过f/k,另一些通过授权。我们使用factory girl的旧方法设置了许多与factory girl构建的模型的实例变量。

即在"spec_helper.rb"中

@grade_system = FactoryGirl.create(:grade_system)
@asset_size = FactoryGirl.create(:asset_size)
@asset_size.grades.create!(FactoryGirl.attributes_for(:grade))
@company = FactoryGirl.create(:company, :asset_size => @asset_size, :grade_system => @grade_system)

这真是太愚蠢了。

当我试图修复具有正确关联的工厂时,我总是遇到一个错误,即"属性已经定义:association"。我猜是因为一个用户创建了一个属于员工的工厂,这两个工厂都是由具有关联的工厂创建的:company,导致了冲突。但这并不是唯一的例子。我想我的问题是,在这种情况下最好的做法是什么。我觉得如果我能删掉一家公司,并将其分配给所有需要它的工厂,这可能会奏效,或者将所有适当的关联都塞进公司工厂,但无法用FactoryGirl.build(:user)建立用户……或者我只是错过了关联如何运作的要点?

FactoryGirl.define do
factory :company do
sequence(:name)                    { |n|  "Company#{n}" }
sequence(:subdomain)               { |n| "subdomain#{n}" }  
first_time_setup                   false
non_exempt_multiplier              1.2
exempt_multiplier                  1.2
executive_multiplier               1.2
primary_contact_first_name         'Jarrett'
primary_contact_last_name          'Green'
primary_contact_email              'tes@test.com'
primary_contact_phone              '(555) 555-5555'
hours_considered_part_time         30
hours_considered_full_time         40
association :industry
association :grade_system
association :asset_size
end
end
######################################
FactoryGirl.define do
require 'faker'
factory :employee do
association :company
association :position
association :branch
first_name                Faker::Name.first_name
last_name                 'Smith'
pay_basis                 'salary'
current_salary            10000.00
date_in_position          (Date.today)
sequence(:internal_id)    { |n| n }  
user
end
end
############################################################
FactoryGirl.define do
factory :user do
association :company 
sequence(:login)          {|l|  "user#{l}@test.com"}
sequence(:first_name)     {|fn| "UserFirstName#{fn}"}
sequence(:last_name)      {|ln| "UserLastName#{ln}"}
password                  'thisisthepassword'
password_confirmation     'thisisthepassword'
end
end

处理这一问题的一种有趣方法是使用Fixture作为父记录,然后在工厂中定义它们。为每个模型创建一个有效的夹具,然后您可以在工厂定义中分配它,如下所示:

association : grade_system { GradeSystem.find(12345678) }

其中数字是设备的id。

这种方法有一些好处。首先,它很快,因为您不会每次创建子项时都创建父记录,所以在测试运行开始时会加载一次fixture,并在整个过程中保持不变。其次,这很容易,每个fixture都会根据fixture的名称获得一个id编号-每次运行都是一样的,所以你可以放心直接使用find-它们还可以很容易地链接关联,所以在构建工厂时不需要创建父项的父项。第三,它是灵活的,如果在创建或构建工厂时需要测试,您可以随时传入另一个父级。

您可以避免固定装置的大多数问题,因为您只创建每种类型中的一种作为父项使用。

最新更新