Предположим, что таблица базы данных, в которой хранится эта информация меню, называется nav_items. Тогда соглашение Rails будет иметь модель под названием NavItem:
# app/models/nav_item.rb
class NavItem < ApplicationRecord
has_many :child_menu_items, class_name: NavItem, inverse_of: :parent_menu_item, foreign_key: :parent
belongs_to :parent_menu_item, class_name: NavItem, foreign_key: :parent, inverse_of: :child_menu_items
scope :top_level, { where("parent = ?", 0) }
end
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_action :populate_nav_vars
private
def populate_nav_vars
@nav_items = NavItem.top_level
end
end
# app/view/layouts/_nav.html
# @nav_items is defined in the controller as NavItem.top_level
# the nav structure is shown here as nested <ul> lists
# it can be rendered appropriately with css (e.g. Bootstrap)
<ul>
<%- @nav_items.each do |top_level_item| %>
<li><%= top_level_item.title %></li>
<li>
<ul>
<%- top_level_item.child_menu_items.each do |child_item| %>
<li><%= child_item.title %>
<%- end %>
</ul>
</li>
<%- end %>
</ul>
Вы действительно не должны беспокоиться о производительности, она не должна быть вообще заметна. Я предполагаю, что вам нужно меню навигации на каждой странице, поэтому удобное место для заполнения необходимых переменных находится в ApplicationController
и заполняет переменную в обратном вызове before_action.
Если вас беспокоит проблема производительности, тогда вы должны сделать элементы навигационной страницы частичным представлением и применить кеширование рельсов к частичному.