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.
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
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With