/ Tags: RUBY-CODE / Categories: SOLUTIONS

Deep Merge Two Nested Hashes Without Losing Keys In Ruby

Perform a recursive hash merge that combines nested values instead of overwriting them — useful for configuration merging, settings overrides, and building complex data structures.

Description

Ruby’s built-in Hash#merge is shallow — it overwrites nested hashes entirely when keys conflict. A deep merge recursively combines nested hashes so both sides contribute keys at every level. The pattern: if both values for a key are Hash, recurse into them. Otherwise use the right-hand value (override behavior). Implement as a recursive method or a merge block. Rails provides Hash#deep_merge in ActiveSupport. For plain Ruby, implement it with a recursive block or extend Hash.

Sample input:

  defaults = { db: { host: "localhost", port: 5432 }, cache: { ttl: 60 } }
  overrides = { db: { port: 5433, ssl: true } }


Sample Output:

  { db: { host: "localhost", port: 5433, ssl: true }, cache: { ttl: 60 } }

Answer

    defaults = { db: { host: "localhost", port: 5432 }, cache: { ttl: 60 } }
    overrides = { db: { port: 5433, ssl: true } }

    # Using merge with a recursive block
    def deep_merge(base, overrides)
      base.merge(overrides) do |_key, base_val, override_val|
        if base_val.is_a?(Hash) && override_val.is_a?(Hash)
          deep_merge(base_val, override_val)
        else
          override_val
        end
      end
    end

    deep_merge(defaults, overrides)
    # => { db: { host: "localhost", port: 5433, ssl: true }, cache: { ttl: 60 } }

    # In-place variant
    def deep_merge!(base, overrides)
      base.merge!(overrides) do |_key, base_val, override_val|
        base_val.is_a?(Hash) && override_val.is_a?(Hash) ? deep_merge!(base_val, override_val) : override_val
      end
    end

    # Rails / ActiveSupport (if available)
    require 'active_support/core_ext/hash/deep_merge'
    defaults.deep_merge(overrides)
    # => { db: { host: "localhost", port: 5433, ssl: true }, cache: { ttl: 60 } }

Learn More

cdrrazan

Rajan Bhattarai

Full Stack Software Developer! 💻 🏡 Grad. Student, MCS. 🎓 Class of '23. GitKraken Ambassador 🇳🇵 2021/22. Works with Ruby / Rails. Photography when no coding. Also tweets a lot at TW / @cdrrazan!

Read More