2013-08-21 3 views
2

Я использую драгоценный камень родословной и хотел бы распечатать целые деревья в таблице. Объект, с которым я работаю, это группы, поэтому он будет выглядеть примерно так.Как вы просматриваете и печатаете многомерный массив в представлении Rails?

Group A 
|__ Group A 1 
    |__ Group A 1 A 
|__ Group A 2 
    |__ Group A 2 A 
    |__ Group A 2 B 
Group B 
Group C 
|__ Group C 1 

Как правило, я бы создать метод и называть себя внутри цикла, но это, казалось бы нарушить MVC соглашение. Как я могу отобразить объект/хэш в представлении?

Примечание. У предков есть способ преобразования группы ActiveModel в хэш, поэтому это опция, а не итерация через объект ActiveModel.

ответ

3

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

<% @groups.each do |group| %> 
    <!-- Render stuff --> 
    <% group.groups.each do |child| %> 
    <!-- Render child stuff --> 
    <% end %> 
<% end %> 

Это может быть намного проще, если вы делаете это с помощью парциальных вместо:

# view.html.erb 
<% render partial: 'group', collection: @groups, as: :group %> 

# _group.html.erb 
<!-- Render stuff --> 
<% render partial: 'first_child', collection: group.groups, as: :group %> 

Отъезд Rendering Collections раздел руководства Rails на Layouts and Rendering для некоторых больше информации.


EDIT: Если вам нужно обработать неизвестный уровень вложенности, обертоны будет работать здесь. Вы даже можете отслеживать глубину, если хотите. Скажем, вы хотите, чтобы отобразить их с помощью вложенных ul элементов:

# _group.html.erb 
<% content_tag :li, class: "depth-#{depth}" do %> 
    <!-- Any output needed for the group itself --> 
    <% unless group.group.empty? %> 
    <ul> 
     <%= render partial "group", collection: group.groups, as: :group, 
       locals: { depth: depth+1 } %> 
    </ul> 
    <% end %> 
<% end %> 

# In your view file 
<ul> 
    <% render partial "group", collection: @groups, as: :group, 
     locals: { depth: 0 } %> 
</ul> 
+0

Проблема в том, что объекты имеют неизвестную глубину. Если я использую этот метод, я получаю только два уровня вывода. Это не тот цикл, который я пытаюсь избежать, это метод саморегуляции, который, как я думаю, нарушит соглашение MVC. – etc

+0

Если все они должны быть визуализированы одинаково, вы можете использовать одинаковые частичные рекурсивно, и в этом случае нужно обрабатывать любую глубину. Обновит мой ответ, чтобы проиллюстрировать. –

+0

Мне нравится это решение. Это дает мне больше свободы над html. Получаю ли я что-либо, используя content_tag вместо более прямого ' etc

2

Создать прок. Это проблема рекурсии.

array_printer = Proc.new do |set| 
    set.map {|elem| (elem.is_a? Array) ? array_printer(elem) : "<td>#{elem}</td>" } 
end 

puts array_printer master_set 
+1

который, действительно, я не очень хорошо решил. Мне придется вернуться позже и отредактировать это. надеюсь, что это помогает в то же время –

1

Я просто написать помощник, чтобы сделать это.

def render_tree(groups) 
    content_tag(:ul) do 
    groups.map do |group| 
     content_tag(:li) do 
     content_tag(:div, group.name, class: "groupname") + 
     render_tree(group.children) 
     end 
    end.join 
    end 
end 

Затем на ваш взгляд:

<%= render_tree @your_tree %> 

Стиль, как хотелось бы.

+0

Я пытаюсь решить это решение. Существует ли синтаксическая проблема в предоставленном коде? Отсутствует} или слишком много концов? Прошу прощения за рудиментарный запрос - я новичок в рубине. – etc

+0

Возможно, я не испытал это. Я не соответствовал {с концом; Я исправлю это. –

+0

Я получаю следующее сообщение об ошибке: undefined method 'join 'for"

    ": ActiveSupport :: SafeBuffer Любые предложения? (Еще раз спасибо, btw) – etc

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