The design
I have a User model that belongs to a profile through a polymorphic association. The reason I chose this design can be found here. To summarize, there are many users of the application that have really different profiles.
class User < ActiveRecord::Base
belongs_to :profile, :dependent => :destroy, :polymorphic => true
end
class Artist < ActiveRecord::Base
has_one :user, :as => :profile
end
class Musician < ActiveRecord::Base
has_one :user, :as => :profile
end
After choosing this design, I'm having a hard time coming up with good tests. Using FactoryGirl and RSpec, I'm not sure how to declare the association the most efficient way.
First attempt
factories.rb
Factory.define :user do |f|
# ... attributes on the user
# this creates a dependency on the artist factory
f.association :profile, :factory => :artist
end
Factory.define :artist do |a|
# ... attributes for the artist profile
end
user_spec.rb
it "should destroy a users profile when the user is destroyed" do
# using the class Artist seems wrong to me, what if I change my factories?
user = Factory(:user)
profile = user.profile
lambda {
user.destroy
}.should change(Artist, :count).by(-1)
end
Comments / other thoughts
As mentioned in the comments in the user spec, using Artist seems brittle. What if my factories change in the future?
Maybe I should use factory_girl callbacks and define an "artist user" and "musician user"? All input is appreciated.
I currently use this implementation for dealing with polymorphic associations in
FactoryGirl
:In /spec/factories/users.rb:
Then, create the records as usual:
FactoryGirl.create(:artist_user)
Although there is an accepted answer, here is some code using the new syntax which worked for me and might be useful to someone else.
spec/factories.rb
spec/models/artist_spec.rb
Which will create the artist instance as well as the user instance. So you can call:
to get the Artist instance.
Use traits like this;
now you can get user instance by
FactoryGirl.create(:user, :artist)
You can also solve this using nested factories (inheritance), this way you create a basic factory for each class then nest factories that inherit from this basic parent.
You now have access to the nested factories as follows:
Hope this helps someone.
It seems that polymorphic associations in factories behave the same as regular Rails associations.
So there is another less verbose way if you don't care about attributes of model on "belongs_to" association side (User in this example):
FactoryGirl associations: https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md#associations
Factory_Girl callbacks would make life much easier. How about something like this?