開発環境
・Ruby: 2.5.7
・Rails: 5.2.4
・Vagrant: 2.2.7
・VirtualBox: 6.1
・OS: macOS Catalina
前提
下記実装済み。
実装
1.Gemを導入
Gemfile
# 追記
gem 'ancestry'
ターミナル
$ bundle
2.カラムを追加
データ量がかなり多くなるのでindexを張ります。
ターミナル
$ rails g migration AddAncestryToCategory ancestry:string:index
ターミナル
$ 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.モデルを編集
category.rb
# 追記
has_ancestry
has_ancestry
➡︎ ancestryを使える様になる。
メソッド一覧
| メソッド名 | 返り値 |
|---|---|
| parent | 親レコードを取得 |
| parent_id | 親レコードのIDを取得 |
| root | レコードのルートを取得 |
| root_id | レコードのルートIDを取得 |
| root?is_root? | レコードがルートであれば、trueを返す |
| ancestors | ルートで始まり、親で終わる、レコードの祖先を返す |
| ancestors? | レコードに祖先(ルートノードではない)がある場合はtrueを返す |
| ancestor_ids | レコードの祖先のIDを返す |
| path | ルートで始まり、自己で終わる、レコードのパスを返す |
| path_ids | ルートIDで始まり、 自己のIDで終わるパスのIDをリストで返す |
| children | 子レコードを取得 |
| child_ids | 子レコードのIDを取得 |
| has_parent?ancestors? | レコードが親を持っていれば、trueを返す |
| has_children?children? | レコードが子を持っていれば、trueを返す |
| is_childless?childless? | レコードが子を持っていなければ、trueを返す |
| siblings | 兄弟レコード(同じ階層のレコード)を返す |
| sibling_ids | 兄弟レコード(同じ階層のレコード)のIDを返す |
| has_siblings?siblings? | レコードの親に複数の子がある場合はtrueを返す |
| is_only_child?only_child? | レコードが親の唯一の子である場合はtrueを返す |
| descendants | 子レコード、孫レコード、曽孫レコード... を返す |
| descendant_ids | 子レコード、孫レコード、曽孫レコード... のIDを返す |
| indirects | 孫レコード以下を返す |
| indirect_ids | 孫レコード以下のIDを返す |
| subtree | 子孫と自己のモデルを返す |
| subtree_ids | レコードのサブツリーのIDをリストで返す |
| depth | ノードの深さを返す |
| parent_of?(node) | このレコードを(node)の親にする |
| root_of?(node) | このレコードを(node)のルートにする |
| ancestor_of?(node) | (node)の祖先にはこのレコードが含まれる |
| child_of?(node) | (node)はレコードの親 |
| descendant_of?(node) | (node)はこのレコードの祖先の1つ |
| indirect_of?(node) | (node)はこのレコードの祖先の1つですが、親ではない |
階層構造
親:ビジネス
子:経済
孫:日本経済、国際経済
本のカテゴリーに上記の様な親子関係を持たせたい場合は、以下の様にデータを作成します。
business = Category.create(name: 'ビジネス')
business_economy = business.children.create(name: '経済')
business_economy.children.create([{ name: '日本経済' }, { name: '国際経済' }])
カラム構造
| id | name | ancestry |
|---|---|---|
| 1 | ビジネス | nil |
| 2 | 経済 | 1(親のid) |
| 3 | 日本経済 | 1/2(親のid/子のid) |
| 4 | 国際経済 | 1/2(親のid/子のid) |