내가 잘못된 방식으로 설정하는 경우 누군가 말해 줄 수 있습니까?
has_many.through 연결이있는 다음 모델이 있습니다.
class Listing < ActiveRecord::Base
attr_accessible ...
has_many :listing_features
has_many :features, :through => :listing_features
validates_presence_of ...
...
end
class Feature < ActiveRecord::Base
attr_accessible ...
validates_presence_of ...
validates_uniqueness_of ...
has_many :listing_features
has_many :listings, :through => :listing_features
end
class ListingFeature < ActiveRecord::Base
attr_accessible :feature_id, :listing_id
belongs_to :feature
belongs_to :listing
end
저는 Rails 3.1.rc4, FactoryGirl 2.0.2, factory_girl_rails 1.1.0 및 rspec을 사용하고 있습니다. 다음은 :listing
공장에 대한 기본적인 rspec rspec 온 전성 검사입니다 .
it "creates a valid listing from factory" do
Factory(:listing).should be_valid
end
여기는 Factory (: listing)
FactoryGirl.define do
factory :listing do
headline 'headline'
home_desc 'this is the home description'
association :user, :factory => :user
association :layout, :factory => :layout
association :features, :factory => :feature
end
end
:listing_feature
및 :feature
공장 유사하게 설정합니다.
는 IF association :features
라인이 주석 다음 내 모든 테스트를 통과.
때
association :features, :factory => :feature
오류 메시지는
배열을 반환 undefined method 'each' for #<Feature>
하기 때문에 나에게 의미가 있다고 생각했습니다 listing.features
. 그래서 나는 그것을
association :features, [:factory => :feature]
그리고 지금 내가 얻는 오류는 ArgumentError: Not registered: features
이런 식으로 팩토리 객체를 생성하는 것이 합리적이지 않습니까? 아니면 무엇을 놓치고 있습니까? 모든 의견에 감사드립니다!
답변
이러한 종류의 연결을 생성하려면 FactoryGirl의 콜백을 사용해야합니다.
완벽한 예는 여기에서 찾을 수 있습니다.
https://thoughtbot.com/blog/aint-no-calla-back-girl
당신의 모범으로 그것을 집으로 가져 오십시오.
Factory.define :listing_with_features, :parent => :listing do |listing|
listing.after_create { |l| Factory(:feature, :listing => l) }
#or some for loop to generate X features
end
답변
또는 블록을 사용하고 association
키워드를 건너 뛸 수 있습니다 . 이렇게하면 데이터베이스에 저장하지 않고 객체를 빌드 할 수 있습니다 (그렇지 않으면 has_many 연결은 build
대신 함수 를 사용하더라도 레코드를 db에 저장합니다 create
).
FactoryGirl.define do
factory :listing_with_features, :parent => :listing do |listing|
features { build_list :feature, 3 }
end
end
답변
다음을 사용할 수 있습니다 trait
.
FactoryGirl.define do
factory :listing do
...
trait :with_features do
features { build_list :feature, 3 }
end
end
end
를 사용하여 callback
DB 생성이 필요한 경우 :
...
trait :with_features do
after(:create) do |listing|
create_list(:feature, 3, listing: listing)
end
end
다음과 같은 사양에서 사용하십시오.
let(:listing) { create(:listing, :with_features) }
이렇게하면 공장에서 중복이 제거되고 재사용이 더 쉬워집니다.
https://robots.thoughtbot.com/remove-duplication-with-factorygirls-traits
답변
몇 가지 다른 접근 방식을 시도했는데 이것이 저에게 가장 안정적으로 작동 한 방식입니다 (귀하의 경우에 적용됨).
FactoryGirl.define do
factory :user do
# some details
end
factory :layout do
# some details
end
factory :feature do
# some details
end
factory :listing do
headline 'headline'
home_desc 'this is the home description'
association :user, factory: :user
association :layout, factory: :layout
after(:create) do |liztng|
FactoryGirl.create_list(:feature, 1, listing: liztng)
end
end
end
답변
내 설정 방법은 다음과 같습니다.
# Model 1 PreferenceSet
class PreferenceSet < ActiveRecord::Base
belongs_to :user
has_many :preferences, dependent: :destroy
end
#Model 2 Preference
class Preference < ActiveRecord::Base
belongs_to :preference_set
end
# factories/preference_set.rb
FactoryGirl.define do
factory :preference_set do
user factory: :user
filter_name "market, filter_structure"
factory :preference_set_with_preferences do
after(:create) do |preference|
create(:preference, preference_set: preference)
create(:filter_structure_preference, preference_set: preference)
end
end
end
end
# factories/preference.rb
FactoryGirl.define do
factory :preference do |p|
filter_name "market"
filter_value "12"
end
factory :filter_structure_preference, parent: :preference do
filter_name "structure"
filter_value "7"
end
end
그런 다음 테스트에서 다음을 수행 할 수 있습니다.
@preference_set = FactoryGirl.create(:preference_set_with_preferences)
도움이되기를 바랍니다.