为什么我的FactoryGirl回调会在它不应该运行时运行?

时间:2012-07-10 08:50:08

标签: ruby-on-rails factory-bot

我正在使用FactoryRirl 3.3.0和RoR 3.2.3

我有一个像这样的has_one个人资料的用户模型;

class User < ActiveRecord::Base
  has_secure_password
  has_one :profile, dependent: :destroy
  accepts_nested_attributes_for :profile, update_only: true
  attr_accessible :email, :username, :password, :password_confirmation, :profile_attributes
  before_create :build_profile
end

class Profile < ActiveRecord::Base
  attr_accessible :first_name, :last_name
  belongs_to :user
  validates :user, presence: true
  validates :first_name, presence: true, on: :update
  validates :last_name, presence: true, on: :update
end

在我的rspec测试中,我有时需要阻止before_create:build_profile运行,这样我就可以让没有配置文件的用户。我通过FactoryGirl回调管理这个

after(:build) {|user| user.class.skip_callback(:create, :before, :build_profile)}

我的用户工厂定义如下;

FactoryGirl.define do
  factory :user do
    sequence(:email) {|n| "user_#{n}@example.com"}
    sequence(:username) {|n| "user_#{n}"}
    password "secret"
    factory :user_with_profile do
      factory :new_user_with_profile do
        before(:create) {|user| user.activated = false}
      end
      factory :activated_user_with_profile do
        before(:create) {|user| user.activated = true}
      end
    end
    factory :user_without_profile do
      after(:build) {|user| user.class.skip_callback(:create, :before, :build_profile)}
      factory :new_user_without_profile do
        before(:create) {|user| user.activated = false}
      end
      factory :activated_user_without_profile do
        before(:create) {|user| user.activated = true}
      end
    end
  end
end

我的期望是:new_user_without_profile:activated_user_without_profile会继承after(:build)来自:user_without_profile的回调,而:new_user_with_profile:activated_user_with_profile工厂则不会,但它不是那样的工作。这是从控制台中摘录来演示我的问题;

irb(main):001:0> user = FactoryGirl.create :new_user_with_profile
irb(main):002:0> user.profile
=> #<Profile id: 11, first_name: "", last_name: "", created_at: "2012-07-10 08:40:10", updated_at: "2012-07-10 08:40:10", user_id: 18>
irb(main):003:0> user = FactoryGirl.create :new_user_without_profile
irb(main):004:0> user.profile
=> nil
irb(main):005:0> user = FactoryGirl.create :new_user_with_profile
irb(main):006:0> user.profile
=> nil

所以,我第一次创建:new_user_with_profile时,会按预期创建一个配置文件,但第二次创建一个:new_user_without_profile之后,它就不再了! after(:build)回调似乎没有被再次调用(如果我添加一些代码来输出东西,我在终端中看不到它)。我不知道这里出了什么问题。还有其他人吗?

1 个答案:

答案 0 :(得分:2)

这是一个肮脏的解决方案,但您是否尝试在factory :user_with_profile中编写回调定义:

after(:build) {|user| user.class.set_callback(:create, :before, :build_profile)}

有效吗?