Hash#to_h
Hash#to_h converts the hash to a plain Hash instance. When called without a block, it returns self for a plain Hash but returns a new Hash for subclasses. With a block, it transforms each key-value pair into whatever you return from the block.
No Block: Regular Hash
For a plain Hash, to_h returns self:
h = { a: 1, b: 2 }
h.to_h
# => { a: 1, b: 2 }
h.to_h.object_id == h.object_id # true — same object
This isn’t useful for plain hashes, but matters when dealing with subclassed hashes.
Subclassed Hash
If you subclass Hash, to_h returns a plain Hash with the same content:
class CustomHash < Hash
end
ch = CustomHash.new
ch[:a] = 1
ch[:b] = 2
plain = ch.to_h
plain.class # => Hash (not CustomHash)
plain # => { a: 1, b: 2 }
This is the correct behavior for converting subclassed hashes to regular hashes before passing them to methods that expect plain Hash.
With a Block: Transforming Pairs
When you pass a block, it gets called with each key-value pair and expects a 2-element array return value:
h = { foo: 0, bar: 1, baz: 2 }
h.to_h { |key, value| [value, key] }
# => { 0 => :foo, 1 => :bar, 2 => :baz }
The block returns [new_key, new_value]. Those pairs become the new hash. This is how you transform both keys and values in one pass.
Practical Use Cases
Swapping Keys and Values
{ a: 1, b: 2 }.to_h { |k, v| [v, k] }
# => { 1 => :a, 2 => :b }
Filtering and Transforming
scores = { alice: 95, bob: 82, carol: 98 }
# Keep only keys that are symbols, and double the values
scores.to_h { |k, v| [k, v * 2] if k.is_a?(Symbol) }
# => { alice: 190, bob: 164, carol: 196 }
Since the block must return a 2-element array, returning nil drops that pair:
h = { a: 1, b: 2, c: 3 }
h.to_h { |k, v| v.even? ? [k, v] : nil }
# => { b: 2 }
Converting from Enumerable Operations
Many Enumerable methods return arrays of arrays, not hashes. to_h converts them:
# group_by returns { group_label => [[k,v], [k,v]] }
users = { alice: 28, bob: 35, carol: 28 }
grouped = users.group_by { |_k, v| v }
# Each group is [[key, value], [key, value]] — not a hash
grouped.transform_values { |pairs| pairs.to_h }
# => { 28 => { alice: 28, carol: 28 }, 35 => { bob: 35 } }
Merging with Transform
h1 = { a: 1, b: 2 }
h2 = { b: 3, c: 4 }
# Merge and transform in one pass
h1.merge(h2).to_h { |k, v| [k, v * 10] }
# => { a: 10, b: 30, c: 40 }
Converting Other Collections
to_h also works on arrays of pairs:
[[:a, 1], [:b, 2]].to_h
# => { a: 1, b: 2 }
This is Enumerable#to_h, which Hash includes. The result is a plain Hash.
Keyword Arguments
Ruby 3 dropped the auto-conversion of keyword argument hashes. to_h is useful for explicitly converting when you need to pass a hash as keyword arguments:
def greet(name:, greeting: "Hello")
puts "#{greeting}, #{name}!"
end
opts = { name: "Alice", greeting: "Hi" }
greet(**opts) # works in Ruby 3
greet(**opts.to_h) # explicit conversion (redundant but clear)
Empty Hash
Calling to_h on an empty hash returns an empty hash (or a new empty hash for subclasses):
{}.to_h
# => {}
CustomHash.new.to_h
# => {}
See Also
- /reference/hash-methods/to-a/ — convert a hash to an array of key-value pairs
- /reference/hash-methods/transform-keys/ — transform only keys, keeping values
- /reference/hash-methods/transform-values/ — transform only values, keeping keys