有人可以告诉我,如果我只是以错误的方式进行设置吗?
我有以下具有 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
这里是工厂(: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
工厂的设置类似。
如果 association :features
行被注释掉,那么我的所有测试都通过了。
association :features, :factory => :feature
错误消息是 undefined method 'each' for #<Feature>
,我认为这对我来说很有意义,因为 listing.features
返回一个数组。所以我把它改成了
association :features, [:factory => :feature]
我现在得到的错误是ArgumentError: Not registered: features
以这种方式生成工厂对象是不明智的,还是我错过了什么?非常感谢您的任何和所有输入!
或者,您可以使用块并跳过 association
关键字。这样就可以在不保存到数据库的情况下构建对象(否则,has_many 关联会将您的记录保存到数据库中,即使您使用 build
函数而不是 create
也是如此)。
FactoryGirl.define do
factory :listing_with_features, :parent => :listing do |listing|
features { build_list :feature, 3 }
end
end
创建这些类型的关联需要使用 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
您可以使用 trait
:
FactoryGirl.define do
factory :listing do
...
trait :with_features do
features { build_list :feature, 3 }
end
end
end
使用 callback
,如果您需要创建数据库:
...
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
从 FactoryBot v5 开始,关联保留了构建策略。关联是解决此问题的最佳方式,docs have good examples for it:
FactoryBot.define do
factory :post do
title { "Through the Looking Glass" }
user
end
factory :user do
name { "Taylor Kim" }
factory :user_with_posts do
posts { [association(:post)] }
end
end
end
或控制计数:
transient do
posts_count { 5 }
end
posts do
Array.new(posts_count) { association(:post) }
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)
希望有帮助。
与 @thisismydesign 类似,但它在我的末端创建了一个额外的 post
(FactoryBot v6.2)。
为了避免这种情况,我添加了关键字 instance
,如下所示:
FactoryBot.define do
factory :post do
title { "Through the Looking Glass" }
user
end
factory :user do
name { "Taylor Kim" }
factory :user_with_posts do
posts { [association(:post, user: instance)] }
end
end
end
不定期副业成功案例分享
build
和create
的能力使它成为最通用的模式。然后在测试accepts_nested_attributes_for
的控制器操作时使用此自定义 FG 构建策略 gist.github.com/Bartuz/74ee5834a36803d712b7 到post nested_attributes_for
association
关键字对父级和子级使用相同的构建策略。因此,它可以构建不保存到数据库的对象。