mysql - 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 缓存应用于部分视图。
推荐阅读
- python - Function to input key and value from dictionary, extract line of data from given input location (csv file), and output the line of data
- node.js - (JWT) RSA Encryption/decryption issue
- javascript - 在 websocket api javascript 中使用回调函数
- google-apps-script - 如何使用 onclick=google.script.run.taxBill(this.value) 在循环的 Htmlservice 表中获取列值?
- c# - 如何在 Visual Studio 中阻止磁贴自动缩放
- javascript - 为什么这个 javascript 在 thymeleaf 的内联 javascript 标记中不起作用?语法有问题吗?
- python - 基于前一行的唯一行数 - Pandas
- javascript - 在 componentDidMount 之后根据 React State 设置输入值?
- reactjs - 将初始文件加载到材质 ui dropzone
- python-3.6 - 在 Python 中读取文件时出现“无后端错误”