2015-03-15 4 views
0

Я пытаюсь поэкспериментировать с блоками и как перебирать коллекции в ERB. У меня есть модели в соотношении «один ко многим» (канал и их соответствующие типы).Rails ERB итерация по массиву

контроллер

class HomePageController < ActionController 
    def index 
    @channels = Channel.all 
    end 
end 

Тогда в представлении, я перебирать все атрибуты, принадлежащих к каналу. Когда я хочу, чтобы напечатать все виды, этот код дает мне желаемый результат:

вид

<% @channels.each do |channel| %> 
    <% @types.each do |type| %> 
     <%= Type.find(type).name %> 
    <% end %> 
<% end %> 

Сначала я пытался добиться этого, используя yield ключевое слово в аккуратном однострочнике, но я не мог» t удалять что-либо в браузере, только на консоль

<% @types.each {|type| yield Type.find(type).name } %> 

Есть ли эквивалентная однострочная линия?

+3

не <% = @ types.each {| type | Type.find (type) .name}%> work? – srecnig

+0

- это @types массив целых идентификаторов? –

+0

'<% =' выводит содержимое, а '<%' просто выполняет его. См. Ответ от @srecnig. – mudasobwa

ответ

3

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

# controller 
@channels = Channel.includes(:types) # avoiding n+1 queries 

# view 
<% @channels.each do |channel| %> 
    # some channel info output 
    <% channel.types.each do |type| %> 
    <%= type.name %> 
    <% end %> # types loop 
<% end %> # channel loop 

Как уже упоминалось @Almaron, вы могли бы оказать частичное упрощение для более, если у вас есть частичный называется _type.html.erb вы можете позвонить непосредственно оказывать

# view 
<%= render channel.types %> 

Rails сделает все итерации и рендеринг.

+0

На самом деле type_ids является отношением has_many, для каждого родительского типа я могу иметь массив этих идентификаторов типов. Итак, как бы я это сделал в контроллере? – Rabiees

+0

'type_ids' - это просто виртуальное имя, которое я создал, я просто использовал его, потому что' @ types' должен быть массивом типов, а не массивом ids, вы можете называть его любым, что хотите, 'ids' или что-либо. –

+0

Я имел в виду: как следует относиться к вложенному типу (отношения «один ко многим») в контексте передачи данных между контроллером и представлением. Например, канал имеет много типов. Итак, чтобы напечатать все каналы и их соответствующие типы, нужно ли фактически создать структуру данных в виде карты в контроллере, а затем получить доступ к ней в представлении? Или нужно создать вспомогательную функцию, передать идентификаторы и вызвать ее из представления?У меня нет проблем с решением этого, но я хочу сделать это Rails. – Rabiees

1

Прежде всего, этот вид кода не относится к виду. Не обрабатывайте базу данных с точки зрения (в вашем случае Type.find()). Переместите его к контроллеру, где он принадлежит.

Второе, что нужно отметить, - это разница между <%= и <% тегами. Первый выводит возвращаемый результат, а второй - нет. Проблема с .each заключается в том, что он возвращает объект, на котором он был использован, поэтому в вашем случае, если вы просто поедете <%= @types.each {|type| Type.find(type).name } %>, вы получите распечатанный массив @types.

Если вы хотите упростить этот код, вы можете использовать вспомогательный метод для итерации и частичный для рендеринга каждого элемента. Таким образом, вы получите что-то вроде этого <% collection_iterate @items, 'item_partial' %>

Смежные вопросы