# proposal: Hash#deep\_set

**URL:** <https://discuss.rubyonrails.org/t/proposal-hash-deep-set/89423>\
**Category:** rubyonrails-core\
**Created:** [June 24, 2025, 6:39am UTC](https://discuss.rubyonrails.org/t/proposal-hash-deep-set/89423 "2025-06-24T06:39:01Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![pavel.ev](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/pavel.ev/32/13396_2.png) [@pavel.ev](https://discuss.rubyonrails.org/u/pavel.ev)\
**Post date:** [June 24, 2025, 6:39am UTC](https://discuss.rubyonrails.org/t/proposal-hash-deep-set/89423/1 "2025-06-24T06:39:01Z")

</div>

When we want to set value in nested Hash the code become longer, I’d like to have similar to `Hash#dig` but for setting values

example:

```ruby
users_hash = {}

users.each do |user|
  country_code = user.country&.code
  users_hash[country_code] ||= {}
  users_hash[country_code][user.city] ||= {}
  users_hash[country_code][user.city][user.email] = user
end

```

With Hash#deep\_set (or other better name) it could be

```ruby
users_hash = {}

users.each do |user|
  users_hash.deep_set(
    [user.country&.code, user.city, user.email] => user
  )

  # or
  users_hash.deep_set(user.country&.code, user.city, user.email, with: user)

  #
  users_hash.deep_hash(user.country&.code, user.city)[user.email] = user

  # or
  users_hash.deep_set_array(user.country&.code, user.city, with: user)
end

```

Also, can override `:[]=` method to support multiple arguments

```ruby
... 
def []=(*args, **kargs)
  # make deep set
end
...

users_hash = HashWithDeepSet.new # or {}.with_deep_set
users.each do |user|
  users_hash[user.country&.code, user.city, user.email] = user

  # or
  users_hash[user.country&.code, user.city, fill_with: []] << user
end

```

some other useful methods I copy from project to project, mostly for large arrays to make lookup faster

```ruby
def map_by_key(array, key)
  result = {}
  array.each do |element|
    result[element[key]] ||= []
    result[element[key]] << element
  end

  result
end

def uniq_map_by_key(array, key)
  result = {}
  array.each do |element|
    result[element[key]] = element
  end

  result
end

```

---

<div class="post-metadata">

**Author:** ![e\_a](https://avatars.discourse-cdn.com/v4/letter/e/9fc348/32.png) [@e\_a](https://discuss.rubyonrails.org/u/e_a)\
**Post date:** [July 5, 2025, 6:37pm UTC](https://discuss.rubyonrails.org/t/proposal-hash-deep-set/89423/2 "2025-07-05T18:37:02Z")

</div>

This seems to have similarity with [this previous proposal](https://discuss.rubyonrails.org/t/proposal-add-hash-transform-value-to-activesupport-hash-only-bury/81787). As suggested on that discussion, using the `default_proc` functionality of Ruby to auto-create nested hashes seems to offer similar benefits without anything new.

As to your `map_by_key` that seems to be doing the same thing as Ruby built-in [group\_by](https://rubyapi.org/3.4/o/enumerable#method-i-group_by) function. And your `uniq_map_by_key` seems like the same as the ActiveSupport’s built-in [index\_by](https://api.rubyonrails.org/classes/Enumerable.html#method-i-index_by) function.
