ruby - Nested Hashes and method reuse -


i have hashes want iterate, , have nested hashes can go 3-4 levels deep, using if statement @ moment check see if value hash , iterate through again i'm repeating code here.

is there dry way using method?

also want final output end in table, what's best way this? that's why had multiple if statements add separate tags.

example method:

<% def hashtest(key, value) %>     <% if value.is_a?(hash) %>         <%= key %>             <% value.each |key, value| %>                 <%= key %>                 <%= value %>             <% end %>     <% else %>         <%= key %>         <%= value %>     <% end %> <% end %> 

and mess of if statements have...

<% parsed.each |key, value| %>     <% if value.is_a?(hash) %>         <%= key %>         <br/>         <% value.each |key, value| %>                 <% if value.is_a?(hash) %>                     <%= key %>                     <br/>                     <% value.each |key, value| %>                             <% if value.is_a?(hash) %>                             <%= key %>                             <br/>                                 <% value.each |key, value| %>                                     <%= key %>                                     <%= value %>                                     <br/>                                 <% end %>                             <% else %>                                 <%= key %>                                 <%= value %>                                 <br/>                             <% end %>                     <% end %>                 <% else %>                     <%= key %>                     <%= value %>                     <br/>                 <% end %>         <% end %>     <% else %>         <%= key %>         <%= value %>         <br/>     <% end %> <% end %> 

example input:

{   "statement": {     "generated": "2015-01-11",     "due": "2015-01-25",     "period": {       "from": "2015-01-26",       "to": "2015-02-25"     }   },   "total": 136.03,   "package": {     "subscriptions": [       { "type": "tv", "name": "movies", "cost": 50.00 },       { "type": "phone", "name": "landline", "cost": 5.00 },       { "type": "broadband", "name": "fibre", "cost": 16.40 }     ],     "total": 71.40   },   "callcharges": {     "calls": [       { "called": "07716393769", "duration": "00:23:03", "cost": 2.13 },       { "called": "07716393769", "duration": "00:23:03", "cost": 2.13 },       { "called": "07716393769", "duration": "00:23:03", "cost": 2.13 },       { "called": "07716393769", "duration": "00:23:03", "cost": 2.13 },       { "called": "07716393769", "duration": "00:23:03", "cost": 2.13 },       { "called": "07716393769", "duration": "00:23:03", "cost": 2.13 },       { "called": "07716393769", "duration": "00:23:03", "cost": 2.13 },       { "called": "07716393769", "duration": "00:23:03", "cost": 2.13 },       { "called": "07716393769", "duration": "00:23:03", "cost": 2.13 },       { "called": "07716393769", "duration": "00:23:03", "cost": 2.13 },       { "called": "07716393769", "duration": "00:23:03", "cost": 2.13 },       { "called": "07716393769", "duration": "00:23:03", "cost": 2.13 },       { "called": "07716393769", "duration": "00:23:03", "cost": 2.13 },       { "called": "07716393769", "duration": "00:23:03", "cost": 2.13 },       { "called": "07716393769", "duration": "00:23:03", "cost": 2.13 },       { "called": "07716393769", "duration": "00:23:03", "cost": 2.13 },       { "called": "07716393769", "duration": "00:23:03", "cost": 2.13 },       { "called": "07716393769", "duration": "00:23:03", "cost": 2.13 },       { "called": "02074351359", "duration": "00:23:03", "cost": 2.13 },       { "called": "02074351359", "duration": "00:23:03", "cost": 2.13 },       { "called": "02074351359", "duration": "00:23:03", "cost": 2.13 },       { "called": "02074351359", "duration": "00:23:03", "cost": 2.13 },       { "called": "02074351359", "duration": "00:23:03", "cost": 2.13 },       { "called": "02074351359", "duration": "00:23:03", "cost": 2.13 },       { "called": "02074351359", "duration": "00:23:03", "cost": 2.13 },       { "called": "02074351359", "duration": "00:23:03", "cost": 2.13 },       { "called": "02074351359", "duration": "00:23:03", "cost": 2.13 },       { "called": "02074351359", "duration": "00:23:03", "cost": 2.13 }     ],     "total": 59.64   },   "store": {     "rentals": [       { "title": "50 shades of grey", "cost": 4.99 }     ],     "purchases": [       { "title": "that's said", "cost": 9.99 },       { "title": "broke mountain", "cost": 9.99 }     ],     "total": 24.97   } } 

example output:

https://jsfiddle.net/un5ex8y1/1/

assuming want display each key, each value, , each array element in separate row,

def flatten_breakify(val)   case val   when hash     val.map { |k, v| "#{k}<br>#{flatten_breakify(v)}" }.join('<br>')   when array     val.map(&method(:flatten_breakify)).join('<br>')   else     val   end end 

another, more elegant approach:

def flatten_all(val)   case val   when hash     val.flat_map { |k, v| [k, *flatten_all(v)] }   when array     val.flat_map(&method(:flatten_all))   else     val   end end 

then can put in template

<%= flatten_all(data).join('<br>') %> 

in order not mix html controllers.

edit: see have added indent in output, has not been mentioned elsewhere. i'd recommend use <ul> instead of plain <br> then, achieve proper nesting, , solve indent using css. not able use second approach, since has more structure now. first piece of code, since involves html, should not in controller, in helper (that's helpers for, generating html data).


Comments

Popular posts from this blog

angularjs - ADAL JS Angular- WebAPI add a new role claim to the token -

php - CakePHP HttpSockets send array of paramms -

node.js - Using Node without global install -