FactoryGirl and polymorphic associations

后端 未结 6 1473
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-23 14:18

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 a

相关标签:
6条回答
  • 2020-12-23 14:53

    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):

    # Factories
    FactoryGirl.define do
      sequence(:email) { Faker::Internet.email }
    
      factory :user do
        # you can predefine some user attributes with sequence
        email { generate :email }
      end
    
      factory :artist do
        # define association according to documentation
        user 
      end
    end
    
    # Using in specs    
    describe Artist do      
      it 'created from factory' do
        # its more naturally to starts from "main" Artist model
        artist = FactoryGirl.create :artist        
        artist.user.should be_an(User)
      end
    end
    

    FactoryGirl associations: https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md#associations

    0 讨论(0)
  • 2020-12-23 14:55

    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.

    FactoryGirl.define do
        factory :user do
            # attributes_for user
            factory :artist_profile do
                association :profile, factory: :artist
            end
            factory :musician_profile do
                association :profile, factory: :musician
            end
        end
    end
    

    You now have access to the nested factories as follows:

    artist_profile = create(:artist_profile)
    musician_profile = create(:musician_profile)
    

    Hope this helps someone.

    0 讨论(0)
  • 2020-12-23 15:11

    I currently use this implementation for dealing with polymorphic associations in FactoryGirl:

    In /spec/factories/users.rb:

    FactoryGirl.define do
    
      factory :user do
        # attributes for user
      end
    
      # define your Artist factory elsewhere
      factory :artist_user, parent: :user do
        profile { create(:artist) }
        profile_type 'Artist'
        # optionally add attributes specific to Artists
      end
    
      # define your Musician factory elsewhere
      factory :musician_user, parent: :user do
        profile { create(:musician) }
        profile_type 'Musician'
        # optionally add attributes specific to Musicians
      end
    
    end
    

    Then, create the records as usual: FactoryGirl.create(:artist_user)

    0 讨论(0)
  • 2020-12-23 15:12

    Use traits like this;

    FactoryGirl.define do
        factory :user do
            # attributes_for user
            trait :artist do
                association :profile, factory: :artist
            end
            trait :musician do
                association :profile, factory: :musician
            end
        end
    end
    

    now you can get user instance by FactoryGirl.create(:user, :artist)

    0 讨论(0)
  • 2020-12-23 15:18

    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.

    0 讨论(0)
  • 2020-12-23 15:20

    Factory_Girl callbacks would make life much easier. How about something like this?

    Factory.define :user do |user|
      #attributes for user
    end
    
    Factory.define :artist do |artist|
      #attributes for artist
      artist.after_create {|a| Factory(:user, :profile => a)}
    end
    
    Factory.define :musician do |musician|
      #attributes for musician
      musician.after_create {|m| Factory(:user, :profile => m)}
    end
    
    0 讨论(0)
提交回复
热议问题