多態的な関連付けを介してプロファイルに属するユーザーモデルがあります。このデザインを選んだ理由は こちら にあります。要約すると、アプリケーションのユーザーは本当に異なるプロファイルを持っています。
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
この設計を選択した後、良いテストを思いつくのに苦労しています。 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_girl callbacks を使用して、「アーティストユーザー」と「ミュージシャンユーザー」を定義する必要がありますか?すべての入力を歓迎します。
Factory_Girlコールバックは、人生をずっと楽にします。このようなものはどうですか?
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
受け入れられた答えがありますが、ここに私のために働いたし、他の誰かに役立つかもしれない新しい構文を使用したコードがあります。
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
これにより、アーティストインスタンスとユーザーインスタンスが作成されます。だからあなたは電話することができます:
@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)
でユーザーインスタンスを取得できるようになりました
ネストされたファクトリ(継承)を使用してこれを解決することもできます。この方法では、各クラスの基本ファクトリを作成し、この基本親から継承するファクトリをネストします。
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」関連付け側(この例ではユーザー)のモデルの属性を気にしない場合は、もう少し冗長な方法があります。
# 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
のポリモーフィックな関連付けを処理しています。
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
_
次に、通常どおりレコードを作成します:FactoryGirl.create(:artist_user)