工厂女孩:使用序列内联vs不内联

时间:2012-01-04 13:29:11

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

有两种方法可以在工厂女孩中使用序列:

Factory.sequence :my_id do |n|
  "#{n}"
end

Factory.define :my_object do |mo|
  mo.id        Factory.next :my_id
end

并简单地内联:

Factory.define :my_object do |mo|
  mo.sequence(:id)    { |n| "#{n}" }
end

我的问题是这个。如果我在两个不同的工厂中使用内联版本,那么会有两个不同的序列,它们从1开始并以串联方式递增...这意味着如果我创建每种类型的工厂对象中的一个,它们都将具有id 1?

如果我在两个不同的工厂中使用外部定义的序列,我保证在两个对象中获得唯一的ID吗?意思是每个对象的ID是不同的吗?

我正在尝试确认上述行为是否准确,因为我正在使用一个完全愚蠢的数据模型试图获得rspec&工厂女孩玩得很好。数据库的设计者进行设置,以便不同的对象必须生成在一组不相关的对象中唯一的id。此时更改数据模型并不是一个可行的解决方案,但我真的很想将这些内容拖回Rails。

2 个答案:

答案 0 :(得分:4)

在两个不同的工厂中使用外部定义的序列时,您会看到工厂中的递增ID。但是,当使用内联序列时,每个工厂都有自己的序列。

我在下面创建了示例rake任务来说明这一点。它显示以下结果:

*** External FactoryGirl Sequence Test Results ***
User Name: Name 1
User Name: Name 2
User Name: Name 3
User Name: Name 4
Role: Name 5
Role: Name 6
Role: Name 7
Role: Name 8
*** Internal FactoryGirl Sequence Test Results ***
User Name: Name 1
User Name: Name 2
User Name: Name 3
User Name: Name 4
Role: Role 1
Role: Role 2
Role: Role 3
Role: Role 4

正如您所看到的,当您使用外部序列时,当您从用户移动到角色时,数字会继续增加。但是,当使用内联序列时,增量彼此独立。

此示例使用了以下模式文件:

create_table "users", :force => true do |t|
  t.string   "name"
  t.string   "email"
end

create_table "roles", :force => true do |t|
  t.string   "name"
end

示例rake任务是:

require 'factory_girl_rails'
namespace :sequencetests do
  Rake::Task[:environment].invoke
  task :external do
    FactoryGirl.factories.clear
    desc "Factory Girl Sequence Test using an externally defined sequence"
    puts "*** External FactoryGirl Sequence Test Results ***"
    FactoryGirl.define do
      sequence :name do |n|
        "Name #{n}"
      end
      factory :user do |u|
        name
      end

      factory :role do |r|
        name
      end
    end

    users = buildit(:user)
    roles = buildit(:role)

    puts( showit(users, "User Name: "))
    puts( showit(roles, "Role: "))
  end

  task :inline do
    FactoryGirl.factories.clear
    puts "*** Internal FactoryGirl Sequence Test Results ***"
    desc "Factory Girl Sequence Test using an inline sequence"
    FactoryGirl.define do
      factory :user do |u|
        u.sequence(:name) {|n| "Name #{n}" }
      end

      factory :role do |r|
        r.sequence(:name) {|n| "Role #{n}" }
      end
    end

    users = buildit(:user)
    roles = buildit(:role)

    puts( showit(users, "User Name: "))
    puts( showit(roles, "Role: "))

  end

end
task sequencetests: ['sequencetests:external', 'sequencetests:inline']

def buildit(what)
  items = []
  4.times do
    items << FactoryGirl.build(what)
  end
  items
end


def showit(items, prefix = "Name: ")
  results = ""
  items.each do |item|
    results += "#{prefix}#{item.name}\n"
  end
  results
end

我希望这有助于解释在FactoryGirl中使用序列时的不同可能性。

答案 1 :(得分:2)

是的,内联版本将创建2个独立序列,每个序列从1

开始