rubyguides

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:

MethodDescription
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

ParameterTypeDefaultDescription
keyObjectRequiredThe 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 name
  • has_key? — The most explicit alias
  • key? — The shortest alias
  • member? — 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