Ruby on rails 如何在RubyonRails中输出分层列表
当一个页面可以是另一个页面的父页面时,我有一个页面的层次结构。页面存储在具有以下结构的DB表中:Ruby on rails 如何在RubyonRails中输出分层列表,ruby-on-rails,ruby,hierarchy,Ruby On Rails,Ruby,Hierarchy,当一个页面可以是另一个页面的父页面时,我有一个页面的层次结构。页面存储在具有以下结构的DB表中: page.id page.name page.parent\u id 现在我需要输出一个分层列表,如下所示: A页 B页 C页 D页 等 E页 此外,对多个级别也没有限制 在RoR中实现这一目标的最佳方法是什么?提前谢谢。嗨,我会用一些宝石来做这个 i、 e 嗨,我会用一些宝石来做这件事 i、 e 假设代码,未验证 class Page < ActiveReco
- page.id
- page.name
- page.parent\u id
- A页
- B页
- C页
- D页
- 等
- E页
在RoR中实现这一目标的最佳方法是什么?提前谢谢。嗨,我会用一些宝石来做这个 i、 e
嗨,我会用一些宝石来做这件事 i、 e
假设代码,未验证
class Page < ActiveRecord::Base
has_many :children, class_name: 'Page', foreign_key: 'parent_id'
belongs_to :parent, class_name: 'Page'
end
# Helper
def tree_list(collection)
content_tag :ul do
collection.each do |item|
if item.children.blank?
content_tag :li do
item.name
end
else
tree_list(item)
end
end
end
end
# View
tree_list(Page.all)
class页面
基本思想是
tree\u list
方法将生成一个递归列表,直到某个页面没有子页面。假设代码,未验证
class Page < ActiveRecord::Base
has_many :children, class_name: 'Page', foreign_key: 'parent_id'
belongs_to :parent, class_name: 'Page'
end
# Helper
def tree_list(collection)
content_tag :ul do
collection.each do |item|
if item.children.blank?
content_tag :li do
item.name
end
else
tree_list(item)
end
end
end
end
# View
tree_list(Page.all)
class页面
基本思想是
tree\u list
方法将创建一个递归列表,直到某个页面没有子页面为止。正如另一个用户所建议的,您可以使用estority
gem,但它需要更改您的数据库。如果不能这样做,则应创建一个有向无环图,并为每个节点设置深度
class Page < ActiveRecord::Base
attr_accessor :depth
def children
@children ||= []
end
end
# Loading required pages in single query, add predicate if needed
pages = Page.includes(:parent).all
# Setting up a hash table to find pages in constant time
page_index = pages.reduce({}){|acc, page| acc[page.id] = page}
# Setting up children
pages.each do |page|
if page.parent_id
page_index[page.parent_id].children << page
end
end
# Basic depth-first search routine
def dfs(page, visited, depth)
page.depth = depth
visited[page.id] = true
page.children.select{|p| visited[p] == nil}.each{|p| dfs(p, visited, depth + 1)}
end
# Performing depth-first search for each connected component
visited = {}
pages.each do |page|
if visited[page.id] == nil
dfs(page, visited, 0)
end
end
class页面 page_index[page.parent_id].children正如另一位用户所建议的,您可以使用祖先
gem,但它需要更改您的数据库。如果不能这样做,则应创建一个有向无环图,并为每个节点设置深度
class Page < ActiveRecord::Base
attr_accessor :depth
def children
@children ||= []
end
end
# Loading required pages in single query, add predicate if needed
pages = Page.includes(:parent).all
# Setting up a hash table to find pages in constant time
page_index = pages.reduce({}){|acc, page| acc[page.id] = page}
# Setting up children
pages.each do |page|
if page.parent_id
page_index[page.parent_id].children << page
end
end
# Basic depth-first search routine
def dfs(page, visited, depth)
page.depth = depth
visited[page.id] = true
page.children.select{|p| visited[p] == nil}.each{|p| dfs(p, visited, depth + 1)}
end
# Performing depth-first search for each connected component
visited = {}
pages.each do |page|
if visited[page.id] == nil
dfs(page, visited, 0)
end
end
class页面 页面索引[page.parent\u id]。儿童以下是要处理的最佳实践-
简单的桌子
Table Emp
id: Integer
name: String
parent_id: Integer
联想
app/models/emp.rb
class Emp < ApplicationRecord
has_many :subs, class_name: 'Emp', foreign_key: :parent_id
belongs_to :superior, class_name: 'Emp', foreign_key: :parent_id
end
app/models/emp.rb
类Emp
范围定义
class Emp < ApplicationRecord
----
----
scope :roots, -> { where(parent_id: nil) }
end
class Emp{where(parent_id:nil)}
结束
获取数据
def tree_data
output = []
Emp.roots.each do |emp|
output << data(emp)
end
output.to_json
end
def data(employee)
subordinates = []
unless employee.subs.blank?
employee.subs.each do |emp|
subordinates << data(emp)
end
end
{name: employee.name, subordinates: subordinates}
end
def树_数据
输出=[]
Emp.root.each do | Emp|
输出以下是要处理的最佳实践-
简单的桌子
Table Emp
id: Integer
name: String
parent_id: Integer
联想
app/models/emp.rb
class Emp < ApplicationRecord
has_many :subs, class_name: 'Emp', foreign_key: :parent_id
belongs_to :superior, class_name: 'Emp', foreign_key: :parent_id
end
app/models/emp.rb
类Emp
范围定义
class Emp < ApplicationRecord
----
----
scope :roots, -> { where(parent_id: nil) }
end
class Emp{where(parent_id:nil)}
结束
获取数据
def tree_data
output = []
Emp.roots.each do |emp|
output << data(emp)
end
output.to_json
end
def data(employee)
subordinates = []
unless employee.subs.blank?
employee.subs.each do |emp|
subordinates << data(emp)
end
end
{name: employee.name, subordinates: subordinates}
end
<代码>def树\u数据
输出=[]
Emp.root.each do | Emp|
输出谢谢,我尝试了一下,它成功了!不过有两个增强功能:1)嵌套的content_标记违反直觉。有关详细信息,请参见此链接:;2) 我稍微修改了代码:def tree_list(collection)content_tag(:ul)do collection.each do | item | concat(content_tag(:li,item.name))if!item.children.blank?concat(tree_list(item.children))end
这是一个有效的版本。虽然这种方法有效,但我很可能会坚持使用现有的gem,以避免重新发明轮子。无论如何,谢谢你的建议!这取决于用例,而不是发明轮子。如果只用一种方法就能解决我的问题,我绝对不会去买宝石。这是简单的基本原则。谢谢,我试了一下,它成功了!不过有两个增强功能:1)嵌套的content_标记违反直觉。有关详细信息,请参见此链接:;2) 我稍微修改了代码:def tree_list(collection)content_tag(:ul)do collection.each do | item | concat(content_tag(:li,item.name))if!item.children.blank?concat(tree_list(item.children))end
这是一个有效的版本。虽然这种方法有效,但我很可能会坚持使用现有的gem,以避免重新发明轮子。无论如何,谢谢你的建议!这取决于用例,而不是发明轮子。如果只使用一种方法可以解决我的问题,我肯定不会去创业板。这是简单的基本原则。谢谢你让我知道这个宝石。我是Ruby和Rails新手,不知道所有可能的选项。我会给它一个