FactoryGirl关联模型故障:“SystemStackError:堆栈级别太深”

问题描述 投票:9回答:2

我正在使用Ruby on Rails 3.0.9,RSpec-rails 2和FactoryGirl。我试图陈述一个工厂协会模型,但我遇到了麻烦。

我有一个factories/user.rb文件,如下所示:

FactoryGirl.define do
  factory :user, :class => User do
    attribute_1
    attribute_2
    ...

    association :account, :factory => :users_account, :method => :build, :email => '[email protected]'
  end
end

和一个factories/users/account.rb文件如下:

FactoryGirl.define do
  factory :users_account, :class => Users::Account do
    sequence(:email) {|n| "foo#{n}@bar.com" }
    ...
  end
end

上面的示例在我的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

我收到以下错误:

Failure/Error: Unable to find matching line from backtrace
SystemStackError:
  stack level too deep

如何解决这个问题,以便从双方\工厂访问相关模型(也就是说,在我的spec文件中,我想使用像user.accountaccount.user这样的RoR关联模型方法)?

P.S。:我读了Factory Girl and has_one问题,我的案子与链接问题中解释的案例非常接近。也就是说,我也有一个has_one协会(在UserUsers::Account课程之间)。

ruby-on-rails ruby ruby-on-rails-3 rspec factory-bot
2个回答
20
投票

根据the docs的说法,你不能把协会的双方都放进工厂。您需要使用它们的after回调来设置要返回的对象。

例如,在factories/users/account.rb文件中,你放了类似的东西

after(:build) do |user_account, evaluator|
    user_account.user = FactoryGirl.build(:user, :account=>user_account)
end

对于has_many关联,您需要使用他们的* _list函数。

after(:build) do |user_account, evaluator|
    user_account.users = FactoryGirl.build_list(:user, 5, :account=>user_account)
end

注意:我认为文档中的示例有点误导,它没有为对象分配任何内容。我相信应该是这样的(注意作业)。

# 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

0
投票

Spyle的优秀答案(仍然使用Rails 5.2和RSpec 3.8)将适用于大多数协会。我有一个用例,工厂需要使用2个不同的工厂(或不同的特征)进行单个has_many关联(即用于范围类型方法)。

我最终提出的是:

# 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

这允许用户拥有1个“常规”类别的帖子和1个“特殊”类别的帖子。

© www.soinside.com 2019 - 2024. All rights reserved.