Hash#include?
The include? method checks whether a hash contains a specific key. It’s one of several key-checking methods available on Ruby’s Hash class.
You will often see it in guard clauses and feature checks because it answers one narrow question very quickly: does this key exist? That keeps the calling code simple when the next step depends on the presence of a value rather than its contents.
Syntax
hash.include?(key) # => true or false
Aliases
The include? method has three aliases:
| Method | Description |
|---|---|
has_key? | Same behavior, most explicit |
key? | Same behavior, shorter |
member? | Same behavior, older alias |
include? | Original method name |
All four methods check whether the given object exists as a key in the hash.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
key | Object | Required | The key to search for in the hash |
Return Value
Returns true if the key exists in the hash, false otherwise.
Description
Ruby’s Hash class provides four methods for checking key existence:
include?— The original method namehas_key?— The most explicit aliaskey?— The shortest aliasmember?— An older alias
All four do exactly the same thing: they check whether the argument is a key in the hash. They use the internal lookup mechanism, making them O(1) for average case.
This method is useful when you need to verify that a particular key exists before accessing or modifying its value.
It is especially handy when the hash may be sparse or built from user input. A quick existence check can keep the follow-up code from assuming more than the data actually provides.
Examples
Basic usage
hash = { name: "Alice", age: 30, city: "London" }
hash.include?(:name) # => true
hash.include?(:age) # => true
hash.include?(:country) # => false
The basic call is straightforward, but the aliases are worth knowing because they often appear in older Ruby code. All four methods — include?, has_key?, key?, and member? — delegate to the same internal lookup. The only practical difference is convention: key? is the shortest and most common in newer projects, while has_key? and member? are explicit enough to be clear without additional comments.
Using the aliases
config = { theme: "dark", debug: false }
config.has_key?(:theme) # => true
config.key?(:debug) # => true
config.member?(:missing) # => false
Choosing among the aliases is a style decision. The key? form is concise and reads naturally in guard clauses. The has_key? form is more explicit and can make the intent clearer when the code is reviewed by someone less familiar with Ruby. Either way, the underlying mechanism is the same, so the choice should match the conventions of the project.
With different key types
mixed_keys = { "string_key" => 1, :symbol_key => 2, 42 => 3 }
mixed_keys.include?("string_key") # => true
mixed_keys.include?(:symbol_key) # => true
mixed_keys.include?(42) # => true
mixed_keys.include?("missing") # => false
Ruby hashes accept keys of any type — strings, symbols, integers, and even objects. The type you use determines how the lookup works: "string_key" and :string_key are distinct keys. This flexibility is powerful, but it also means you need to be consistent about which key type you use throughout a codebase, especially when data comes from external sources like JSON or CSV files.
Checking before access
options = { timeout: 30, retries: 3 }
if options.include?(:timeout)
puts "Timeout is set to #{options[:timeout]}"
end
That pattern is common when you want to keep the read path explicit. The key check stays close to the access, so it is easy to see why the lookup is safe. It also avoids the surprise of a nil return from [] being misinterpreted as “key absent” when the key actually exists and its value happens to be nil.
With nil as a key
sparse = { nil => "null value", "key" => 42 }
sparse.include?(nil) # => true
sparse.include?("key") # => true
sparse.include?("not_there") # => false
Performance Note
The include? method (and its aliases) use the internal lookup mechanism, making them O(1) on average. This is much faster than iterating through all keys.
If you find yourself calling include? or has_key? repeatedly, consider whether the data structure fits your access pattern.
If the code is checking many keys in a tight loop, it may be worth reshaping the data or caching the derived result. The method itself is fast, but the surrounding design still matters.
See Also
hash-has-key— The explicit alias for include?hash-has-value— For checking values instead of keyshash-keys— Returns all keys in the hashhash-values— Returns all values in the hashhash-merge— Merge hashes together