FactoryGirl association model trouble: “SystemStackError: stack level too deep”

后端 未结 2 1960
迷失自我
迷失自我 2020-12-16 00:33

I am using Ruby on Rails 3.0.9, RSpec-rails 2 and FactoryGirl. I am trying to state a Factory association model but I am in trouble.

I have a factories/user.rb

相关标签:
2条回答
  • 2020-12-16 01:13

    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.

    For instance, in the factories/users/account.rb file, you put something like

    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.

    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
    
    0 讨论(0)
  • 2020-12-16 01:13

    Spyle's excellent answer (still working with Rails 5.2 and RSpec 3.8) will work for most associations. 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).

    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.'

    0 讨论(0)
提交回复
热议问题