gpt4 book ai didi

ruby-on-rails-3 - Factory_girl、关联和 after_initialize 的问题

转载 作者:行者123 更新时间:2023-12-02 09:39:23 25 4
gpt4 key购买 nike

我有一个这样定义的 Family 类:

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

在我的工厂.rb 中,我有:

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

在我的 family_spec.rb 中,我有

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 给家人打电话,一切都会正常。

感谢您的帮助。

最佳答案

这是我从 Joe Ferris 那里得到的答案:

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

还有本·休斯 (Ben Hughes) 的这一篇:

为了详细说明 Joe 所说的内容,调用了 after_initialize 方法对象初始化后立即执行,而此时用户确实还没有已设置。

例如,虽然这可行:

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

这不会(这就是factory_girl在幕后做的事情):

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

一般来说,使用 after_initialize 时要非常小心,因为请记住,这是在每个对象初始化时调用的。一家人的呼唤对 1,000 个对象将导致调用 1,000 次。

听起来在这种情况下你最好使用before_validation 而不是 after_initialize。

以下语法也适用于 rspec 中的测试:

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

关于ruby-on-rails-3 - Factory_girl、关联和 after_initialize 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5916162/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com