Factory_girl,关联和after_initialize问题 [英] Problem with Factory_girl, association and after_initialize

查看:66
本文介绍了Factory_girl,关联和after_initialize问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个如此定义的Family类:

I have a Family class so defined:

class Family < ActiveRecord::Base
  after_initialize :initialize_family
  belongs_to :user
  validates :user, 
       :presence => true

  validates :name,   
       :presence => true,          
       :length => { :maximum => 30 },
       :format => { :with => /\A[a-zA-Z0-9\-_\s\']+\z/i}

  def initialize_family
    if self.name.blank? && self.user
        self.name = "#{self.user.profile_full_name}'s Family"
    end
  end
end

在我的factory.rb中,我有:

In my factories.rb I have:

Factory.define :family do |f|
   f.association :user, :factory => :user
end

在我的family_spec.rb中,

In my family_spec.rb I have

let(:family) { Factory(:family) }

但这失败了:

1) Family is valid with valid attributes
     Failure/Error: let(:family) { Factory(:family) }
     ActiveRecord::RecordInvalid:
       Validation failed: Name can't be blank, Name is invalid, Languages can't be blank, Languages is too short (minimum is 1 characters)
     # ./spec/models/family_spec.rb:8:in `block (2 levels) in <top (required)>'
     # ./spec/models/family_spec.rb:10:in `block (2 levels) in <top (required)>'

使用调试器,我可以看到在after_initialize被称为self.user时为nil.为什么会这样呢? 如果我用create或new来称呼这个家庭,一切都会很好.

Using the debugger I can see that when after_initialize is called self.user is nil. Why is this happening? If I call the family with create or new everything works fine.

感谢您的帮助.

推荐答案

这是我从乔·费里斯那里得到的答案:

This is the answer I got from Joe Ferris:

factory_girl不会将参数传递给构造函数.它在上使用#user = 您的模型,并在不带任何参数的情况下实例化它.

factory_girl doesn't pass arguments to the constructor. It uses #user= on your model, and instantiates it without any arguments.

这是本·休斯(Ben Hughes)的

and this one from Ben Hughes:

要详细说明乔在说什么,将调用after_initialize方法 在对象初始化后立即执行,而那时用户确实还没有 已设置.

To elaborate on what Joe is saying, after_initialize methods are called immediately upon object initialization, and that time indeed user has not been set.

因此,例如,这将起作用:

So for example while this will work:

family = Family.create!(:user => @user) # or @user.families.create ...

这不会(这是factory_girl在后台执行的操作):

This will not (which is what factory_girl is doing under the hood):

family = Family.new
family.user = @user
family.save!

一般来说,您想要使用after_initialize时要格外小心,因为 请记住,这是在每个对象初始化上调用的.全家福 在1,000个对象上将导致被调用1,000次.

Just in general you want to be real careful using after_initialize, as remember this is called on every object initialization. A Family.all call on 1,000 objects will cause that to get called 1,000 times.

在这种情况下,您最好使用 before_validation而不是after_initialize.

Sounds like in this instance you might be better of using a before_validation instead of after_initialize.

以下语法也可以在rspec中进行测试:

The following syntax also works for testing in rspec:

let (:family) { Family.create(:user => @user) }

这篇关于Factory_girl,关联和after_initialize问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆