Несколько выпадающих меню в рельсах 6 - PullRequest
0 голосов
/ 10 июля 2020

Совершенно новичок в рельсах и не могу понять, как создать динамическую c строку меню. База данных использует простой метод для хранения пунктов меню:

id | title   | url             | parent | position
--------------------------------------------------------------------
1    Books     /books            0        1 (first link on menu bar)
2    Fiction   /books/fiction    1        1 (first link under Books menu)
3    CDs       /cd               0        2 (second link on menu bar)
4    Fantasy   /books/fantasy    1
5    Singles   /cd/single        2
6    Albums    /cd/album         2

Мне нужно получить все записи в этой таблице и отобразить их в соответствии с их родительскими элементами. Все элементы с родительским 0 будут отображаться в строке меню. Когда пользователь наводит курсор на какой-либо родительский элемент, все его дочерние элементы перечислены под ним.

Когда я делал это в PHP, я использовал al oop, что приводило к множеству вызовов базы данных; Один для получения всех родительских элементов в порядке расположения (поскольку администратор может изменить порядок, в котором родительские элементы отображаются в меню), а затем по одному для каждого родительского элемента, чтобы получить все его дочерние элементы (также в порядке расположения). Затем я добавил каждый полученный элемент в массив, названный в честь parent_id, и, наконец, объединил массивы.

$ item [$ parent] [] = '

1 Ответ

1 голос
/ 10 июля 2020

Предположим, что таблица базы данных, в которой хранится эта информация меню, называется 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.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...