課題
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
表示できた:
補足
ERB内で直接関数宣言するのもアレなので、大きくなりそうならヘルパとパーシャルに切り出す感じで。
また同様の機能/表示を簡単に実現できそうな awesome_nested_set
と the_sortable_tree
というgemがあるとのことなので、こちらを使うほうがいいかもしれない。参考: