为什么我的工厂定义不能使用另一个?

时间:2016-08-28 05:17:48

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

我在Rails 4.2应用程序中使用Rolify gem。

我在工厂使用种子数据。但是,根据我的阅读,这不是正确的方法。

我无法在我的规范文件中使用复杂的工厂调用,无法正确理解如何正确执行此操作。

这是我的员工工厂:

factory :employee do
  ["proofreader", "admin", "super_admin"].each do |role|
      FactoryGirl.create(:role, name: role)
  end
  first_name { Faker::Name.first_name}
  ...

我需要在Employee之前创建角色,以便我可以在Employee模型中保存他们的ID。

在我的应用程序中,当员工注册时,通过表单添加角色。所以我不能在创建之后为某些测试添加角色。

如果我在Employee工厂中创建角色,如下所示:

FactoryGirl.define do
  factory :role do
    name :proofreader
  end
end

我收到错误告诉我它找不到工厂命名的角色。它存在如下:

class Employee < ActiveRecord::Base
  # returns the full name of the employee. This code is found in a concern called name.rb
  include Name

  rolify

  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable


  enum status: [:active, :vacation, :unemployed]

    enum os: [:mac, :windows]

    validates :first_name, 
            presence: true,
            length: {minimum: 2}

  validates :last_name, 
            presence: true,
            length: {minimum: 2}

    validates :email, email: true, presence: true, uniqueness: true
  validates :paypal_email, email: true, presence: true, uniqueness: true
  validates :skype_id, presence: true, uniqueness: true
  validates :mobile, presence: true, numericality: true, length: {minimum: 10}
  validates :address, :province_state, :country, :postal_code, :bachelor_degree, :os,:status, :role_ids,  presence: true 



end

这是我的员工模型,它验证员工必须具有角色:

s.get(example.com.au/blah/menu.asp)

那么如何创建一个没有为数据库设置角色的员工呢?

1 个答案:

答案 0 :(得分:1)

当factory_girl读取FactoryGirl.create(:role)工厂定义时,您正在尝试:employee:employee工厂位于employee.rb:role工厂位于role.rb(或类似名称),而factory_girl可能按文件名的字母顺序读取工厂定义,因此定义:employee:role尚不存在。

在定义了所有工厂之后,您需要在测试运行时创建所有角色。

:employee工厂中,更改初始化role_ids的方式:

role_ids { [(Role.first || FactoryGirl.create(:role, name: :default)).id] }

(实际上,您应该只能设置roles而不是role_ids,这样您就不必在默认角色上调用.id。)

然后在特征的回调中添加其他角色:

trait :proofreader do
  after(:create) do |employee|
    FactoryGirl.create :role, name: :proofreader
    employee.add_role(:proofreader)
  end
end

但是,假设您的角色没有改变,除非您的应用程序代码也发生变化,我会使用种子。这会简单得多,而且我不知道为什么会出错。我已经在几个项目中用种子完成了它并且效果很好。