Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
794 views
in Technique[技术] by (71.8m points)

ruby on rails - FactoryGirl association model trouble: "SystemStackError: stack level too deep"

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 file like the following:

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

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

and a factories/users/account.rb file like the following:

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

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 sidesfactories (that is, in my spec files I would like to use RoR association model methods like user.account and account.user)?

P.S.: I read the Factory Girl and has_one question and my case is very close to the case explained in the linked question. That is, I have an has_one association too (between User and Users::Account classes).

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...