Rails

erbでn階層のツリーを表示する

More than 1 year has passed since last update.

課題

1:N の 自己参照関係を持ったツリー状のモデルを、n階層のツリーとしてビュー内に静的に表示したい。

たとえば、以下のようなモデル:

$ ./bin/rails g model foo name:string foo_id:integer
app/models/foo.rb
class Foo < ApplicationRecord
  has_many :children, foreign_key: :foo_id, class_name: 'Foo'
end

解決方法

ERB内に表示用の再帰関数を定義して呼び出す方法で解決した。

app/views/foo/index.html.erb
<% def disp_tree(foo) %>
  <li>
    <span><%= foo.name %></span>
    <ul>
      <% foo.children.each do |f| %>
        <% disp_tree(f) %>
      <% end %>
    </ul>
  </li>
<% end%>

<ul>
  <% disp_tree(@root) %>
</ul>

適当にデータを入れて確認してみる:

app/controllers/foo_controller.rb
class FooController < ApplicationController
  def index
   @root = Foo.create!(name: 'root')

   @root.children << Foo.create!(name: 'n1')
   @root.children << Foo.create!(name: 'n2')
   @root.children << Foo.create!(name: 'n3')

   @root.children[0].children << Foo.create!(name: 'n1-1')
   @root.children[0].children << Foo.create!(name: 'n1-2')
   @root.children[0].children << Foo.create!(name: 'n1-3')

   @root.children[1].children << Foo.create!(name: 'n2-1')
   @root.children[1].children << Foo.create!(name: 'n2-2')
   @root.children[1].children << Foo.create!(name: 'n2-3')

   @root.children[2].children << Foo.create!(name: 'n3-1')
   @root.children[2].children << Foo.create!(name: 'n3-2')
   @root.children[2].children << Foo.create!(name: 'n3-3')

   @root.children[0].children[0].children << Foo.create!(name: 'n1-1-1')
   @root.children[0].children[0].children << Foo.create!(name: 'n1-1-2')
   @root.children[0].children[0].children << Foo.create!(name: 'n1-1-3')
  end
end

表示できた:

スクリーンショット 2017-09-09 23.46.34.png

補足

ERB内で直接関数宣言するのもアレなので、大きくなりそうならヘルパとパーシャルに切り出す感じで。

また同様の機能/表示を簡単に実現できそうな awesome_nested_setthe_sortable_tree というgemがあるとのことなので、こちらを使うほうがいいかもしれない。参考: