最近、仕事が忙しくて、小物のgemを作るというoutputが無かったので、思い付いたものを無理矢理形にしてみた。
タイトル通りで、キーワード引数で受け取った値をHashとしてまとめて取得するgem。
どういうものかというと以下の様な感じになる。
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拡張になってたりするし、多分あんまりパフォーマンス良くない。
名前は違っててもいいので、本家に入れてくれんかなあと少し思う。