2010-12-02 38 views
1

我找到了一種方法來完成這項工作,但我對好的方式/ Rails 3方式感到好奇。 (我仍然使用2.3.5,但希望在新年前後遷移。)如何在多代模塊中定義/附加導軌驗證

情況:我有兩層模塊繼承,第二層被混合到Rails模型中。這兩個模塊定義的驗證方法,我想他們都在驗證連接到基礎類,但由於繼承的兩個層次,下面不工作:

def self.included(base) 
    base.validate :yadda_yadda 
end 

當包括該模塊由另一個模塊,解釋器研磨到尖銳的停頓,因爲模塊不知道約ActiveRecord::Validations。包括驗證模塊會引起「save?」的問題。感謝alias_method

以下的工作,只要你記得打電話super,只要你覆蓋validate()。我不相信自己或未來的維護者要記住這一點,所以如果可能的話,我想使用validate :yadda_yadda成語。

module Grandpa 

    def validate 
    must_be_ok 
    end 

    def must_be_ok 
    errors.add_to_base("#{self} wasn't ok") 
    end 

end 

module Dad 

    include Grandpa 

    def validate 
    super 
    must_be_ok_too 
    end 

    def must_be_ok_too 
    errors.add_to_base("#{self} wasn't ok either") 
    end 

end 

class Kid < ActiveRecord::Base 

    include Dad 

    validate :must_be_ok_three 

    def must_be_ok_three 
    errors.add_to_base("#{self} wasn't ok furthermore") 
    end 

end 

建議? Rails 3的方法?我認爲驗證API沒有太大改變。

+0

那麼要清楚你想要跨多個模型共享驗證? – jonnii 2010-12-02 20:43:23

回答

0

我解決了它(當我遇到同樣的問題,但與驗證以外的東西)。

簡短回答:您可以在要引入的模塊上調用send(:included,base)。在上面的included()定義中,您需要檢查基類是Class還是Module。

爲什麼你會想要這樣做?那麼,我有一些模塊可以從我的模型中提取一些常用的功能。例如,模塊HasAllocable設置多態性關係,併爲虛擬屬性設置一個getter/setter對。現在我有另外一個模塊需要拉入HasAllocable,以便讓基類不必記住它。

我很想知道這是否對任何人都有趣。我在網上沒有看到任何類似的東西,所以我想知道模型繼承的多層更多是反模式。

module Grandpa 

    def self.included(base) 
    if base.kind_of?(Class) 
     base.validate :must_be_ok 
    end 
    end 

end 

module Dad 

    include Grandpa 

    def self.included(base) 
    if base.kind_of?(Class) 
     # you can do this 
     #base.send(:include, Grandpa) 
     # you can also do this 
     Grandpa.send(:included, base) 
     # this does not invoke Grandpa.included(Kid) 
     #super(base) 

     base.validate :must_be_ok_too 
    end 
    end 

end 

class Kid < ActiveRecord::Base 
    include Dad 
    validate :must_be_ok_three 
end