やりたいこと
このようなメソッドがあるとする。
def my_method(key1:, key2:)
# do something
end
このメソッドの中で {key1: 引数値, key2: 引数値}
のような hash が欲しい。
まずはメソッドの引数の定義情報を得る
定義したメソッドの引数名の一覧は Method#parameters で得られる。
def my_method(key1:, key2:, key3:)
p method(__method__).parameters
# => [[:keyreq, :key1], [:keyreq, :key2], [:keyreq, :key3]]
end
my_method(key1: "val1", key2: "val2", key3: "val3")
上記の様に Method#parameters は引数の数だけの要素数の配列を返す。各要素の1つ目の要素は 引数の種類を表すシンボル、2つ目の要素は 引数名 となる。実際の引数の値は含まれない点に留意する。
今回はキーワード引数のデフォルト値を定義してない為、各1つ目の要素は「必須のキーワード引数」を表す :keyreq
となっている。
キーワード引数を表すシンボルは :keyreq
か :key
なので、これらに一致する変数をハッシュに変換できれば実現できそう。
ということで実現方法は以下。
キーワード引数をハッシュとして受け取る方法
eval で変数名を評価した結果(つまり変数の値)をハッシュに入れていく。
def my_method(key1:, key2:)
named_params = method(__method__).parameters.each_with_object({}) do |p, h|
parameter_type, name = p
is_keyword_parameter = [:key, :keyreq].include? parameter_type
next unless is_keyword_parameter
h[name] = eval(name.to_s)
end
p named_params
# => {:key1=>"val1", :key2=>"val2"}
end
my_method(key1: "val1", key2: "val2")
短縮版
def my_method(key1:, key2:)
named_params = method(__method__).parameters.each_with_object({}) do |p, h|
h[p[1]] = eval(p[1].to_s) if [:key, :keyreq].include? p[0]
end
p named_params
# => {:key1=>"val1", :key2=>"val2"}
end
my_method(key1: "val1", key2: "val2")