簡體   English   中英

具有has_many和has_one的多態關聯的Factory Girl

[英]Factory Girl with polymorphic association for has_many and has_one

我目前正在開發一個項目,我想用工廠女孩創建測試,但我無法使用多態has_many關聯。 我嘗試了其他文章中提到的許多不同的可能性,但它仍然無效。 我的模型看起來像這樣:

class Restaurant < ActiveRecord::Base
  has_one :address, as: :addressable, dependent: :destroy
  has_many :contacts, as: :contactable, dependent: :destroy

  accepts_nested_attributes_for :contacts, allow_destroy: true
  accepts_nested_attributes_for :address, allow_destroy: true

  validates :name, presence: true
  #validates :address, presence: true
  #validates :contacts, presence: true
end

class Address < ActiveRecord::Base
  belongs_to :addressable, polymorphic: true

  # other unimportant validations, address is created valid, the problem is not here
end

class Contact < ActiveRecord::Base
  belongs_to :contactable, polymorphic: true
  # validations ommitted, contacts are created valid
end

因此,我想要為餐廳創建一個地址和聯系人的工廠(在餐廳進行驗證,但如果不可能,即使沒有它們),但我無法這樣做。 最終語法應該是:

let(:restaurant) { FactoryGirl.create(:restaurant) }

哪個還應該創建相關的地址和聯系人。 我讀了很多文章但總是遇到一些錯誤。 目前我的工廠(序列定義正確)是這樣的:

factory :restaurant do
  name
  # address {FactoryGirl.create(:address, addressable: aaa)}
  # contacts {FactoryGirl.create_list(:contact,4, contactable: aaa)}
  # Validations are off, so this callback is possible
  after(:create) do |rest|
    # Rest has ID here
    rest.address = create(:restaurant_address, addressable: rest)
    rest.contacts = create_list(:contact,4, contactable: rest)
  end
end

factory :restaurant_address, class: Address do
  # other attributes filled from sequences...

  association :addressable, factory: :restaurant
  # addressable factory: restaurant
  # association(:restaurant)
end

factory :contact do
  contact_type
  value

  association :contactable, :factory => :restaurant
end

有沒有辦法在地址和聯系人設置的測試中創建一個帶有一個命令的餐館? 因為after(:create)回調,我真的需要擺脫我的驗證嗎? 現狀如下:

  1. 餐廳創建了名稱和ID。
  2. 正在創建地址 - 所有都是正確的,它具有包括addressable_id和addressable_type在內的所有值
  3. 在那之后所有的聯系人都被創造了,一切都很好,cntacts有正確的價值觀。
  4. 之后,餐廳沒有來自關聯對象的任何ID,也沒有與adddress或聯系人的關聯
  5. 之后,由於某種原因餐廳再次建立(可能添加這些關聯?)並且它失敗:我得到ActiveRecord:RecordInvalid。

我正在使用factory_girl_rails 4.3.0,ruby 1.9.3和rails 4.0.1。 我會很高興得到任何幫助。

更新1:

為了澄清我的目標,我希望能夠使用一個命令在我的規范中創建餐廳,並能夠訪問相關的地址和聯系人,這應該在創建餐廳時創建。 讓我們忽略所有的驗證(我從一開始就在我的例子中注釋了它們)。 當我使用after(:build)后 ,創建第一個餐館,而不是使用餐館ID作為addressable_id和類名作為addressable_type創建地址。 同樣適用於聯系人,一切都是正確的。 問題是,餐廳不知道他們(它沒有地址ID或聯系人),我無法從我想要的餐廳訪問它們。

經過徹底的搜索后,我在這里找到了答案- stackoverflow問題 。這個答案也指向了這個要點 主要是在after(:build)回調中構建關聯,然后將它們保存在after(:create)回調之后。 所以它看起來像這樣:

factory :restaurant do
  name

  trait :confirmed do
    state 1
  end

  after(:build) do |restaurant|
    restaurant.address = build(:restaurant_address, addressable: restaurant)
    restaurant.contacts = build_list(:contact,4, contactable: restaurant)
  end

  after(:create) do |restaurant|
    restaurant.contacts.each { |contact| contact.save! }
    restaurant.address.save!
  end
end

我在我的rspec中也有一個錯誤,因為我之前使用(:每個)回調而不是之前(:all)。 我希望這個解決方案有助於某人。

問題

驗證相關行列表的長度是SQL中框架的難題,因此在ActiveRecord中構建框架也是一個難題。

如果您在地址表上存儲餐館外鍵,您實際上無法創建一個在保存時具有地址的餐館,因為您需要保存餐館以獲取其主鍵。 您可以通過在內存中構建關聯對象,驗證這些問題,然后在一個SQL事務中提交整個對象圖,來解決ActiveRecord中的這個問題。

怎么做你要問的

你通常可以通過將事物移動到after(:build)鈎子而不是after(:create) 一旦保存自己,ActiveRecord將保存其依賴的has_onehas_many關聯。

您現在收到錯誤,因為您無法修改對象以滿足after(:create)塊中的驗證,因為驗證已在回調運行時運行。

你可以改變你的餐廳工廠看起來像這樣:

factory :restaurant do
  name

  after(:build) do |restaurant|
    restaurant.address = build(:restaurant_address, addressable: nil)
    restaurant.contacts = build(:contact, 4, contactable: nil)
  end
end

nil那兒是打破工廠之間的循環關系。 如果您這樣做,則無法對addressable_idcontactable_id鍵進行驗證,因為在保存restaurant之前它們將無法使用。

備擇方案

雖然您可以同時使用ActiveRecord和FactoryGirl來執行您所要求的操作,但它會設置一個不穩定的依賴項列表,這些依賴項很難理解,並且很可能導致漏洞驗證或意外錯誤,例如您現在看到的錯誤。

如果您通過這種方式從餐館模型驗證聯系人,因為您創建餐館及其相應聯系人的表單,您可以通過創建一個新的ActiveModel對象來表示該表單,從而為您節省很多痛苦。 您可以收集每個對象所需的屬性,移動一些驗證(尤其是驗證聯系人列表長度的驗證),然后以更清晰,更不可能的方式在該表單上創建對象圖。打破。

這樣做的另一個好處是可以輕松地在其他測試中創建輕量級restaurant對象,而無需擔心聯系人或地址。 如果強制工廠每次都創建這些依賴對象,那么很快就會遇到兩個問題:

  • 你的測試會非常緩慢。 每次想要與餐廳合作時創建五個相關記錄將不會擴展到很遠。
  • 如果您想在測試中指定不同的聯系人或地址,您將不斷與您的工廠抗爭。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM