I can't use factory_girl
because I'm testing sunspot and need real database.
Edit: nope. It can works with sunspot. I'm wrong.
How can I build has_many :through(a.k.a many-to-many) associations in fixtures?
I google it and get a invalid solution
Edit:
Finally I use factory_girl. I google-copy-paste a snippet:
factory :tagging do
question { |a| a.association(:question) }
tag { |a| a.association(:tag) }
end
(question has_many tags through taggings, vice versa)
It works well. But what's it? The factory_girl's readme didn't meantion this syntax.
Could someone explain?
You can find the official documentation for factory_girl, which is very complete, here.
Here is a nice (shorter) blogpost explaining factory_girl 2 (comparing it with factory-girl 1).
UPDATED:
To Explain the code a bit:
factory :tagging do
association :tag
end
will look for a factory called :tag
and will construct that object, and then link that to the association tag
(e.g. a belongs_to
) that is there inside your object :tagging
.
Please note: this is the default factory. If you want taggings
to share a tag
, you will need to do something like
@tag = Factory(:tag)
@tagging_1 = Factory(:tagging, :tag => @tag)
@tagging_2 = Factory(:tagging, :tag => @tag)
Hope this helps.
If it's a classic has_and_belongs_to_many association, without other information in the association model, I think the conventions allow you to write your fixtures like that :
#users.yml
john:
first_name: John
last_name: Doe
hobbies: [swim, play_tennis]
#hobbies.yml
swim:
name: Swim
play_tennis:
name: Play Tennis
But I'm not completely sure !
I used fixtures on testing for has_many :through
by hash merge
# posts.yml
one:
title: "Railscasts"
url: "http://railscasts.com/"
description: "Ruby on Rails screencasts"
# categories.yml
one:
name: "magazine"
two:
name: "tutorial"
three:
name: "news"
four:
name: "Ruby"
# posts_controller_test.rb
def test_post_create
assert_difference 'Post.count' do
post :create, post: posts(:one).attributes
.merge(categories: [categories(:two), categories(:four)])
end
end
when after adding another fixture file, and tried this it didn't work
# post_categories.yml
one:
post: one
category: two
two:
post: one
category: four
def test_post_create
assert_difference 'Post.count' do
post :create, post: posts(:one)
end
end
puts posts(:one).attributes
# {"id"=>980190962, "url"=>"http://railscasts.com/", "title"=>"Railscasts", "description"=>"Ruby on Rails screencasts", "created_at"=>Thu, 14 May 2015 18:27:20 UTC +00:00, "updated_at"=>Thu, 14 May 2015 18:27:20 UTC +00:00}
puts posts(:one).attributes
.merge(categories: [categories(:two), categories(:four)])
# {"id"=>980190962, "url"=>"http://railscasts.com/", "title"=>"Railscasts", "description"=>"Ruby on Rails screencasts", "created_at"=>Thu, 14 May 2015 18:30:23 UTC +00:00, "updated_at"=>Thu, 14 May 2015 18:30:23 UTC +00:00, "category_ids"=>[980190962, 1018350795]}