ancestry[gem]を使った多階層カテゴリー管理

# 概要
'ancestry'は、階層のあるカテゴリーなどツリー構造を管理するgemです。

今回は以下のような三つの階層に枝分かれしたデータを扱います。

○中学一年
　・数量
　　正負の数 / 文字式　/ 資料の活用
　・方程式・関数
　　比例・反比例 / 一次方程式
　・図形
　　平面図形 / 立体図形
○中学二年
　・数量
　　式の計算 / 確率
　・方程式・関数
　　連立方程式 / 一次関数
　・図形
　　平行と合同 / 証明 / 図形の性質
○中学三年
　・数量
　　式の計算 / 平方根 / 標本調査
　・方程式・関数
　　二次方程式 / 二次関数
　・図形
　　三平方の定理 / 図形の性質 / 円周角

# 準備
### 1. gemファイルに追加
```Gemfile:Gemfile
gem 'ancestry'
```

### 2. Categoriesテーブルの作成
```:ターミナル
$ rails g model category
```

```ruby:migration_file
class CreateCategories < ActiveRecord::Migration[5.2]
  def change
    create_table :categories do |t|
      t.string :name
      t.string :ancestry
      t.timestamps
    end
  end
end
```
ancestryカラムにデータの階層を示す値が入ります

```:ターミナル
$ rake db:migrate
```

このようなテーブルになります。

|id|name|ancestry|
|:---|:---|:--|

### 3. Catagoryモデルにhas_ancestryを追加
```ruby:category.rb
class Category < ApplicationRecord
  has_ancestry
end
```
githubによると様々なオプションがあります。

### 4. データをDBに登録
```ruby:seeds.rb
grade_one = Category.create(name: "中学一年")

one_quantity = grade_one.children.create(name: "数量")
one_function = grade_one.children.create(name: "方程式・関数")
one_shape = grade_one.children.create(name: "図形")

one_quantity.children.create([{name: "正負の数"}, {name: "文字式"}, {name: "資料"}])
one_function.children.create([{name: "比例・反比例"}, {name: "一次方程式"}])
one_shape.children.create([{name: "平面図形"}, {name: "立体図形"}])


grade_two = Category.create(name: "中学二年")

two_quantity = grade_two.children.create(name: "数量")
two_function = grade_two.children.create(name: "方程式・関数")
two_shape = grade_two.children.create(name: "図形")

two_quantity.children.create([{name: "式の計算"}, {name: "確率"}])
two_function.children.create([{name: "連立方程式"}, {name: "一次関数"}])
two_shape.children.create([{name: "平行と合同"}, {name: "証明"}, {name: "図形の性質"}])


grade_three = Category.create(name: "中学三年")

three_quantity = grade_three.children.create(name: "数量")
three_function = grade_three.children.create(name: "方程式・関数")
three_shape = grade_three.children.create(name: "図形")

three_quantity.children.create([{name: "式の計算"}, {name: "平方根"}, {name: "標本調査"}])
three_function.children.create([{name: "二次方程式"}, {name: "二次関数"}])
three_shape.children.create([{name: "三平方の定理"}, {name: "図形の性質"}, {name: "円周角"}])
```
ancestry(gem)とモデルにhas_ancestryを加えたことにより、childrenメソッドが使えるようになりました。

```:ターミナル
$ rake db:seed
```

やっと、以下のようなテーブルができました。
<img src="https://i.gyazo.com/432cafa7c7538ab136ed2d6b99a28c22.png" width=40%>

ancestryがNULLなレコードが一番上の階層、ひとつの数値が書かれているレコードが第二階層、/でわけられたふたつの数値があるものが最下層のデータになっています。

|id|name|ancestry|
|:--|:--|:--|
|1|中学一年|NULL|
|2|数量|1|
|5|正負の数|1/2|

親のidとancestryカラムの数値を見ると、それぞれが関連していることがわかります。

# 値の取得
いよいよ、値の取得方法をおっていきます。

まずはchildrenメソッドで、一つ下の階層の値をすべて取得します。

```:ターミナル

pry(main)> one_grade = Category.find_by(name: "中学一年")
=> #<Category:0x007fc50033ad98
 id: 1,
 name: "中学一年",
 ancestry: nil,
 
pry(main)> one_grade.children
=> [#<Category:0x007fc5003a9a40
  id: 2,
  name: "数量",
  ancestry: "1",
#<Category:0x007fc5003a96f8
  id: 3,
  name: "方程式・関数",
  ancestry: "1",
 #<Category:0x007fc5003a9540
  id: 4,
  name: "図形",
  ancestry: "1",>]
```
中学一年.children
　→　数値 / 方程式・関数 / 図形

つぎにindirectsメソッドで一つ階層をまたぎ最下層のデータをすべて取得します。

```:ターミナル
 pry(main)> one_grade.indirects

=> [#<Category:0x007fc504a8f180
  id: 5,
  name: "正負の数",
  ancestry: "1/2",
 #<Category:0x007fc504a8f040
  id: 6,
  name: "文字式",
  ancestry: "1/2",
#<Category:0x007fc504a8ef00
  id: 7,
  name: "資料",
  ancestry: "1/2",
#<Category:0x007fc504a8edc0
  id: 8,
  name: "比例・反比例",
  ancestry: "1/3",
#<Category:0x007fc504a8ec80
  id: 9,
  name: "一次方程式",
  ancestry: "1/3",
 #<Category:0x007fc504a8eb40
  id: 10,
  name: "平面図形",
  ancestry: "1/4",
 #<Category:0x007fc504a8ea00
  id: 11,
  name: "立体図形",
  ancestry: "1/4",
```
中学一年.indirects
 →　正負の数 / 文字式 / 資料の活用 / 比例・反比例 / 一次方程式 / 平面図形 / 立体図形


上の階層（親）のデータも取得していきましょう 

上の階層はparentメソッドです。

```:ターミナル
pry(main)> solid_figure = Category.find_by(name: "立体図形")
=> #<Category:0x007fc504a67090
 id: 11,
 name: "立体図形",
 ancestry: "1/4",

pry(main)> solid_figure.parent
=> #<Category:0x007fc500142040
 id: 4,
 name: "図形",
 ancestry: "1",
```

立体図形.parent
　→　図形

ふたつ上の階層の取得はメソッドがないようなのでparentを連鎖させます

```:ターミナル
pry(main)> solid_figure.parent.parent

=> #<Category:0x007fc500280c68
 id: 1,
 name: "中学一年",
 ancestry: nil,
```

立体図形.parent.parent
 →　中学一年

# まとめ　+αのメソッド

Category.root
→　中学一年 / 中学二年 / 中学三年

中学一年.children
→　数量 / 方程式・関数 / 図形

中学一年.indirects
→ 　正負の数 / 文字式 / 資料の活用 / 比例・反比例 / 一次方程式 / 平面図形 / 立体図形

立体図形.parent
→　図形

立体図形.parent.parent
 →　中学一年

中学一年.children_ids
→　2 / 3 / 4

中学一年.indirect_ids
→ 5 / 6 / 7 / 8 / 9 / 10 / 11

他にいくつかのメソッドが用意されています。
詳しくはgithubのREADMEを参照していただきたいです。

https://github.com/stefankroes/ancestry

なにか間違いがあればご指摘いただけると幸いです！