[英]FactoryGirl association model trouble: “SystemStackError: stack level too deep”
I am using Ruby on Rails 3.0.9, RSpec-rails 2 and FactoryGirl. 我正在使用Ruby on Rails 3.0.9,RSpec-rails 2和FactoryGirl。 I am trying to state a Factory association model but I am in trouble.
我试图陈述一个工厂协会模型,但我遇到了麻烦。
I have a factories/user.rb
file like the following: 我有一个
factories/user.rb
文件,如下所示:
FactoryGirl.define do
factory :user, :class => User do
attribute_1
attribute_2
...
association :account, :factory => :users_account, :method => :build, :email => 'foo@bar.com'
end
end
and a factories/users/account.rb
file like the following: 和一个
factories/users/account.rb
文件如下:
FactoryGirl.define do
factory :users_account, :class => Users::Account do
sequence(:email) {|n| "foo#{n}@bar.com" }
...
end
end
The above example works as expected in my spec files, but if in the factory :users_account
statement I add the association :user
code so to have 上面的示例在我的spec文件中按预期工作,但如果在
factory :users_account
语句我添加了association :user
代码以便有
FactoryGirl.define do
factory :users_account, :class => Users::Account do
sequence(:email) {|n| "foo#{n}@bar.com" }
...
association :user
end
end
I get the following error: 我收到以下错误:
Failure/Error: Unable to find matching line from backtrace
SystemStackError:
stack level too deep
How can I solve that problem so to access associated models from both sides\\factories (that is, in my spec files I would like to use RoR association model methods like user.account
and account.user
) ? 如何解决这个问题,以便从双方\\工厂访问相关模型 (也就是说,在我的spec文件中,我想使用像
user.account
和account.user
这样的RoR关联模型方法) ?
PS: I read the Factory Girl and has_one question and my case is very close to the case explained in the linked question. PS:我读过“ 工厂女孩”并且有一个问题,我的案子与链接问题中解释的情况非常接近。 That is, I have an
has_one
association too (between User
and Users::Account
classes). 也就是说,我也有一个
has_one
关联(在User
和Users::Account
类之间)。
According to the docs , you can't just put both sides of the associations into the factories. 根据文档 ,你不能只把协会的两边都放进工厂。 You'll need to use their after callback to set an object(s) to return.
您需要使用它们的after回调来设置要返回的对象。
For instance, in the factories/users/account.rb
file, you put something like 例如,在
factories/users/account.rb
文件中,你可以输入类似的内容
after(:build) do |user_account, evaluator|
user_account.user = FactoryGirl.build(:user, :account=>user_account)
end
For has_many associations, you'll need to use their *_list functions. 对于has_many关联,您需要使用他们的* _list函数。
after(:build) do |user_account, evaluator|
user_account.users = FactoryGirl.build_list(:user, 5, :account=>user_account)
end
Note: I believe the example in the docs is a bit misleading it doesn't assign anything to the object. 注意:我认为文档中的示例有点误导,它没有为对象分配任何内容。 I believe it should be something like (note the assignment).
我相信应该是这样的(注意作业)。
# the after(:create) yields two values; the user instance itself and the
# evaluator, which stores all values from the factory, including ignored
# attributes; `create_list`'s second argument is the number of records
# to create and we make sure the user is associated properly to the post
after(:create) do |user, evaluator|
user.posts = FactoryGirl.create_list(:post, evaluator.posts_count, user: user)
end
Spyle's excellent answer (still working with Rails 5.2 and RSpec 3.8) will work for most associations. Spyle的优秀答案(仍然使用Rails 5.2和RSpec 3.8)将适用于大多数协会。 I had a use case where a factory needed to use 2 different factories (or different traits) for a single has_many association (ie. for a scope type method).
我有一个用例,工厂需要使用2个不同的工厂(或不同的特征)进行单个has_many关联(即用于范围类型方法)。
What I ended up coming up with was: 我最终提出的是:
# To build user with posts of category == 'Special' and category == 'Regular'
after(:create) do |user, evaluator|
array = []
array.push(FactoryBot.create_list(:post, 1, category: 'Regular')
array.push(FactoryBot.create_list(:post, 1, category: 'Special')
user.posts = array.flatten
end
This allowed the user to have 1 post of category 'Regular' and 1 post of category 'Special.' 这允许用户拥有1个“常规”类别的帖子和1个“特殊”类别的帖子。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.