flchp 关注 2023-08-08 112 31 23 22
父子树形结构是一个比较常见的结构,比如:电商平台商品的多级分类(一级分类,二级分类,三级分类),公司的多级组织(集团公司、省公司、市公司、县公司)等。
针对这种结构的设计,ruby中有非常好用gem: "ancestry" ,下面介绍一下这个gem的基本用法。
1 | + gem 'ancestry'
|
($代表在命令行执行)
执行$ bundle install,重启rails s
给需要父子树形结构的model如:category添加ancestry字段。
执行$ rails g migration add_ancestry_to_categories ancestry:string:index;执行:$ rake db:migrate
1 | + has_ancestry
|
创建子节点:
@category.children.create
查询子节点:
@category.children
查询自己及以下的所有节点:
@category.subtree
查询父节点:
@category.parent
查询当前节点的层级(顶级节点为0,其子类为1,依此类推):
@category.depth
查询某个层级的所有节点比如第二层的所有节点:
Category.at_depth(1)
其他scope方法:
before_depth(depth) Return nodes that are less deep than depth (node.depth < depth)
to_depth(depth) Return nodes up to a certain depth (node.depth <= depth)
at_depth(depth) Return nodes that are at depth (node.depth == depth)
from_depth(depth) Return nodes starting from a certain depth (node.depth >= depth)
after_depth(depth) Return nodes that are deeper than depth (node.depth > depth)
执行$ rails g migration add_ancestry_depth_and_children_count_to_categories ancestry_depth:integer:default[0] children_count:integer,生产迁移文件后执行$ rake db:migrate
1 2 | - has_ancestry + has_ancestry cache_depth: true, touch: true, counter_cache: true |
执行$ rails c,进入程序控制台执行Category.rebuild_depth_cache!
注意:要使用会触发回调的增删改查方法,才会正确维护counter_cache的值。
delete、decrement等方法不会处罚回调,不会更新counter_cache的值。
一个常见场景:分类下有多中商品
1 2 3 4 5 | class Category < ApplicationRecord has_ancestry +has_many :products end |
查询当前分类节点:
@category = Category.find(params[:id])
查询当前分类节点下所有商品:
@products = @category.products
查询当前分类的子级分类下所有商品:
@subcategories = @category.children
@products = @subcategories.map(&:products).flatten
查询当前分类节点和子孙分类节点下的所有商品:
@categories = @category.subtree
@products = @categories.map(&:products).flatten