Câu hỏi Cách thiết lập nhà máy trong FactoryGirl với liên kết has_many


Ai đó có thể cho tôi biết nếu tôi đang đi về việc thiết lập một cách sai lầm?

Tôi có các mô hình sau có các liên kết 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

Tôi đang sử dụng Rails 3.1.rc4, FactoryGirl 2.0.2, factory_girl_rails 1.1.0 và rspec. Đây là kiểm tra độ chính xác rspec rspec cơ bản của tôi cho :listing nhà máy:

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

Đây là Nhà Máy (: danh sách)

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

Các :listing_feature và :feature các nhà máy được thiết lập tương tự.
Nếu association :features dòng được nhận xét, sau đó tất cả các bài kiểm tra của tôi vượt qua.
Khi nó là

association :features, :factory => :feature

thông báo lỗi là undefined method 'each' for #<Feature>  mà tôi nghĩ có ý nghĩa với tôi bởi vì listing.features trả về một mảng. Vì vậy, tôi đã thay đổi nó thành

association :features, [:factory => :feature]

và lỗi tôi nhận được bây giờ là ArgumentError: Not registered: features  Nó chỉ là không hợp lý để được tạo ra các đối tượng nhà máy theo cách này, hoặc những gì tôi đang mất tích? Cảm ơn rất nhiều cho bất kỳ và tất cả các đầu vào!


76
2017-08-05 22:30


gốc




Các câu trả lời:


Việc tạo ra các loại liên kết này yêu cầu sử dụng callback của FactoryGirl.

Một tập hợp hoàn hảo các ví dụ có thể được tìm thấy ở đây.

http://robots.thoughtbot.com/post/254496652/aint-no-calla-back-girl

Để mang nó về nhà cho ví dụ của bạn.

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

51
2017-10-11 23:04



bạn đã kết thúc bằng cách sử dụng liên kết: tính năng, [: factory =>: feature]? - davidtingsu


Ngoài ra, bạn có thể sử dụng một khối và bỏ qua association từ khóa. Điều này làm cho nó có thể xây dựng các đối tượng mà không lưu vào cơ sở dữ liệu (nếu không, một liên kết has_many sẽ lưu các bản ghi của bạn vào db, ngay cả khi bạn sử dụng build thay vì create).

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

85
2017-09-25 17:11



Đây là meow của con mèo. Khả năng cho cả hai build và create làm cho nó trở thành mẫu linh hoạt nhất. Sau đó, sử dụng chiến lược xây dựng FG tùy chỉnh này gist.github.com/Bartuz/74ee5834a36803d712b7 đến post nested_attributes_for khi kiểm tra các hoạt động của bộ điều khiển accepts_nested_attributes_for - Chris Beck
upvoted, dễ đọc hơn và linh hoạt hơn câu trả lời được chấp nhận IMO - m_x


Tôi đã thử một vài cách tiếp cận khác nhau và đây là phương pháp làm việc đáng tin cậy nhất đối với tôi (phù hợp với trường hợp của bạn)

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

20
2017-11-15 03:51





Bạn đã có thể sử dụng trait:

FactoryGirl.define do
  factory :listing do
    ...

    trait :with_features do
      features { build_list :feature, 3 }
    end
  end
end

Với callback, nếu bạn cần tạo DB:

...

trait :with_features do
  after(:create) do |listing|
    create_list(:feature, 3, listing: listing)
  end
end

Sử dụng trong thông số kỹ thuật của bạn như thế này:

let(:listing) { create(:listing, :with_features) }

Điều này sẽ loại bỏ trùng lặp trong các nhà máy của bạn và có thể tái sử dụng nhiều hơn.

https://robots.thoughtbot.com/remove-duplication-with-factorygirls-traits


13
2018-01-23 18:39





Đây là cách tôi thiết lập của tôi lên:

# 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

Và sau đó trong các bài kiểm tra của bạn, bạn có thể làm:

@preference_set = FactoryGirl.create(:preference_set_with_preferences)

Hy vọng rằng sẽ giúp.


0
2017-09-08 16:20