search
LoginSignup
8

More than 5 years have passed since last update.

posted at

updated at

Organization

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

最近、仕事が忙しくて、小物の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拡張になってたりするし、多分あんまりパフォーマンス良くない。
名前は違っててもいいので、本家に入れてくれんかなあと少し思う。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
8