Hash#key?
The key? method returns true if the given key is present in the hash, false otherwise.
Syntax
hash.key?(key) # => true or false
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
key | Object | Required | The key to look up in the hash |
Return Value
Returns true if key exists in the hash, false if it does not.
Description
key? is one of four identical methods for checking key existence on Ruby’s Hash. The others are has_key?, include?, and member?. All four do the same thing — they use the hash’s internal lookup, which is O(1) on average.
Use key? when you want to verify a key is present before accessing or modifying its value. This is safer than direct access with [], which returns nil for missing keys (unless the hash has a default).
Examples
Basic usage
config = { host: "localhost", port: 5432, ssl: true }
config.key?(:host) # => true
config.key?(:timeout) # => false
Guarding against missing keys
def connect(options)
raise ArgumentError, "host is required" unless options.key?(:host)
host = options[:host]
port = options.fetch(:port, 5432)
# ...
end
key? is often paired with fetch when you want to distinguish between a missing key and an explicit nil value:
settings = { debug: false }
if settings.key?(:debug)
# key exists, even if the value is falsy
enable_debugging if settings[:debug]
end
With symbol and string keys
Symbol and string keys are distinct in Ruby hashes:
prefs = { theme: "dark", "font_size" => 14 }
prefs.key?(:theme) # => true
prefs.key?("theme") # => false
prefs.key?("font_size") # => true
Checking before assignment
defaults = { timeout: 30, retries: 3 }
user_options = { timeout: 60 }
def merge_options(defaults, overrides)
merged = defaults.dup
overrides.each do |key, value|
merged[key] = value if merged.key?(key)
end
merged
end
merge_options(defaults, user_options)
# => { timeout: 60, retries: 3 }
Only keys that exist in the defaults are taken from overrides.
Aliases
key? is equivalent to:
has_key?— same behavior, more explicitinclude?— same behavior, older namemember?— same behavior, oldest alias
h = { a: 1, b: 2 }
h.key?(:a) # => true
h.has_key?(:a) # => true
h.include?(:a) # => true
h.member?(:a) # => true
Gotchas
Confusing key? with value?. key? checks keys. value? checks values. These are independent lookups:
scores = { alice: 95, bob: 82 }
scores.key?(:alice) # => true — :alice is a key
scores.value?(95) # => true — 95 is a value
scores.key?(95) # => false — 95 is not a key
scores.value?(:alice) # => false — :alice is not a value
Using ||= with potentially nil values. If a key exists with an explicit nil value, key? returns true but ||= still overwrites:
config = { debug: nil }
config.key?(:debug) # => true
config[:debug] ||= false # overwrites nil with false — probably not what you want
Use fetch instead when you need to distinguish between a missing key and nil.
See Also
hash-has-key— the more explicit aliashash-has-value— check if a value exists insteadhash-keys— returns all keys in the hash