#ancestryとは
AncestryはRuby on RailsのActiveRecordモデルのレコードをツリー構造(階層)として編成することを可能にするGemのことです。
親・子・孫等の、すべてのツリー構造の関係の編成を簡単に出来ます。
##使い方
※親子孫のツリー構造を作成するとします。
1.Gemfaileに以下を記述する。
gem 'ancestry'
忘れず実行する
$ bundle install
2.モデルを作成する
$ rails g model category name:string
忘れず実行する。
$ rails db:migrate
3.先ほど作ったcategoriesテーブルにancestryのカラムを作成する
$ rails g migration add_ancestry_to_category ancestry:string:index
忘れず実行する。
$ rails db:migrate
4.モデルにancestryを明示する
category.rb
class Category < ApplicationRecord
~省略~
has_ancestry
end
5.ancestryのメソッドを用いてデータ挿入する
Ancestryモデルを操作するには、以下のインスタンスメソッドを使用できます。
method | return value |
---|---|
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 | ノードの深さを返す |
レコードがルートの場合、他のルートレコードは兄弟と見なされます。兄弟はレコード自体を返す。
2つのノード間の関係を判別するインスタンスメソッドもあります。
method | return value |
---|---|
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つですが、親ではない |
上記の表を見本としてseeds.rbにデータを入れていく
seeds.rb
#一階層目
lady = Category.create(name: "レディース")
#二階層目
lady_1 = lady.children.create(name: "トップス")
#三階層目
lady_1.children.create([{:name=>"すべて"}, {:name=>"Tシャツ/カットソー(半袖/袖なし)"},{:name=>"Tシャツ/カットソー(七分/長袖)"}])
データを入れ終わったら、、、
$ rails db:seed
この表のようなデータが作成される。
id | name | ancestry |
---|---|---|
1 | レディース | nil |
2 | トップス | 1 |
3 | すべて | 1/2 |
4 | Tシャツ/カットソー(半袖/袖なし) | 1/2 |
5 | Tシャツ/カットソー(七分/長袖) | 1/2 |