2016-04-03 7 views
2

メソッドを動的に定義し、それにパラメータを渡そうとしています。これは私がこれまで持っているものです:routeが呼び出されると動的に定義されたメソッドのデフォルトのパラメータ

class Commands 
end 

@commands = Commands.new 

def route(name, &block) 
    Commands.send(:define_method, name, &block) 
end 

route 'foo' do 
    puts 'oh hai' 
    puts data 
end 

、これは私が実行されることを期待するものである:

data = {name: 'foo', optional: 'bar'} 
@commands.send(data['name'].to_sym, data) 

私はのような何かをしない限り、dataが定義されていないため、これは失敗します。

route 'foo' do |data| 
    puts 'oh hai' 
    puts data 
end 

デフォルトパラメータを渡す方法はありますか?それはsinatrarbのようだが、まだコードから頭や尾を作ることができていない。

+1

「デフォルトパラメータを渡す」という意味は理解できません。 –

+0

泥として透明? :)不明確な質問をお詫び申し上げます。問題の一部は間違いなく、私が求めている根本的な質問は何か分かりません。 回答は対象となっているので、実験して質問を更新する – Dishcandanty

答えて

3

あなたの質問はあまり明確ではありませんが、あなたが探している機能は通常instance_evalと友人で達成されていると思われます。 instance_evalは、呼び出し先のコンテキストで指定されたブロックを評価し、呼び出し先のインスタンスメソッドとインスタンス変数をブロック内で使用できるようにします。ここで

は本当に基本的な例です:

"foo".instance_eval do 
    puts size 
    puts upcase 
end 
# -> 3 
# -> FOO 

sizeupcaseは、私たちがブロックに与えたパラメータではありません、彼らは、Stringオブジェクトのコンテキストで既に利用されている方法です。我々はインスタンスrouteメソッドに与えられたブロックを評価するコンテキストとして使用できるルートクラスを定義しました。ここ

class Route 
    attr_reader :data 

    def initialize(name) 
    @data = { name: name, optional: "bar" } 
    end 
end 

rt = Route.new("foo") 

rt.instance_eval do 
    puts 'oh hai' 
    puts data 
end 
# -> oh hai 
# -> {:name=>"foo", :optional=>"bar"} 

を念頭に置いて

、あなたはこのような何かを始めるかもしれません。

def route(name, &block) 
    rt = Route.new(name) 
    Commands.send(:define_method, name) do 
    rt.instance_eval(&block) 
    end 
end 

route 'foo' do 
    puts 'oh hai' 
    puts data 
end 

route 'qux' do 
    puts "My name is %{name} and optional is %{optional}" % data 
end 

@commands = Commands.new 
@commands.foo 
# -> oh hai 
# -> {:name=>"foo", :optional=>"bar"} 

@commands.qux 
# -> My name is qux and optional is bar 
1

ブロックは、routeメソッドに渡しているものです。あなたはそれゆえルビーは、任意の数のパラメータに対して文句はありません、あなたが望むものは何でも合格するのは自由です

1つのパラメーターをブロックするためにデフォルト値を割り当てることができます(@commands.fooが実際に呼び出されるまで。):

λ = lambda do |data = 'hello'| 
    puts data 
end 

そしてrouteに、このラムダを渡す:

route 'foo', &λ 
#⇒ "hello" 

私の知る限りでは、のようなハックのいくつかの種類を使用して明示的に外国binding内のローカル変数を割り当てる方法はありません

block.binding.local_variable_set(:data, 'hello') 
関連する問題