2011-07-29 26 views
3

特定のメソッドが定義されていない場合、エラーをスローするモジュールにいくつかのコードを入れたいと思います。 このモジュールの実装はすべてのクラスで異なるため、このモジュールはこのメソッドの外部定義に依存しています。このコードは、開発者がモジュールの機能を使用しようとするよりもむしろメソッドを実装するのを忘れてしまったことを早期に知るのに役立ちます。メソッドが定義されていない場合Ruby:クラスメソッドが見つからない場合、モジュールでエラーが発生する

module MyModule 
    def self.included(klass) 
    raise "MyModule: please `def my_method` on #{klass}" unless klass.respond_to?(:my_method) 
    end 
end 

は、私は簡単に、それは私の必要なメソッドは、クラスで定義されている可能性があります、ほとんどのモジュールは、ファイルの先頭に含まれているがために、モジュールの付属の定義でエラーを発生させることができます私のモジュールが含まれる前ではありません。

class MyClass 
    include MyModule 
    def self.my_method 
    # ... 
    end 
end 

これはまだエラーを引き上げる:(

は、それは方法が真にクラス定義で定義されていない場合にのみ、エラーが発生することは可能ですか?ほとんどの種類のclass.onloadコールバックを必要としています。場合あなたはmethod_missingdefine_methodを利用したい好きではない、プログラマはこの必要なメソッドを定義することなく、当社のモジュールが含まれる場合があります?

答えて

5

を可能性を軽減する方法のための任意の他のアイデアが鳴ります。

あなたの場合未処理の例について

  • コールsuper:することを忘れないでくださいmethod_missingを使用してください。

this questionを見て、プラスthisthatrespond_to?メソッドを実装します。

更新:

それは目標がないJavaやC++のようなチェックの静的メソッドを行うことです鳴ります。これはRubyで以来ルビー:-(

には本当に意味がありません。

  • オブジェクトの各インスタンスは、独自のeigenclassを持って指定されたオブジェクトは、実行時に混入し、必要なメソッドを有することができるので、という理由だけで。それが必要なときFooは、データベースクエリの方法のために必要なメソッドを作成動的method_missingとRoRのフックのようなフレームワーク
  • 。クラスのロード時に方法は無意味である必要はないので、この方法は、存在(またはしない)ことができる。

"class on load"に関して:クラス定義が実際に実行されます。これを試してみてください:

class Foo 
    p "Hi" 
end 

初めて "Foo"と表示されます。これは、deviseのようなものが彼らの魔法を行う方法です。

class User < ActiveRecord::Base 
    # **CALL 'devise' method** 
    devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable 

    # **CALL attr_accessible method** 
    attr_accessible :email, :password, :password_confirmation 
end 

だから多分、民間慣例により、開発者は、問題のクラスの下にcheck_classメソッド呼び出しを追加していますか?

私はその意図を理解していますが、ルビーがうまく動作するように戦っているようです。

ほとんどJavaの人として、私は欲求不満を感謝します。私には推測させてください:メソッドが欠けていた生産にコードが戻ってくるという繰り返しのケース? :-P

アップデート2:凍結したクラスの使用を禁止するRubyで

WRT onload新しいメソッドがすべての時間を定義しますが。 (あるいはインスタンスはそのインスタンスのためだけに定義された新しいメソッドを得ることができます)。メソッドが存在しないかどうかをチェックするのはスナップショットのチェックであり、静的な言語によるチェックではありません。これはルビー独自のものですHalting problem

+1

私は固有クラスに精通しています。はい、静的メソッドチェックのようなことをしようとしています。私の同僚の一人は、この期待をMyModuleを実装するモデルのテストに移行できると指摘しました。私たちは、すべてのモデルのテスト/スペックとmixinできるマクロacts_as_my_moduleを持つことができます。大声で文句を言うことはなく、余分なプログラマーの献身を必要としますが、ルビーエスクが最もあります – Schneems

+0

rspecを使用している場合は、次のようなことができます:http://relishapp.com/rspec/rspec-core/v/ 2-6/dir/example-groups/shared-examples – Schneems

+0

すべてのことが考慮されている場合は、展開の一部として実行されるツールが必要であり、このような問題がある場合は展開を停止する必要があります。すでに知っているように思えますが、代替案が期待されています: – Pat

3

エラーを発生させるだけの名前を持つメソッドを宣言して、メソッドを再定義する方法について教えてください。開始時に、あなたのプログラムを想定し

module MyModule 
    def my_method 
    raise "Please implement me" 
    end 
end 


class MyClass 
    include MyModule 
    def my_method 
    # do something 
    end 
end 
+0

私はこれを考えましたが、メソッドを呼び出すまではまだ痛みを感じません。 – Schneems

+0

定義を完全に省略すると、ほとんど同じ効果が得られます。実際には、それはもっと優れたものになります。なぜなら、汎用的でない記述的な 'RuntimeError'例外を発生させるのではなく、' NoMethodError'例外を発生させるからです。そこにいることはありませんでした。それは慣用的なRubyのやり方であり、例えばEnumerableとComparableのようなやり方です。 –

2

は、すべてのファイルを必要とし、任意のautoloadなどを使用しないすべてのものが必要とされた後、次の右のようなものを使用することができますが、プログラムが実際に開始する前に:

classes_to_check = Object.constants.find_all do |const| 
    klass = Object.const_get(c) 
    klass.ancestors.include?(MyModule) if klass.kind_of?(Module) 
end 

classes_to_check.each do |klass| 
    raise "MyModule: please `def my_method` on #{klass}" \ 
    unless klass.respond_to?(:my_method) 
end 

しかし、私は個人的に常にドッグベルトのソリューションを使用しています。

関連する問題