Hash#fetch
は便利なメソッドです。基本的には Hash#[]
と同じ動作をしますが、キーが存在しない場合の動作が異なります。
key が存在しない場合は例外が発生する
Hash#[]
では指定した key が存在しない場合は nil
を返します。
user = {
id: 1,
name: "Yamada Tarou"
}
p user[:name] #=> "Yamada Tarou"
p user[:email] #=> nil
しかし、Hash#fetch
メソッドでは指定した key が存在しない場合は例外が発生します。これは Hash.new(0)
のようにハッシュにデフォルト値を設定していても発生します。
user = {
id: 1,
name: "Yamada Tarou"
}
p user.fetch(:name) #=> "Yamada Tarou"
p user.fetch(:email) #=> `fetch': key not found: :email (KeyError)
例外が発生するため、key のスペルミスによるバグが発生しなくなります。
デフォルト値を指定することが可能
Hash#fetch
は第二引数にデフォルト値を指定することが可能で、key が存在しない場合はこのデフォルト値を返します。
user = {
id: 1,
name: "Yamada Tarou"
}
p user.fetch(:name) #=> "Yamada Tarou"
p user.fetch(:email, "dummy@example.com") #=> "dummy@example.com"
Hash#[]
でも似たような操作を書くことは可能ですが
user = {
id: 1,
name: "Yamada Tarou"
}
p user[:admin] || true #=> true
p user.fetch(:admin, true) #=> true
指定した key の値が nil
や false
の場合に期待した動作にならない場合があるので注意が必要です。
user = {
id: 1,
name: "Yamada Tarou",
admin: false
}
p user[:admin] || true #=> true
p user.fetch(:admin, true) #=> false
ブロックを受け取れる
また、Hash#fetch
ではブロックを渡すことも可能で、キーが存在しない場合はそのブロックの戻り値を返します。ブロック引数には指定した key の値が入ります。
user = {
id: 1,
name: "Yamada Tarou"
}
p user.fetch(:name) #=> "Yamada Tarou"
p user.fetch(:email) { |key|
"#{key} not found" #=> "email not found"
}
これは第二引数に Proc オブジェクトを渡すことで同様のことが可能です。
default = -> (key) {
"#{key} not found"
}
user = {
id: 1,
name: "Yamada Tarou"
}
p user.fetch(:name) #=> "Yamada Tarou"
p user.fetch(:email, &default) #=> "email not found"
参考サイト