2015-06-01 2 views
0

У меня есть некоторые хэши, которые я хочу повторить, и некоторые из них имеют вложенные хэши, которые могут идти на 3-4 уровня, Я использую оператор if на данный момент, чтобы проверить, является ли это значение хэш, а затем повторить его снова, но я просто повторяю код здесь.Вложенные хэши и повторное использование метода

Есть ли способ СУХОЙ, чтобы сделать это, используя метод?

Также я хочу, чтобы конечный результат заканчивался в таблице, что лучший способ сделать это? Вот почему у меня были несколько операторов if, поэтому я мог добавлять отдельные теги.

Пример метода:

<% def hashTest(key, value) %> 
    <% if value.is_a?(Hash) %> 
     <%= key %> 
      <% value.each do |key, value| %> 
       <%= key %> 
       <%= value %> 
      <% end %> 
    <% else %> 
     <%= key %> 
     <%= value %> 
    <% end %> 
<% end %> 

и это беспорядок если заявления у меня ...

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

Пример ввода:

{ 
    "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 what she said", "cost": 9.99 }, 
     { "title": "Broke back mountain", "cost": 9.99 } 
    ], 
    "total": 24.97 
    } 
} 

Пример вывода:

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

+2

Пожалуйста, отредактируйте в своем ожидаемом выходе для некоторого ввода образца. Мы могли бы вывести его из вашего беспорядка if-операторов, но мы бы предпочли не делать этого. Кроме того, напрямую не связан с вашим вопросом, но вы злоупотребляете ERb. У вас не должно быть такого кода в ваших шаблонах. Особенно это не определения методов. Вся цель шаблонов состоит в том, чтобы отделить код от разметки (см. MVC и разделение проблем). – Amadan

+0

Ну вот почему мне нужен метод, поэтому я могу поставить его в контроллер и покончить с беспорядком. – Longshanks

+0

Я понимаю беспорядок во втором фрагменте; это то, что вы хотите покончить с этим. Это первый фрагмент, против которого я возражаю, что явно находится в поле зрения, а не в контроллере. – Amadan

ответ

1

Предполагая, что вы хотите отобразить каждый ключ, каждое значение, и каждый элемент массива в отдельной строке,

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 

Другой, более элегантный подход:

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 

, то вы можете положить в ваш шаблон

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

, чтобы не смешивать HTML в контроллерах.

EDIT: Я вижу, что вы добавили отступ в своем выходе, о котором не упоминалось нигде. Я бы порекомендовал вам использовать <ul> вместо простого <br>, чтобы достичь правильной вложенности и разрешить отступ с помощью CSS. Вы не сможете использовать второй подход, так как теперь он имеет большую структуру. Первый фрагмент кода, поскольку он включает HTML, не должен находиться в контроллере, а в помощнике (для этого используются помощники, для генерации HTML из данных).

+0

Это не сработало, оно повторяется несколько раз, а форматирование ошибочно. В идеале я хотел бы, чтобы он выводился в таблицу. – Longshanks

+0

Данные могут быть повторены только в том случае, если они повторяются в структуре данных.И форматирование точно так, как вы указали в своем первом сообщении. Именно поэтому я попросил несколько раз предоставить пример вывода в вашем вопросе - не «концептуальную» версию, а HTML, которую вы ожидаете получить. Я понятия не имею, как вы можете представить это в таблицу (не говоря уже о том, что ни одна версия вашего вопроса до сих пор не упоминала таблицу вообще). Кроме того, 'nestedHashName' не появляется нигде в ваших данных. – Amadan

+0

Извиняюсь, я не ожидал, что ситуация станет более сложной, если добавить структуру к нескольким итерациям. – Longshanks