[Ruby] [Rails] Implementation of multi-level category function using ancestry Preparation

2 minute read

Development environment

・Ruby: 2.5.7 Rails: 5.2.4 ・Vagrant: 2.2.7 ・VirtualBox: 6.1 ・OS: macOS Catalina

Premise

Implemented below.

Posting function implementationMany-to-many category function implementation

Implementation

1. Introduce Gem

Gemfile


# Addition
gem'ancestry'

terminal


$ bundle

2. Add column

Since the amount of data will be quite large, put an index.

terminal


$ rails g migration AddAncestryToCategory ancestry:string:index

terminal


$ rails db:migrate

``

schema.rb
create_table "categories", force: :cascade do |t|
  t.string "name"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
  t.string "ancestry"
  t.index ["ancestry"], name: "index_categories_on_ancestry"
end

3. Edit the model

``

category.rb
# Addition
has_ancestry

has_ancestry ➡︎ You can use ancestry.

Method list

Method name return value
parent Get parent record
parent_id Get the ID of the parent record
root Get root of record
root_id Get root ID of record
root?is_root? Returns true if the record is root
ancestors Returns record ancestors starting at root and ending at parent
ancestors? returns true if the record has an ancestor (not a root node)
ancestor_ids Returns IDs of record ancestors
path returns the path of the record, starting at the root and ending at self
path_ids Returns a list of path IDs starting with the root ID and ending with its own
children Get child records
child_ids Get IDs of child records
has_parent?ancestors? returns true if the record has parents
has_children?children? returns true if the record has children
is_childless?childless? returns true if the record has no children
siblings Returns sibling records (records in the same hierarchy)
sibling_ids Returns the IDs of sibling records (records in the same hierarchy)
has_siblings?siblings? returns true if the parent of the record has multiple children
is_only_child?only_child? returns true if the record is the only child of its parent
descendants Returns child records, grandchild records, great-grandchild records…
descendant_ids Returns the IDs of child records, grandchild records, great-grandchild records…
indirects returns sub-records below
indirect_ids Returns the IDs below the grandchild record
subtree returns models of descendants and self
subtree_ids Returns a list of record subtree IDs
depth Returns the depth of the node
parent_of?(node) Make this record the parent of (node)
root_of?(node) Make this record the root of (node)
ancestor_of?(node) (node) contains this record
child_of?(node) (node) is the parent of the record
descendant_of?(node) (node) is one of the ancestors of this record
indirect_of?(node) (node) is one of the ancestors of this record, but it is not the parent

Hierarchical structure

Parent: Business Child: Economy ** Grandchild: Japanese economy, international economy **

If you want to have the above-mentioned parent-child relationship in the category of the book, create the data as follows.

``


business = Category.create(name:'business')

business_economy = business.children.create(name:'economy')

business_economy.children.create([{ name:'Japanese economy' }, {name:'International economy' }])

Column structure

|id|name|ancestry| |—|—|—| |1|Business|nil| |2|Economy|1(parent id)| |3|Japan Economy|1/2(parent id/child id)| |4|International economy|1/2(parent id/child id)|

Sequel

Multi-level category function implementation (seed)