如何建立工厂FactoryGirl用的has_many协会

问题描述 投票:84回答:5

谁能告诉我,如果我只是去有关安装错误的方式?

我有以下型号有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,1.1.0 factory_girl_rails,和RSpec。下面是:listing工厂我的基本rspec的rspec的完整性检查:

it "creates a valid listing from factory" do
  Factory(:listing).should be_valid
end

这里是工厂(:上市)

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难道仅仅是不明智的可发电工厂对象这样,还是我缺少什么?非常感谢任何和所有输入!

rspec ruby-on-rails-3.1 has-many-through factory-bot
5个回答
54
投票

创建这类协会要求使用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

101
投票

另外,您也可以使用块并跳过association关键字。这使得人们有可能建立对象,而不保存到数据库中(否则,一个的has_many协会将你的记录保存到数据库,即使你使用build功能,而不是create的)。

FactoryGirl.define do
  factory :listing_with_features, :parent => :listing do |listing|
    features { build_list :feature, 3 }
  end
end

21
投票

你可以使用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


20
投票

我尝试了几种不同的方法,这是大多数工作可靠,我的一个(适用于你的情况)

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

0
投票

这里是我定住了:

# 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)

希望帮助。

© www.soinside.com 2019 - 2024. All rights reserved.