2012-04-20 73 views
2

我有一個抽象模型,有很多實現子模型。我希望能夠在抽象模型中定義一些函數,這些函數在子模型上調用時依賴於子模型自己的定義。 Ruby on Rails中可能有這樣的事情嗎?Ruby on Rails:有沒有類似於子類的C++虛擬方法?

例如,在長度屬性在子模型中定義:

class Animal 
    validates_inclusion_of :length, :in => MIN_LENGTH..MAX_LENGTH 
end 

class Elephant < Animal 
    MIN_LENGTH = 5 
    MAX_LENGTH = 20 
end 

然後,當我去Elephant.new.save!我希望它能用Elephant的常量運行驗證。

我想這樣做的原因是因爲將會出現這種驗證的事實對於所有的子模型都是普遍的,唯一不同的是常量的值。

當我試圖這樣做,或者使用小寫方法時,在這兩種情況下,我都會爲未定義的值得到一個名稱錯誤。

在Rails中這樣的事情是可能的嗎?

回答

4
validates_inclusion_of :length, :in => MIN_LENGTH..MAX_LENGTH 

當Ruby看到您的Animal類時會被執行。所以,當然它使用當時出現的MIN/MAX_LENGTH的值。要覆蓋此行爲,你可以這樣做:

validates_inclusion_of :length, :in => lambda {|animal| animal.class.age_range } 

然後在你的AnimalElephant類都定義了(或者只是在最後一節,如果你不打算「孕育」到「剛Animal」) :

def self.age_range 
    # < some suitable range, like 5..20 > 
end 

這樣你的範圍:in將提供:in用合適的範圍內對某些物種在需要的時候進行計算。

P.S.我想你省略了基類Animal只是爲了節省很少的擊鍵;)

+0

你確定這有效嗎?這對我來說絕對是一個好主意。然而,Rails似乎期待着:指向一個容器,而不是將動物傳遞給我的lambda函數。這是我得到的錯誤 - ArgumentError:該方法的對象包括?必須作爲:配置散列的選項提供 – 2012-04-20 06:32:02

+0

是的,我確定。 Heres從API文檔中摘錄:'validates_inclusion_of:states,:in => lambda {| person |國家[person.country]}'。而且,我在回答之前對它進行了測試。 – jdoe 2012-04-20 06:34:28

+0

啊,算了一下。看起來這是2011年4月10日添加的,這可能意味着我需要從3.0開始至少使用Rails 3.1才能正常工作。 – 2012-04-20 06:47:32

相關問題