【问题标题】:Why can't my factory definition use another one?为什么我的工厂定义不能使用另一个?
【发布时间】:2016-08-28 05:17:48
【问题描述】:

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

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

我不知道如何正确地做到这一点,而不必在我的规范文件中使用复杂的工厂调用。

这是我的员工工厂:

require 'faker'

#Seed the database before running the tests only if in test mode
#Fixes problem with rake routes running this command and deleting out the database
Rails.application.load_seed if  Rails.env.test?

FactoryGirl.define do
  factory :employee do
    first_name { Faker::Name.first_name}
    last_name { Faker::Name.last_name}
    sequence(:email) { |n| "peterjohnson#{n}@example.com" }
    mobile 66816927867
    bio "MyText"
    address { Faker::Address.street_address}
    province_state { Faker::Address.state}
    country { Faker::Address.country}
    postal_code { Faker::Address.postcode}
    status :active
    bachelor_degree "B.Sc"
    password Faker::Internet.password(8)
    sequence(:paypal_email) { |n| "paypal_peterJohnson#{n}@example.com" }
    sequence(:skype_id) {|n| "peterjohnson_skype#{n}" }
    os :mac
    role_ids [Role.first.id]

    trait :proofreader do
        after(:create) {|employee| employee.add_role(:proofreader)}
    end

    trait :admin do
        after(:create) {|employee| employee.add_role(:admin)}
    end

    trait :super_admin do
        after(:create) {|employee| employee.add_role(:super_admin)}
    end
  end
end

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

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

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

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

我收到一条错误消息,告诉我找不到名为角色的工厂。存在如下:

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

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

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

那么如何在不播种数据库的情况下创建具有角色的 Employee 呢?

【问题讨论】:

  • rake routes 不应该碰你的工厂。你确定你说的不是rake db:resetrake db:seed
  • 我同意它不应该,但它确实如此。奇怪的是,它运行 seed.rb 文件没有明显的原因,只是在Employees.rb工厂中存在Rails.application.load_seed,这更奇怪。

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


【解决方案1】:

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

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

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

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

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

然后在 trait 的回调中添加额外的角色:

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

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

【讨论】:

  • 感谢 Dave 的代码和解释。我应该更清楚为什么我不能在某些测试中这样做。原因是我的功能测试有一个表单,它将角色显示为复选框。我需要填充这些角色,以便我可以显示复选框。我有验证检查员工必须先分配角色才能保存。所以我不能创建一个没有分配角色的员工。如果您知道正确执行此操作的方法,或者我正在做的事情还可以,那就太好了。我是一个菜鸟,也是一个尝试做事的最佳实践。
  • 我想可能就是这样。我猜你上面展示的特征是行不通的,因为你一开始就无法创建员工。如果您在after(:build) 而不是after(:create) 中创建并添加一个角色,它是否有效?您可能需要绕过 add_role 并自己将角色添加到员工。
  • 特征起作用是因为我首先为数据库播种,否则你是对的,它们不起作用。如果是这样的话,我会尝试之后再报告。
  • 我的验证需要 role_ids 存在。所以我无法构建员工对象
  • 你的意思是Employee 有一个要求员工有角色的验证吗?如果是这样,这些性状怎么可能对种子起作用?最好将您的验证添加到您的问题中。
猜你喜欢
  • 1970-01-01
  • 2015-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多