rubyguides

Hash#store

Hash#store associates a value with a key in a hash. It is functionally identical to the bracket assignment syntax h[key] = value, but the method form makes the return value explicit: store returns the value that was just stored, not the hash.

That explicit return value can make small examples easier to reason about, especially when you want to capture the stored value immediately. It also mirrors the assignment behavior you already get from []= in Ruby, so the main choice is usually readability.

Syntax

h.store(key, value) → value

Parameters

ParameterTypeDescription
keyObjectThe key to associate — can be any object
valueObjectThe value to associate with the key

Return Value

store returns the value that was stored — not the hash. This is different from languages like Python where dict[key] = value returns the value, but it matches Ruby’s bracket assignment which also returns the stored value.

h = {}
result = h.store(:name, "Alice")
result # => "Alice"

That return value is easy to miss if you only think about assignment syntax. Seeing it in a variable makes the behavior explicit and helps explain why store can be useful in small examples or when you need the inserted value right away.

Examples

Basic usage

h = {}
h.store(:name, "Alice")
h.store(:age, 30)
h # => {:name=>"Alice", :age=>30}

This is the most common use case: add one entry at a time and keep the code readable. In a hash-building loop, store reads a little more like a method call than an assignment, which some people prefer when the operation is part of a longer chain.

Overwriting an existing key

h = {name: "Alice", age: 30}
h.store(:name, "Bob")
h # => {:name=>"Bob", :age=>30}

Overwriting an existing key is not special in Ruby hashes. The newer value simply replaces the old one, so store behaves the same way as []= when a key is already present.

Chaining assignments

Because store returns the stored value, you can chain it:

h = {}
[h.store(:a, 1), h.store(:b, 2), h.store(:c, 3)]
# => [1, 2, 3]

This example is a reminder that store returns the value, not the hash object. That makes it easy to build a list of the inserted values, but it does not support method chaining on the hash itself.

In other words, store is useful for the side effect on the hash, but the expression result is the value you passed in. That distinction is what makes the method feel different from fluent APIs that return the receiver.

With arbitrary key types

h = {}
h[[1, 2, 3]] = "array key"
h[[1, 2, 3]] # => "array key"

h[->() { 42 }] = "lambda key"
h[->() { 42 }] # => nil (each lambda is a different object)

Arbitrary keys are legal in Ruby, but lookup still depends on object identity and hash behavior. Two objects that look similar can still be different keys if Ruby sees them as distinct values.

That is why it helps to pick a stable key type early. If you know the hash will be read by name later, use a key shape that stays consistent across the whole code path.

nil as a key

h = {}
h[nil] = "null value"
h[nil] # => "null value"

Using nil as a key is sometimes useful when you are storing a default or fallback entry. The important part is consistency, because the same key must be used for both writing and reading.

It can also make guard code a little simpler when you want one slot for the “no explicit key” case. The tradeoff is the same as with any special key: document it so the next reader knows why it is there.

store vs []

Both store and []= associate a key with a value. There is no functional difference.

h = {}

h[:key] = "value"     # => "value"
h.store(:key2, "val") # => "val"

h # => {:key=>"value", :key2=>"val"}

The two forms are interchangeable in everyday code, so the choice is mostly about style. Use the one that reads best in the surrounding method, and keep the rest of the code consistent.

Choose store when you want the method call form to be explicit, or []= when bracket syntax feels more natural.

Gotchas

Mutating a key object breaks lookup

Using a mutable object as a key and then mutating it breaks hash lookups, because the key’s hash value changes:

h = {}
key = [1, 2]
h[key] = "value"

key << 3
h[key]     # => nil — hash of [1,2] changed
h[[1, 2]]  # => nil — no key with hash of [1,2] exists anymore

This is one of the main reasons Ruby developers prefer stable keys such as symbols, frozen strings, or numbers. If the object’s value can change after insertion, the lookup rules can no longer find it reliably.

Always use immutable objects (symbols, strings, numbers, frozen arrays) as hash keys when possible.

String and symbol keys are distinct

h = {}
h["name"] = "Alice"
h[:name]  = "Bob"
h # => {"name"=>"Alice", :name=>"Bob"}
h["name"]  # => "Alice"
h[:name]   # => "Bob"

The split between string and symbol keys is a common source of subtle bugs. When you design an API or data shape, choose one convention and stick to it so later lookups stay predictable.

See Also