Цикл в шаблонах

Мой шаблон выглядит так:

  <h2>Oracle</h2>

  <% @q_oracle.each do |q| %>
    <%= link_to(q.title + ' (' + q.answer_count.to_s + ') ' + q.question_id.to_s, 'http://stackoverflow.com/' + q.question_answers_url) %>  </br>

  <% end %>


  <h2>Ruby and Rails</h2>

  <% @q_ruby.each do |q| %>
    <%= link_to(q.title + ' (' + q.answer_count.to_s + ') ' + q.question_id.to_s, 'http://stackoverflow.com/' + q.question_answers_url) %>  </br>

  <% end %>

Итак, temlate состоит из статических заголовков (h2) и циклически проходит через массив. Я ищу способ избежать копирования кода в моем шаблоне. Что-то вроде:

@hash = { 'Oracle' => @q_oracle, 'Ruby and Rails' => @q_ruby }

@hash.each { |@t, @a|

  <h2>@t</h2>

  <% @a.each do |q| %>
    <%= link_to(q.title + ' (' + q.answer_count.to_s + ') ' + q.question_id.to_s, 'http://stackoverflow.com/' + q.question_answers_url) %>  </br>

  <% end %>
}

Возможно ли это?

Ответы

Ответ 1

Да, вы можете это сделать.

Решение Ruby 1.9

В Ruby 1.8 это решение может использоваться, когда порядок титров не имеет значения. В Ruby 1,9 названия появятся для того, чтобы они были вставлены в хэш.

Просто поместите эту переменную в действие вашего контроллера:

@hash = { 'Oracle' => @q_oracle, 'Ruby and Rails' => @q_ruby }

И получить доступ к этой переменной из вашего представления:

<% @hash.each do |t, a| %>
  <h2><%= t %></h2>
  <% a.each do |q| %>
    <%= link_to(q.title + ' (' + q.answer_count.to_s + ') ' + q.question_id.to_s, 'http://stackoverflow.com/' + q.question_answers_url) %>  </br>
  <% end %>
<% end %>

Ruby 1.8 с отсортированными клавишами

Этот метод сортирует ключи, чтобы они отображались в алфавитном порядке.

<% @hash.keys.sort.each do |t| %>
  <h2><%= t %></h2>
  <% @hash[t].each do |q| %>
    <%= link_to(q.title + ' (' + q.answer_count.to_s + ') ' + q.question_id.to_s, 'http://stackoverflow.com/' + q.question_answers_url) %>  </br>
  <% end %>
<% end %>

Ruby 1.8 с массивами

Этот метод будет вести себя как Ruby 1.9 в любой рубиновой версии - появятся заголовки, чтобы они были добавлены.

Переменная @hash должна быть инициализирована как:

@hash = [ ['Oracle', @q_oracle], ['Ruby and Rails',@q_ruby] ]

Просмотр должен быть обновлен до:

<% @hash.each do |title_with_questions| %>
  <h2><%= title_with_questions[0] %></h2>
  <% title_with_questions[1].each do |q| %>
    <%= link_to(q.title + ' (' + q.answer_count.to_s + ') ' + q.question_id.to_s, 'http://stackoverflow.com/' + q.question_answers_url) %>  </br>
  <% end %>
<% end %>

Ответ 2

Это, конечно, возможно, но он ставит очень много логики Ruby в представлении, которое довольно вонючее. Я думаю, что было бы лучше исключить дублирование части тела списка вопросов в частичное.

Главное представление...

<h2>Oracle</h2>

<%= render :partial => 'question_list', :locals => {:questions => @q_oracle} %>


<h2>Ruby and Rails</h2>

<%= render :partial => 'question_list', :locals => {:questions => @q_ruby} %>

Частичный: _question_list.html.erb...

  <% questions.each do |q| %>
    <%= link_to(q.title + ' (' + q.answer_count.to_s + ') ' + q.question_id.to_s, 'http://stackoverflow.com/' + q.question_answers_url) %>  </br>

  <% end %>

Этот подход более читабельен, чем вложенный цикл, а также более гибкий с точки зрения настройки структуры страницы. Например: что делать, если вы хотите применить различные стили к каждому списку или поместить разделитель между ними?

Ответ 3

Но, конечно, можно выполнить цикл Hash.

<% @hash.each do |title, var|
  <h2><%= title %></h2>
  ... so forth ...
<% end %>