FactoryGirl在列表中创建列表 - 连接表

时间:2014-09-02 13:54:43

标签: ruby-on-rails ruby rspec factory-bot

我有一个连接模型,我想创建十个测试实例。我想要八个独特的,两个不是。

该表称为job_locations,每个实例都有一个作业ID和一个位置ID。我希望十个作业中的两个使用相同的位置ID。

我正在尝试与工厂女孩这样做,但不必费力地手工写出来。

我最接近的就是这个,我想象的并不是很接近,特别是因为我甚至没有开始理解我将如何获取独特的记录。

job_locations = FactoryGirl.create_list(:job_location, 10, job: FactoryGirl.create_list(:job, 10), location: FactoryGirl.create_list(:location, 10)) 

由于

2 个答案:

答案 0 :(得分:1)

查看create_list的自述文件和规范我不认为它将数组作为默认值。除非该功能未经测试且当然没有记录,否则在这种情况下引导清楚......

这样的事情会更冗长,但声明性更强。

jobs = FactoryGirl.create_list(:job, 10)
locations = []; job_locations = []
jobs.each do |job|
  locations << location = FactoryGirl.create_list(:location, 10)
  job_locations << FactoryGirl.create(:job_location, 10, job: job, location: location)
end

并且可以轻松地将单个项目编入索引。

或者编写自己的create_list帮助程序,如下所示:

def factory_create_list(name, count, params)
  list_params = params.delete(:list_params)
  (0..count-1).each_with_object([]) do |i, arr|
    build_params = params.merge(list_params.map { |p| p[i] })
    arr << FactoryGirl.create(name, build_params)
  end
end

factory_create_list(:thing, 20, user: user1, list_params: { location: [...], another_thing: [...] })

(未测试)。

但是考虑建立或抄袭而不是尽可能地创造速度。 (减少数据库访问。)此外,您的解决方案是一个非常长,不可穿透的线。通过将事物分配给变量然后在最后一行组装它们来拆分它,为清楚起见。你会在2个月内感谢自己。

答案 1 :(得分:1)

首先,让我们通过使用将填充其JobLocation关联的特征来简化job的构建:

FactoryGirl.define do
  factory :job_location do
    # Attributes here

    trait :with_job do
      job   { build(:job) }
    end
  end
end

现在,您可以致电FactoryGirl.build(:job_location, :with_job),它会返回JobLocation已为您构建Job。这不是必需的,但它可以帮助您免于编写FactoryGirl.build(:job_location, job: FactoryGirl.build(:job)),这种可读性要低得多。

您可以使用以下代码构建(或创建,如果您需要持久化记录)对象:

locations     = FactoryGirl.build_list(:location, 8) + 
  FactoryGirl.build_list(:location, 1)*2

job_locations = locations.map do |location|
  FactoryGirl.build(:job_location, :with_job, location: location)
end

首先,构造一个Location个对象的数组。它构建了8个唯一的对象,然后连接了2个相同对象的数组,之后你可以很容易地构建JobLocation个对象的数组。