2013-01-14 82 views
1

驗證我想知道是否有一種方法做STI的update_attributes方法時,驗證基於新類類型的屬性?Rails的STI子類上update_attributes方法

例如,假設我有:

class A < ActiveRecord::Base 
end 
class B < A 
    validates :attribute_z, :presence => true 
end 
class C < A 
    validates :attribute_x, :presence => true 
    validates :attribute_y, :presence => true 
end 

我辦(軌道的方式實現):

b = A.find('b-id') 
b.update_attributes({ 'type' => 'C', :attribute_x => 'present', :attribute_y => 'present', :attribute_z => nil }) # will return false with errors on 'attribute_z must be present' 

我試着#becomes

b = A.find('b-id') 
b = b.becomes(C) 
b.update_attributes({ 'type' => 'C', :attribute_x => 'present', :attribute_y => 'present', :attribute_z => nil }) 
# this works partially, because the validations are ok but when i look to console i get something like: 
UPDATE "as" SET "type" = 'c', "attribute_z" = NULL, "attribute_y' = 'present', 'attribute_x' = 'present' WHERE "as"."type" IN ('C') AND "as"."id" = 'b-id' 
# which is terrible because it's looking for a record of B type on the C types. 
+0

我可以把:如果=> PROC {|記錄| record.type =='C'}驗證並將驗證放在A類。但是擁有這個子類是沒有意義的。 B和C的基本差別僅在驗證行爲中。 (我對這兩種類型都有很多驗證) – Guilherme

回答

0

與此相關的話題Callback for changed ActiveRecord attributes?,你可以捕獲任何賦值屬性的賦值,並通過使用變量方法使「自己」具有不同的類(A,B或C)。所以每當你使用find方法,它會填充與來自DB數據(由「B-ID」標識)一個全新的模型實例,並在必要時它會自動強制鑄模型實例爲另一種類型。

這對你有幫助嗎?

+0

謝謝,我不知道attribute_changed。但由於這個問題是,這樣做STI當它不解決我的問題,在UPDATE SQL clausule是:UPDATE表設置屬性WHERE(被迫STI STUFF,table.type IN(「對象類型」))AND table.id ='更新ID」。 因此,如果我有一個對象,它是從B型,並且改變使用而成,「更新」將在類型C的對象被調用,那麼更新將使用「C」作爲對C型STI的強制變量,但帶ID的記錄在舊的類型'B'上,所以UPDATE不起作用。 – Guilherme

0

我已經提出了一個解決方案:https://gist.github.com/4532583,因爲條件是由rails內部添加的(https://github.com/rails/rails/blob/master/activerecord/lib/active_record/inheritance.rb#L15)我創建了一個新的「update_attributes」方法,在給定類型的情況下改變類型。 :)