Ruby

[小ネタ] Rubyのキーワード引数で受け取った値をHashとしてまとめて取得するgem

More than 1 year has passed since last update.

最近、仕事が忙しくて、小物のgemを作るというoutputが無かったので、思い付いたものを無理矢理形にしてみた。

タイトル通りで、キーワード引数で受け取った値をHashとしてまとめて取得するgem。

どういうものかというと以下の様な感じになる。

joker1007/given_keyword_args

require 'given_keyword_args'

class Dummy
def dummy(foo:, bar: "bar", **options)
given_keyword_args
end

def dummy_with_rest(foo:, bar: "bar", **options)
given_keyword_args_with_rest
end
end

p Dummy.new.dummy(foo: "foo", other1: "other1", other2: "other2") # => {foo: "foo", bar: "bar"}
p Dummy.new.dummy_with_rest(foo: "foo", other1: "other1", other2: "other2") # => {foo: "foo", bar: "bar", other1: "other1", other2: "other2"}

なんで、こんなのが欲しいかというと、例えばCLIツールのエントリポイントとして割と多くのキーワード引数をオプションで受け取るタイプのメソッドがあったりすると、内部でメソッドを細かく分けた時に、ほぼ同じキーワード引数を続きの処理にぶん投げる、みたいなことがしばしばあって、それを一々同じこと書くのが面倒だったからです。

こういうのが……

class Dummy

def dummy(foo:, bar: "bar", aws_access_key: nil, aws_secret_access_key: nil, aws_region: nil)
puts foo
continue(
bar: bar,
aws_access_key: aws_access_key_id,
aws_secret_access_key: aws_secret_access_key,
aws_region: aws_region
)
end

def continue(bar: "bar", , aws_access_key: nil, aws_secret_access_key: nil, aws_region: nil)
# ...
end
end

こうなる。

class Dummy

def dummy(foo:, bar: "bar", a: 1, b: 2, c: 3)
puts foo
continue(**(given_keyword_args.tap { |h| h.delete(:foo) }))
end

def continue(bar: "bar", a: 1, b: 2, c: 3)
# ...
end
end

まあ、これぐらいだとそんなに差は無いかもしれない……。

内側で割と無茶やってて、ローカル変数をbinding.local_variable_getで取得しているのだが、引数を使わずに暗黙のうちにbindingを受け渡す必要があって、こんな些細なことのためにC拡張になってたりするし、多分あんまりパフォーマンス良くない。

名前は違っててもいいので、本家に入れてくれんかなあと少し思う。