2012-04-24 8 views
3

I`veには、以下のRubyのクラスを得た:コール追加パラメータを持つブロック内のすべてのメソッド

class Sandwich 
    class << self 
    def prepare_with(special_ingredient, &block) 
     # Some very very special magic is done here to 
     # call instead just .fry! as .fry!({:ingredient=>special_ingredient}) 
     # and for any other method the same 
    end 

    def fry!(opts= {}) 
    end 

    def add_mayo(opts = {}) 
    end 
    end 
end 

class Hamburger < Sandwich 
end 

=> Hamburger.prepare_with(bacon) do 
=> Hamburger.fry! 
=> Hamburger.add_mayo 
=> end 

私はHamburgerクラスのすべてのメソッドを呼び出すの変更と最後のパラメータのハッシュに追加key=>valueを追加します。

いくつかの特別な魔法が.fry!({:ingredient=>special_ingredient})としてcallだけではなく、.fry!のように、すべてのサンドイッチの方法(およびそのすべての子孫)を呼び出すことSandwich.prepare_withで行う必要があります。

EDITED

=> Hamburger.prepare_with(bacon) do 
=> Hamburger.fry! 
=> h = Hash.new("Go fish") 
=> Hamburger.add_mayo 
=> end 
:理想的に私たちはたとえば次のコードのために、内部のブロックコードの呼び出しをフィルタリングするために必要な追加点は、それは追加のパラメータを指定して呼び出すことdoesnの `tのフィルタ方法を任意のprepare_withコードの例外を発生させます
+0

が、これはあなたが –

+0

を探していたものであるなら、私に知らせてあなたが意味するか私の答えを編集しましたHash.newはエラーをスローするはずですか? –

+0

私は本当にあなたの編集を理解しているのか分かりませんが、私はそれが第二の問題であり、この問題は解決しにくいと思います。ここでDSLを構築しようとしているのであれば、おそらく外部のDSLを使うべきでしょう。独自のパーサーを構築するか、treetopやraccを使用して、これを実現できます。次に、未知のステートメントが発生した場合に例外を発生させることができます。 –

答えて

3

のようなものがなぜfry!add_mayoは、インスタンスメソッドではないでしょう見るでしょうか?

EDIT:インスタンスメソッドずに、要求された質問のポスターのように:

class Sandwich 
    class << self 
    def prepare_with(special_ingredient, &block) 
     @@default_opts = {:special_ingredient => special_ingredient} 
     block.call 
    end 

    def fry!(opts={}) 
     opts = opts.merge(@@default_opts) 
     puts "fried with #{opts[:special_ingredient]}" 
    end 

    def add_mayo(opts = {}) 
     puts "added mayo" 
    end 
    end 
end 

class Hamburger < Sandwich 
end 

Hamburger.prepare_with(:bacon) do 
    Hamburger.fry! 
    Hamburger.add_mayo 
end 

Hamburger.prepare_with(:tofu) do 
    Hamburger.fry! 
end 

出力:

fried with bacon 
added mayo 
fried with tofu 
+0

問題定義によるインスタンスメソッドではありません) – Sergey

+0

まあ、あなたはどこか特別な成分を覚えていなければなりません。クラスのvarでそれらを覚えている奇妙に見えるが、秒を待って、私はこれを反映するために私の答えを更新します。 –

+0

私は編集メモを見てください。ありがとうございました。 – Sergey

0

短い答え

block.call :ingredient => special_ingredient 

長い答え

私はあなたをbすべきだと思いますオブジェクトを扱う。 add_mayoとfryはクラスメソッドの代わりにインスタンスメソッドでなければなりません。

私は

class Sandwich 
    class << self 
    def prepare &block 
     sandwich = self.new 
     block.call sandwich 
     sandwich 
    end 
    end 

    def fry(opts = {}) 
    #stuff 
    end 

    def add_mayo(opts = {}) 
    end 
end 

class Hamburger < Sandwich; end 

hamburger = Hamburger.prepare do |h| 
    h.fry :ingredient => :bacon 
    h.add_mayo 
end 
+0

あなたは時間をかけて私を打ち負かしました:) –

+0

@padde私は長い間待たなければなりません。私の答えは常に底にあります。 – gmalette

関連する問題