Factory将创建一个具有角色的对象,但不是两个

时间:2014-01-04 01:47:48

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

我正在使用rolify与用户模型和任务模型(Rails 4)。用户可以拥有的角色之一是“所有者”。我想使用Factory Girl来创建用户对象并为其分配角色。这是我的工厂:

FactoryGirl.define do

  factory :task do  
    owner "Steve"
    agency "an agency"
    facility "a facility"
    description "This task must absolutely be done"
    due_date "2013-12-22 03:57:37"
    completed_date "2013-12-22 03:57:37"

    factory :task_with_owner do
      ignore do
        user_id nil
      end

      after(:create) do |task, user_id|
        User.find(user_id).add_role :owner, task
      end
    end 
  end
end

此规范通过:

  it 'is capable of creating a valid object with owner' do
    @user = create(:user)
    task = create(:task_with_owner, user_id: @user.id)
    expect(@user.has_role? :owner, task).to be_true
  end

此规范失败:

  it 'is capable of creating two valid objects with an owner' do
    @user = create(:user, username: 'janeblow')
    task = create(:task_with_owner, user_id: @user.id)
    expect(@user.has_role? :owner, task).to be_true
    task = create(:task_with_owner, user_id: @user.id)
    expect(@user.has_role? :owner, task).to be_true
  end

错误是:

Failure/Error: task = create(:task_with_owner, user_id: @user.id)                                   
ActiveRecord::RecordNotFound:                                                                       
  Couldn't find User with id=#<#<Class:0x000000050f5e10>:0x00000004c9ed08>                          
 # ./spec/factories/tasks.rb:19:in `block (4 levels) in <top (required)>'                            
 # ./spec/models/role_spec.rb:15:in `block (2 levels) in <top (required)>'

为什么?

1 个答案:

答案 0 :(得分:1)

你的after(:create)块看起来有点不对劲。尝试将其更改为以下内容:

after(:create) do |task, vars|
  User.find(vars.user_id).add_role :owner, task
end

然后重新运行失败的规范。

因为您告诉工厂忽略传入的user_id并改为使用nil,所以在after(:create)块中,您必须从传入的属性中访问它(在第二个块参数,本例中为vars)。你几乎就在那里,但是传递了对象factory_girl用来保存属性,而不是属性本身。

有关其他示例,请参阅此处的Transient Attributes部分 - https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md