Ruby hash nesting

I have a method that selects all rows from my table like this:

smtp_status_raw = my_table.select(:message, :is_valid, :hostname).map { |h| h.values }

      

This returns an array that looks like this:

[{:message=>"blah", :is_valid=>true, :hostname=>"1"}, {:message=>"blah", :is_valid=>true, :hostname=>"2"}, {:message=>"blah", :is_valid=>true, :hostname=>"3}]

      

Using the information above, I want to create a hash that looks like this:

{ 
:node_status => 
    {
        {:hostname => "1", :message: "blah"},
        {:hostname => "2", :message: "blah"},
        {:hostname => "3", :message: "blah"}
    }
}

      

First of all, my question is - is it possible to create a hash like above? In the above Sequel request example, I have three objects that represent three separate nodes and I want to add those three nodes to the key :node_status

. Is it possible? If this is not a valid hash, then what is the alternative?

Second, this is what I tried:

# Initialize the hash
smtp_status_hash = { :node_status: => nil }

      

I've initialized a hash smtp_status_hash

with a key node_status

, but I'm not sure how to nest the query results.

+3


source to share


2 answers


This is not a valid hash because you have 3 values ​​but no keys in the sub-step :node_status

. You can do something like:

smtp_status_raw = [
  {:message=>"blah", :is_valid=>true, :hostname=>"1"},
  {:message=>"blah", :is_valid=>true, :hostname=>"2"},
  {:message=>"blah", :is_valid=>true, :hostname=>"3"}
]

{
  node_status: smtp_status_raw.collect do |hash|
    hash.reject { |key, value| key == :is_valid }
  end
}

      

to get the values ​​in :node_status

as an array:

{
  :node_status=>[
    {:message=>"blah", :hostname=>"1"},
    {:message=>"blah", :hostname=>"2"},
    {:message=>"blah", :hostname=>"3"}
  ]
}

      

Or you could do something like:

{
  node_status: smtp_status_raw.collect do |hash|
    [hash[:hostname], hash[:message]]
  end.to_h
}

      

which sets up a sub-hash with key

being :hostname

and value

:message

:

{
  :node_status=>{
    "1"=>"blah",
    "2"=>"blah",
    "3"=>"blah"
  }
}

      



or if you had more keys that you wanted to keep:

{
  node_status: smtp_status_raw.collect do |hash|
    [hash[:hostname], hash.reject { |key, value| key == :is_valid }]
  end.to_h
}

      

which is still the hash where it key

is :hostname

, but value

has a different hash:

{
  :node_status=>{
    "1"=>{:message=>"blah", :hostname=>"1"},
    "2"=>{:message=>"blah", :hostname=>"2"},
    "3"=>{:message=>"blah", :hostname=>"3"}
  }
}

      

To set key values ​​after creation Hash

, you can do something like:

smtp_status_hash = { node_status:  nil }
smtp_status_hash[:node_status] = "Whatever you want here"

      

You can read more about Hash

and its methods and how you can select

both reject

save or delete keys from a hash. Hashes, although they are the structure of the dictionary and should always have key

one value

, although this value may be Array

different Hash

.

+5


source


try it



smtp_status_hash = {:node_status=>[]}; my_table.select(:message, :is_valid, :hostname).map{ |h| h.values }.each{|i| smtp_status_hash[:node_status] << (i)}

0


source







All Articles