2011-12-21 10 views
0

method_missing関数を使用して動的メソッドを作成しています。 それはすべて正常に動作しますが、私がしたいことは、これらのメソッドをClassName.methods配列に追加することです。コードは次のとおりです。class.methods配列に動的メソッドを追加

module MyObjectStore 
    values = [] 
    temp = {} 
    def self.included(kls) 
    kls.extend ClassMethods 
    end 

    ClassMethods = Module.new do 
    define_method :method_missing do |method,*args,&block|   
     if method =~ /find_by_/ 
     methods << method 
     add_search_method(method,*args) 
     else 
     values.send "#{method}", &block 
     end 
    end 
    define_method :add_search_method do |method,*args| 
     values.each do |obj| 
     x = obj.send "#{method.to_s.split('_')[-1]}" 
     if x == args[0] 
      p obj 
     end 
     end 
    end 
    end 

    define_method :add_check_attribute do |method,*args| 
    if method.to_s =~ /=$/ 
     temp[method[0..-2]] = args[0] 
    else 
     instance_variable_get("@#{method}") 
    end 
    end 
    define_method :method_missing do |method,*args| 
    add_check_attribute(method,*args) 
    end 
    define_method :save do 
    temp.each {|key,value| instance_variable_set("@#{key}",value)} 
    values << self 
    end 
end 

class C 
    include MyObjectStore 
end 

新しいメソッドをメソッドArrayに追加します。それはここにうまく追加されています。問題は、クラスCの参照を作成し、その新たに追加されたメソッドを見つけようとすると、何も返されないということです。すなわち

a = C.new 
a.id = 1 
a.name = 'gaurav' 
a.save 
C.find_by_name('gaurav') 
p a.methods.include?(:find_by_name) 

戻り

私はこれをやって行くことができる方法はありますか?

ありがとうございます。

+0

これは、私に物事をする過度のメタ方法の感触を持っています - 確かに、レールはこれのようなことをしますが、それは簡単に維持することはできません:)。この問題を解決するためにコードを再構成できますか?たとえあなたが「修正」を見つけたとしても、理解して維持するのは難しいでしょう。 – Peter

+0

ちょっとピーター、応答に感謝し、私は過度のメタについても同じことを感じる。 しかし実際には、これは私のトレーニングの練習の1つです。私はこのようにしなければならず、コードのメンテナンスは重要ではありません! :) こういうことができると思いますか、コードをどのように再構築できますか? –

答えて

0

ここで、新しいメソッドはクラスCのために定義されたクラスメソッドです。 しかし 'a'はCのインスタンスなので、それらのメソッドは表示されません。

これは、あなたがmethods << methodモジュールにメソッドを追加しますが、それはそのような何もしないことを想定しているEDITED

p a.class.methods.include?(:find_by_name) 

を返します。だから、明示的

ClassMethods = Module.new do 
    def method_missing(method, *args, &block)  
     if method =~ /find_by_/ 
     add_search_method(method,*args) 
     send(method, *args) 
     else 
     values.send "#{method}", &block 
     end 
    end 

    def add_search_method(method, *args) 
     define_singleton_method(method) do |*args| 
     @@values.each do |obj| 
      return obj if obj.send("#{method.to_s.split('_')[-1]}") == args[0] 
     end 
     nil 
     end 
    end 
    end 

はこの1つを使用してクラスメソッドの定義を交換し、C.methodsは、法によって、あなたの検索が含まれます、次のようにメソッドを定義する必要があります。

私はここで何を達成しようとしているのかはっきりしていませんが、彼のコメントでピーターが提案したように、あなたはおそらくあまりにもきれいに見えないので、あなたのコードを再構成する必要があります。

+0

いいえ、まだ「偽」と書いてあります。\ –

+0

啓蒙主義のDipilに感謝しますが、find_by_ *メソッドは現在動作を停止しました! :\ –

+0

ありがとう、これは完璧に動作し、本当にあなたの助けに感謝します。 :) –

関連する問題