2010-12-02 11 views
1

私はこの作業を行う方法を見つけましたが、より良い方法やRails 3の方法について興味があります。 (私はまだ2.3.5を使用していますが、新年の周りを移行したいと考えています)複数世代のモジュールでレールバリデーションを定義/アタッチする方法

状況:2つのレイヤーの継承があり、2番目のレイヤーがRailsモデルに混在しています。両方のモジュールは、検証メソッドを定義して、私は、基本クラスに検証を添付し、それらの両方が欲しい、しかしので相続の二つのレベルの、次のように動作しません:

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

そのモジュールが含まれている場合モジュールはActiveRecord::Validationsを知らないので、別のモジュールによってインタープリタが慌てて停止するようになります。検証モジュールを含めると、「saveはどこですか?」という質問が返されます。 alias_methodのおかげです。

validate()を無効にするたびにsuperを呼び出すことを忘れない限り、以下のように動作します。私は自分自身や将来のメンテナーがそれを覚えているとは信用しないので、可能であれば、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

答えて

0

私はそれを解決しました(私は同じ問題に遭遇しましたが、検証以外のものを使用しました)。

短い答え:あなたが持ち込みたいモジュールにsend(:included、base)を呼び出すことができます。higher-up included()定義の中で、ベースがクラスかモジュールかをチェックする必要があります。

なぜあなたはこれをやりたいのですか?さて、私はモデルから共通の機能を抽出するモジュールをいくつか持っています。たとえば、モジュールHasAllocableは、ポリモフィックbelongs_toの関係、および仮想属性のゲッター/セッターのペアを設定します。今度は、基底クラスを覚えておかなくて済むように、別のモジュールを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 
関連する問題