2017-02-16 80 views
0

我有一個模型,Guest這需要嵌套屬性爲Numberplate嵌套屬性創建變化關聯類型屬性。模型before_validation之間和before_save

Guest採用STI(單表繼承)和從Person繼承。爲了防止需要額外的查詢或加入到另一個表格,我將該人員類型保存在Numberplate表中名爲person_type的字段中。這樣,我就知道哪些Numberplates由Guests擁有,而無需加入Person表。

由於這種設置,我需要手動設置person_typeNumberplate(還有另一種人類型)。我實現了這個爲before_validation回調的Numberplate型號:

before_validation do 
    self.person_type = self.person.type 
end 

實際的實現是有點更通用的,但它歸結爲這一點。 現在我會在控制檯預期創造一個呼叫GuestNumberplate這一切工作:對Numberplate實例

Numberplate.new({person: Guest.new({company: Company.first}), plate: 'EFEF98'})

person_type正確設置爲"Guest"

當我有一個API端點允許嵌套屬性在一個請求中創建GuestNumberplate時,會出現此問題。奇怪的是,隨着預期person_type被存儲爲"Person',而不是"Guest"。我調試了一下,在person_type得到的before_validation回調,但該回調和before_save回調person_type突然改變"Person"之間設置正確。 我試圖覆蓋person_type setter並在設置時記錄日誌。奇怪的是setter沒有在2個ActiveRecord回調之間調用。

我有點驚呆因爲這種行爲是如何引入,這是否是在Rails核心的一個錯誤的地方或者我不佔什麼。我目前的解決方法是還將person_type設置爲額外的before_save回調,但這不像是最佳解決方案。

相關機型:

class Guest < Person 
    accepts_nested_attributes_for :numberplates 
end 

class Numberplate < ApplicationRecord 
    before_validation do 
     self.person_type = self.person.type 
    end 

    after_validation do 
     # person_type is correctly set to "Guest" 
     puts self.inspect 
    end 

    before_create do 
     # person_type is now suddenly set to "Person" 
     puts self.inspect 
    end 
end 
+0

請嘗試使用[關聯回調](http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#module-ActiveRecord:Associations::ClassMethods-label-Association+callbacks)。 – max

+0

@Max剛剛試過,顯示同樣的行爲 – edwardmp

+0

東西被設置person_type列的人,即使沒有在我身邊的任何自定義代碼。奇怪的。 – edwardmp

回答

0

所以我想通了。

Person類我有這樣的:

has_many :numberplates, as: :person, inverse_of: :person 

as: :person部分不應該存在,並介紹了該行爲。由於早期從多態性向性傳播感染遷移,並因此成爲遺忘的遺留物。一旦我刪除這一切按預期工作。

相關問題