Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FactoryGirl and polymorphic associations

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.

like image 695
Feech Avatar asked Oct 12 '11 23:10

Feech


People also ask

What is polymorphic association in Rails?

Polymorphic relationship in Rails refers to a type of Active Record association. This concept is used to attach a model to another model that can be of a different type by only having to define one association.

How is polymorphic association set up in Rails?

The basic structure of a polymorphic association (PA)sets up 2 columns in the comment table. (This is different from a typical one-to-many association, where we'd only need one column that references the id's of the model it belongs to). For a PA, the first column we need to create is for the selected model.


1 Answers

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

FactoryGirl.define do    factory :musical_user, class: "User" do     association :profile, factory: :musician     #attributes for user   end    factory :artist_user, class: "User" do     association :profile, factory: :artist     #attributes for user   end    factory :artist do     #attributes for artist   end    factory :musician do     #attributes for musician   end end 

spec/models/artist_spec.rb

before(:each) do   @artist = FactoryGirl.create(:artist_user) end 

Which will create the artist instance as well as the user instance. So you can call:

@artist.profile 

to get the Artist instance.

like image 115
veritas1 Avatar answered Oct 10 '22 23:10

veritas1