rails 6中的多个下拉菜单



rails是个新手,不知道如何构建动态菜单栏。数据库使用一种简单的方法来存储菜单项:

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中这样做时,我使用了一个循环,它导致了许多数据库调用;一个用于按位置顺序获取所有父项(因为管理员可以更改父项在菜单上的显示顺序(,然后一个用于每个父项以获取其所有子元素(也按位置顺序(。然后,我将每个结果项添加到一个以parent_id命名的数组中,并最终将数组连接起来。

$item[$parent][]='<a href…'

我知道SQL的效率很低(PHP可能也是(,但当时这并不重要。现在确实如此。

知道我如何在ruby中高效地工作吗?

让我们假设存储此菜单信息的数据库表称为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回调中填充变量。

如果性能问题与您有关,那么您应该将导航页面元素设置为部分视图,并将rails缓存应用于部分视图。

最新更新