FactoryGirl和多态关联

该devise

我有一个用户模型,属于通过多态关联configuration文件。 我select这个devise的原因可以在这里find。 总而言之,应用程序的许多用户具有真正不同的configuration文件。

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 

select这个devise后,我很难得出好的testing。 使用FactoryGirl和RSpec,我不知道如何声明关联最有效的方法。

第一次尝试

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 

评论/其他想法

正如在用户规范的评论中提到的,使用Artist看起来很脆弱。 如果我的工厂在未来发生变化呢?

也许我应该使用factory_girlcallback并定义一个“艺术家用户”和“音乐家用户”? 所有的input是赞赏。

Factory_Girlcallback会让生活变得更容易。 这样的事情呢?

 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 

虽然有一个可以接受的答案,但下面是一些使用新语法的代码,这些代码对我来说很有用,而且可能对其他人有用。

投机/ 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 

规格/型号/ artist_spec.rb

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

这将创build艺术家实例以及用户实例。 所以你可以打电话给:

 @artist.profile 

获取Artist实例。

使用这样的特质;

 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 

现在你可以通过FactoryGirl.create(:user, :artist)获取用户实例。

你也可以使用嵌套的工厂(inheritance)来解决这个问题,这样你可以为每个类创build一个基本的工厂,然后嵌套从这个基本父类inheritance的工厂。

 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 

您现在可以访问嵌套的工厂,如下所示:

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

希望这有助于某人。

似乎工厂中的多态关联与常规的Rails关联相同。

因此,如果您不关心“belongs_to”关联端(此示例中为User)上的模型属性,那么还有一种较为冗长的方式:

 # 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协会: https : //github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md#associations

我目前使用这个实现来处理FactoryGirl多态关联:

在/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 

然后,照常创buildlogging: FactoryGirl.create(:artist_user)