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)