LoginSignup
2
1

More than 3 years have passed since last update.

【Rails】ancestryを用いた多階層カテゴリー機能の実装『準備編』

Last updated at Posted at 2020-06-19

開発環境

・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)

続編

多階層カテゴリー機能実装(seed編)

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1