【问题标题】:FactoryGirl association model trouble: "SystemStackError: stack level too deep"FactoryGirl 关联模型故障:“SystemStackError: stack level too deep”
【发布时间】:2011-09-20 01:03:32
【问题描述】:

我正在使用 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 => 'foo@bar.com'
  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

上面的示例在我的规范文件中按预期工作,但是 iffactory :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

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

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

【问题讨论】:

  • 只是好奇,你有一个User,然后你有一个Users::Account,它应该是复数还是应该是User::Account 或错字?
  • @kwon - 这不是错字。我有一个Users::Account 课程。

标签: ruby-on-rails ruby ruby-on-rails-3 rspec factory-bot


【解决方案1】:

按照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

【讨论】:

    【解决方案2】:

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

    我最终想出的是:

    # 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 个“特殊”类别的帖子。

    【讨论】:

      猜你喜欢
      • 2018-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-04
      • 2015-07-03
      • 2011-08-22
      • 1970-01-01
      • 2017-08-06
      相关资源
      最近更新 更多