如何为具有 has_one/belongs_to 关系且通常由嵌套属性克服的验证的模型创建工厂?
我有一个包含一个用户模型的帐户模型和一个属于帐户模型的用户模型。我认为演示所需的基本代码是:
class Account < ActiveRecord::Base
has_one :user
validates_presence_of :user
accepts_nested_attributes_for :user
end
class User < ActiveRecord::Base
belongs_to :account
# validates_presence_of :account # this is not actually present,
# but is implied by a not null requirement
# in the database, so it only takes effect on
# save or update, instead of on #valid?
end
当我在每个工厂中定义关联时:
Factory.define :user do |f|
f.association :account
end
Factory.define :account do |f|
f.association :user
end
我遇到堆栈溢出,因为每个工厂都递归地创建帐户/用户。
我能够解决这个问题的方法是在我的测试中模拟嵌套属性形式:
before :each do
account_attributes = Factory.attributes_for :account
account_attributes[:user_attributes] = Factory.attributes_for :user
@account = Account.new(account_attributes)
end
但是,我想将这个逻辑保留在工厂中,因为一旦我开始添加其他模块,它就会失控:
before :each do
account_attributes = Factory.attributes_for :account
account_attributes[:user_attributes] = Factory.attributes_for :user
account_attributes[:user_attributes][:profile_attributes] = Factory.attributes_for :profile
account_attributes[:payment_profile_attributes] = Factory.attributes_for :payment_profile
account_attributes[:subscription_attributes] = Factory.attributes_for :subscription
@account = Account.new(account_attributes)
end
请帮忙!
I have an Account model that has_one User model, and a User model that belongs_to Account model. I think that the basic code required for demonstration is:
class Account < ActiveRecord::Base
has_one :user
validates_presence_of :user
accepts_nested_attributes_for :user
end
class User < ActiveRecord::Base
belongs_to :account
# validates_presence_of :account # this is not actually present,
# but is implied by a not null requirement
# in the database, so it only takes effect on
# save or update, instead of on #valid?
end
When I define associations in each factory:
Factory.define :user do |f|
f.association :account
end
Factory.define :account do |f|
f.association :user
end
I get a stack overflow, as each is creating an account/user recursively.
The way I've been able to solve this is to emulate nested attribute forms in my tests:
before :each do
account_attributes = Factory.attributes_for :account
account_attributes[:user_attributes] = Factory.attributes_for :user
@account = Account.new(account_attributes)
end
However, I'd like to keep this logic in the factory, as it can get out of hand once I start adding other modules:
before :each do
account_attributes = Factory.attributes_for :account
account_attributes[:user_attributes] = Factory.attributes_for :user
account_attributes[:user_attributes][:profile_attributes] = Factory.attributes_for :profile
account_attributes[:payment_profile_attributes] = Factory.attributes_for :payment_profile
account_attributes[:subscription_attributes] = Factory.attributes_for :subscription
@account = Account.new(account_attributes)
end
Please help!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我能够通过使用factory_girl的after_build回调解决这个问题。
这将在保存所属类之前创建关联的类,以便验证通过。
I was able to solve this problem by using factory_girl's after_build callback.
This will create the associated classes before the owning class is saved, so validations pass.
查看factory_girl 文档。您建立这些帐户的方式似乎并没有真正利用factory_girl。
我总是通过在测试之前创建我需要的对象来处理关联。我将根据您在上面引用的模型尝试一下:
现在
@account
将具有@account.user
和@account。个人资料
可用。如果您需要定义这些,@profile = @account.profile
效果很好。Have a look at the factory_girl documentation. The way you're building those accounts seems like you're not really taking advantage of factory_girl.
I've always taken care of associations by creating the objects that I need before testing. I'm going to take a stab at this based on the models you're referencing above:
Now
@account
will have@account.user
and@account.profile
available. If you need to define those,@profile = @account.profile
works just great.