Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

Rubyのキーワード引数にto_hashを実装するオブジェクトを渡すとキーワード引数として展開される

More than 1 year has passed since last update.

TL;DR

Rubyにおいて、キーワード引数を取るメソッドには、to_hashメソッドを実装しているオブジェクトを渡すことができて、キーワード引数として展開して解釈される。

キーワード引数とは

def log(msg, level: "ERROR", time: Time.now)
  puts "#{ time.ctime } [#{ level }] #{ msg }"
end

log("Hello!", level: "INFO")  #=> Mon Feb 18 01:46:22 2013 [INFO] Hello!

(https://magazine.rubyist.net/articles/0041/0041-200Special-kwarg.html より引用)

このlogメソッドのleveltimeみたいな感じで、引数にデフォルト値を指定することができて、また名前を指定して引数を渡せるという便利機能です。

Hashはキーワード引数に展開される

キーワード引数にはHashを渡すことができて、その場合はHashの中身が展開されます

# 普通の使い方
log('aaa', level: 'AAA') # => Wed Nov  6 09:16:36 2019 [AAA] aaa
# Hashも渡せる
log('aaa', {level: 'AAA'}) # => Wed Nov  6 09:16:44 2019 [AAA] aaa

このようなHash => keyword引数の変換はRuby 2.7ではdeprecatedになったので注意してください 1

Hash以外もキーワード引数にわたす

そして、キーワード引数に渡して展開されるのはHashだけではありません。「to_hashを実装しており、かつその返り値のkeyがsymbolであるオブジェクト」ならなんでも展開されます。

# to_hashを実装しているクラス
class HogeWithToHash
  def to_hash
    { level: 'AAA' }
  end
end

# キーワード引数として展開される
log('aaa', HogeWithToHash.new) # => Wed Nov  6 09:27:25 2019 [AAA] aaa

# to_hashを実装しているが返り値のHashのkeyが文字列であるクラス
class HogeWithToHashStringKey
  def to_hash
    { 'level' => 'AAA' }
  end
end

# キーワード引数として正しく展開されない
log('aaa', HogeWithToHashStringKey.new) # => ArgumentError (wrong number of arguments (given 2, expected 1))

キーワード引数に展開されるオブジェクトの例: Rake::TaskArguments

このような条件を満たすオブジェクトとして、Rakeタスクを定義するときに使われる Task::Arguments が挙げられます。したがって、以下のRakefileは正しく動きます:

def greet(first_name:, last_name:)
  puts "Hello, #{first_name} #{last_name}"
end

task :greet, [:first_name, :last_name] do |t, args|
  greet(args)
end
$ rake "greet[Ichiro,Tanaka]"
Hello, Ichiro Tanaka

以上

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away