How to output sorted hash to ruby โ€‹โ€‹template

I am creating a configuration file for one of our built-in applications. This is essentially a json file. I have a lot of problems getting a puppet / ruby โ€‹โ€‹1.8 to output the / json hash each time.

I am currently using

<%= require "json"; JSON.pretty_generate data %> 

But when releasing human-readable content, it does not guarantee the same order every time. This means that the puppet often sends change notifications for the same data.

I also tried

 <%= require "json"; JSON.pretty_generate Hash[*data.sort.flatten] %> 

which will generate the same data / order every time. The problem occurs when the data has a nested array.

 data => { beanstalkd => [ "server1", ] } 

becomes

 "beanstalkd": "server1", 

instead

 "beanstalkd": ["server1"], 

I struggled with this for several days and now, so I need help

+7
source share
2 answers

Hash is a disordered data structure. Some languages โ€‹โ€‹(like ruby) have an ordered version of the hash, but in most cases in most languages โ€‹โ€‹you should not rely on any particular hash order.

If order is important to you, you should use an array. So your hash

 {a: 1, b: 2} 

becomes this

 [{a: 1}, {b: 2}] 

I think this does not force too many changes in your code.

Workaround to your situation

Try the following:

 data = {beanstalkId: ['server1'], ccc: 2, aaa: 3} data2 = data.keys.sort.map {|k| [k, data[k]]} puts Hash[data2] #=> {:aaa=>3, :beanstalkId=>["server1"], :ccc=>2} 
0
source

Since the hashes in Ruby are ordered, and the question is marked with , here is a method that will sort the hash recursively (without affecting the order of the arrays):

 def sort_hash(h) {}.tap do |h2| h.sort.each do |k,v| h2[k] = v.is_a?(Hash) ? sort_hash(v) : v end end end h = {a:9, d:[3,1,2], c:{b:17, a:42}, b:2 } p sort_hash(h) #=> {:a=>9, :b=>2, :c=>{:a=>42, :b=>17}, :d=>[3, 1, 2]} require 'json' puts sort_hash(h).to_json #=> {"a":9,"b":2,"c":{"a":42,"b":17},"d":[3,1,2]} 

Please note that this will not happen catastrophically if your hash has keys that cannot be compared. (If your data comes from JSON, this will not be the case, since all keys will be strings.)

+3
source

All Articles