mr_muscle
mr_muscle

Reputation: 2900

Merge multiple hashes after new key

I've got three hashes which I want to merge to base_options under new key - checks. Basically what I want to achieve is:

  {
    base_options,
    checks: {
      document_check,
      identity_check,
      dummy_check,
    }
  },

Below sample hash data:

  dummy_check = {
    dummy: {
      enabled: true,
      preferences: {
        state: 0,
        replay: true,
      },
     }
    }

  identity_check = {
    identity: {
      enabled: true,
      preferences: {},
    },
  }

  document_check = {
      document: {
        enabled: true,
        preferences: {
          face: false,
          liveness: false,
          docs_all: true,
        },
      },
    }

  base_options = {
    send_email: true,
    send_reminder: false,
    reset_client_status: true,
  }

So if I do base_options.merge!(checks: document_check.merge!(identity_check, dummy_check)) I will receive expected hash which is:

  {
    send_email: true,
    send_reminder: false,
    reset_client_status: true,
    checks: {
      document: {
        ...
      },
      identity: {
        ...
        },
      dummy: {
        ...
      }
    },
  }

But this is not super flexible and I don't know if using .merge! two times in one line is not a crap. Are there any other alternatives?

I'm using Ruby 2.7 and Rails 6

Upvotes: 0

Views: 134

Answers (3)

Prashanth Adepu
Prashanth Adepu

Reputation: 69

The answer is in your question, below can be a simple way of achieving the end result. Below is after initializing values of base_options, document_check, identity_check,dummy check.

base_options = {
    base_options: base_options,
    checks: {
      document_check: document_check,
      identity_check: identity_check,
      dummy_check: dummy_check,
    }
  }

=> {:base_options=>{:send_email=>true, :send_reminder=>false, :reset_client_status=>true}, :checks=>{:document_check=>{:document=>{:enabled=>true, :preferences=>{:face=>false, :liveness=>false, :docs_all=>true}}}, :identity_check=>{:identity=>{:enabled=>true, :preferences=>{}}}, :dummy_check=>{:dummy=>{:enabled=>true, :preferences=>{:state=>0, :replay=>true}}}}}

Upvotes: 0

Holger Just
Holger Just

Reputation: 55833

Using merge! is fine and well understood. However, as you are setting a single key on your base_options hash, you can also simple use the hash accessor, i.e.

base_options[:checks] = document_check.merge!(identity_check, dummy_check)

Note that this will also change the document_hash object as merge! modified the receiver. If this is not desired, you can also use merge and return a new Hash. Thus could look like:

base_options[:checks] = document_check.merge(identity_check, dummy_check)

or equivalently

base_options[:checks] = {}.merge!(document_check, identity_check, dummy_check)

The latter option is slightly slower but might better show your intended behavior and is thus easier to understand to readers of your code.

Upvotes: 1

If I understand correctly, you can try the Double Splat **. you can use like this:

base_options.merge(
  checks: **document_check, **identity_check, **dummy_check
)

Upvotes: 0

Related Questions