2009-06-18 11 views
3

を定義するためのモジュールを含める:私はここでやろうとしているときには、私はルビーで遊んでいると私は、次のコードを書かれている動的なクラスメソッド

module IdAndNameRedefine 
    def self.included(base) 
    base.extend(ClassMethods) 
    end 

    module ClassMethods 
    def use_id_and_name_from_module(use_attribute) 
     class_eval <<CODE 
     def id_and_name 
      "\#{id}-\#{#{use_attribute}.downcase}" 
     end 
CODE 
    end 
    end 
end 


class Model 
    include IdAndNameRedefine 

    attr_reader :id, :name1, :name2 

    def initialize(id, name1, name2) 
    @id = id 
    @name1 = name1 
    @name2 = name2 
    end 

    def id_and_name 
    "#{id}-#{name1}" 
    end 

    use_id_and_name_from_module :name2 
end 

model = Model.new(1, "TesT", "Test number TWO") 
puts model.id_and_name 

をクラスのクラスメソッドid_and_nameをオーバーライドすることですIdAndNameRedefine-moduleによって動的に挿入されたメソッドを持つモデル。そのモジュールが含まれている場合、それは "静的"メソッドを作成します(私が理解しているようにModel.classのクラスメソッドです)。use_id_and_name_from_moduleが呼び出されると、id_and_nameを再定義するModelクラスメソッドが作成されますモデルの尋ねた

私の質問は.. これを行うにはより良い方法がありますか、これを行う "正しい"方法ですか?私はclass_evalが好きであれば、この作業をするために値などをエスケープする必要がある文字列を取りますかどうかはわかりません。

答えて

5

class_evalに文字列を渡す必要はありません。代わりにブロックを取ることができます。実際、私は文字列をclass_evalに渡さなければならない1回の機会を考えることができません。

module ClassMethods 
    def use_id_and_name_from_module(use_attribute) 
    class_eval do 
     define_method(:id_and_name) {"#{id}-#{send(use_attribute).downcase}"} 
    end 
    end 
end 

しかし、この特定のケースでは、私達はちょうど私たちは、そのクラスのコンテキスト内で既にしている意味、class_evalselfを言っている:だから私たちはそうのようなクラスメソッドモジュールを書き換えることができます。

module ClassMethods 
    def use_id_and_name_from_module(use_attribute) 
    define_method(:id_and_name) {"#{id}-#{send(use_attribute).downcase}"} 
    end 
end 

(。あなたはその部分の中で最も興味を持って見えたので、私はちょうど、class_evalが実際にどのように動作するかを示したかった)

+0

ありがとう:だから、実際に短縮することができます!私はそれがちょっと馬鹿に見えたと思ったが、私はそれをやるより良い方法を理解できなかった。私はdefine_methodも試したと信じていますが、クラス定義の先頭に 'use_id_and_name_from_module'コールを持っていましたので、うまく動作しませんでした。(クラスIの後の宣言で上書きされてしまいます。 ちょうど好奇心から離れています。クラスの先頭に 'use_id_and_name_from_module'を置く方法はありますか?それを後の宣言で上書きすることはできませんか? –

+0

誰かがそれを置き換えようとするたびに、method_addedを上書きしてあなたのバージョンを再追加することができます。しかし、少し畳み込まれているようだ。メソッドを最初に再定義しないほうがいい。 – Chuck

関連する問題