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:
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
Post a Comment