これらを一度に1つずつ取ります。何がmethod_missing
起こっているのか混乱させるだけなので、これを完全に取り除いてください。それは実際にはそれとは完全に無関係です。
感嘆符*
は2つのことをします。メソッド定義の引数では、複数の引数を配列に吸収します。メソッド呼び出しで使用すると、配列が個々の引数に飛び出します。両方を使用すると、任意の数の引数を別のメソッドに転送できます。
def foo(*args)
bar(*args)
end
def bar(a, b, c)
puts a
puts b
puts c
end
foo(1,2,3) # prints 1, 2 and then 3
基本的にすべての引数を転送しているので、これは同じパターンです。
これ&
はブロック引数用です。メソッド呼び出しごとにこれらの1つだけが存在する可能性があり、最後にぶら下がっているのはブロックです。これは、引数に直接含まれないという点で、特別な引数です。メソッド定義&someblock
の最後の引数としてaddをキャプチャすることにより、ブロックを変数にキャプチャできます。
次に、同じ構文を使用して、メソッド呼び出しでブロックを渡すことができます。
def foo(&block)
bar(&block)
end
def bar
yield
end
foo { puts 'hello' } # prints hello
これにより、ハンギングブロックを呼び出さずに別のメソッドに渡すことができます。yield
通常は、渡されたブロックを実行するために使用するだけなので、必ずしも必要ではありません。ただし、実行するだけでなく何かを実行したい場合は、ブロック自体への参照をキャプチャする必要があります。
したがって、これら2つのことを組み合わせると、究極のメソッドフォワーダーが得られます。任意の数の引数のすべて、および最後にぶら下がっていたブロックをキャプチャし、それらを別のメソッドに送信します。
# forwards everything to the method `bar`
def foo(*args, &block)
bar(*args, &block)
end
最後に、これsend
は単なる方法です。メソッドの名前の後に任意の数の引数(配列ではない)が続くことを想定しており、オプションでハンギングブロックを処理できます。
言い換えると:
foo.send methodName, *args, &block