rails/gem "ancestry"を使って多階層構造をつくる

## "ancestry"・・・　親・子・孫みたいな多階層構造のテーブルを作れるgem。

例）食べログのラーメンカテゴリ

| 親　　|      子　 |  孫　　　　　   |
|:-----------------|------------------:|:------------------:|
|        親:ラーメン　　| 子１:ラーメン |        NULL        |
|           |            子2:汁なしラーメン | 子2の孫:      油そば       |
|              |               |        子2の孫:台湾まぜそば        |
|                |                |       子2の孫:  汁なし担々麺         |
|            | 子3:つけ麺 |       NULL      |

ラーメンは３つ子要素がある。
この場合、汁なしラーメンは孫が３つある。
ラーメンとつけ麺は子のみ。

つまり、親　→　子2:”汁なしラーメン” →　孫　を作成できる。

--------------------------------------------------------------------
```ruby:Gemfile
 gem 'ancestry'
```
```
$ bundle install
$ rails g migration add_ancestry_to_table ancestry:string
```
##  マイグレーションファイル
```ruby:category.rb
class AddAncestryToCategory < ActiveRecord::Migration[5.2]
  def change
    add_column :categories, :ancestry, :string
    add_index :categories, :ancestry
  end
end
```
```
$ rake db:migrate
```

##　Model
```ruby:category.rb
class Category < ApplicationRecord
  has_many :products_categories
  has_many :products, through: :products_categories
  has_ancestry
end
```
## データを入れる
seeds.rb　に記述するとデータを流入できます。
まずは、categoriesにデータを格納する。

```ruby:db/seeds.rb
categories = [{layer1:"レディース",layer1_chaild:[
                  {layer2:"トップス",layer2_chaild:["Tシャツ/カットソー(半袖/袖なし)","Tシャツ/カットソー(七分/長袖)","シャツ/ブラウス(半袖/袖なし)","シャツ/ブラウス(七分/長袖)","ポロシャツ","キャミソール","タンクトップ","ホルターネック","ニット/セーター","チュニック","カーディガン/ボレロ)","アンサンブル","ベスト/ジレ","パーカー","トレーナー/スウェット","ベアトップ/チューブトップ","ジャージ","その他"]},
                  {layer2:"ジャケット/アウター",layer2_chaild:["テーラードジャケット","テーラードジャケット","ノーカラージャケット","Gジャン/デニムジャケット","レザージャケット","ダウンジャケット","ライダースジャケット","ミリタリージャケット","ダウンベスト","ジャンパー/ブルゾン","ポンチョ","ロングコート","トレンチコート","ダッフルコート","ピーコート","チェスターコート","モッズコート","スタジャン","毛皮/ファーコート","スプリングコート","スカジャン","その他</option></select>ノーカラージャケット","Gジャン/デニムジャケット","レザージャケット","ダウンジャケット","ライダースジャケット","ミリタリージャケット","ダウンベスト","ジャンパー/ブルゾン","ポンチョ","ロングコート","トレンチコート","ダッフルコート","ピーコート","チェスターコート","モッズコート","スタジャン","毛皮/ファーコート","スプリングコート","スカジャン","その他"]},
                  {layer2:"パンツ",layer2_chaild:["デニム/ジーンズ","ショートパンツ","カジュアルパンツ","ハーフパンツ","チノパン","ワークパンツ/カーゴパンツ","クロップドパンツ","サロペット/オーバーオール","オールインワン","サルエルパンツ","ガウチョパンツ","その他"]},
                  ]},
             {layer1:"インテリア・住まい・小物",layer1_chaild:[
                  {layer2:"キッチン/食器",layer2_chaild:["食器","調理器具","収納/キッチン雑貨","弁当用品","カトラリー(スプーン等)","テーブル用品","容器","エプロン","アルコールグッズ","浄水機","その他"]},
                  {layer2:"ベッド/マットレス",layer2_chaild:["セミシングルベッド","シングルベッド","セミダブルベッド","ダブルベッド","ワイドダブルベッド","クイーンベッド","キングベッド","脚付きマットレスベッド","マットレス","すのこベッド","ロフトベッド/システムベッド","簡易ベッド/折りたたみベッド","収納付き","その他"]},
                  ]},
             {layer1:"本・音楽・ゲーム",layer1_chaild:[
                  {layer2:"本",layer2_chaild:["文学/小説","人文/社会","ノンフィクション/教養","地図/旅行ガイド","ビジネス/経済","健康/医学","コンピュータ/IT","趣味/スポーツ/実用","住まい/暮らし/子育て","アート/エンタメ","洋書","絵本","参考書","その他"]},
                  {layer2:"漫画",layer2_chaild:["全巻セット","少年漫画","少女漫画","青年漫画","女性漫画","同人誌","その他"]},
                  {layer2:"雑誌",layer2_chaild:["アート/エンタメ/ホビー","ファッション","ニュース/総合","趣味/スポーツ","その他"]},
                  {layer2:"CD",layer2_chaild:["邦楽","洋楽","アニメ","クラシック","K-POP/アジア","キッズ/ファミリー","その他"]},
                  ]},
                ]

```
親要素がlayer1

```
{layer1:"親"

```
```
layer1_chaild:[{layer2:"子要素"                  
```
```
layer2_chaild:["孫１","孫２","孫３", ...]
```
##categories保存する。
```ruby:db/seeds.rb
categories.each do |category|
  @layer1 = Category.create(layer:"#{category[:layer1]}")  #・・・親を保存
    category[:layer1_chaild].each do |layer1_chaild|
      @layer2 = @layer1.children.create(layer:layer1_chaild[:layer2])  #・・・子を保存
        layer1_chaild[:layer2_chaild].each do |layer2_chaild|
          @layer2.children.create(layer:layer2_chaild)    #・・・孫を保存
          end
      end
    end
```
##完成！
```ruby:db/seeds.rb
categories = [{layer1:"レディース",layer1_chaild:[
                  {layer2:"トップス",layer2_chaild:["Tシャツ/カットソー(半袖/袖なし)","Tシャツ/カットソー(七分/長袖)","シャツ/ブラウス(半袖/袖なし)","シャツ/ブラウス(七分/長袖)","ポロシャツ","キャミソール","タンクトップ","ホルターネック","ニット/セーター","チュニック","カーディガン/ボレロ)","アンサンブル","ベスト/ジレ","パーカー","トレーナー/スウェット","ベアトップ/チューブトップ","ジャージ","その他"]},
                  {layer2:"ジャケット/アウター",layer2_chaild:["テーラードジャケット","テーラードジャケット","ノーカラージャケット","Gジャン/デニムジャケット","レザージャケット","ダウンジャケット","ライダースジャケット","ミリタリージャケット","ダウンベスト","ジャンパー/ブルゾン","ポンチョ","ロングコート","トレンチコート","ダッフルコート","ピーコート","チェスターコート","モッズコート","スタジャン","毛皮/ファーコート","スプリングコート","スカジャン","その他</option></select>ノーカラージャケット","Gジャン/デニムジャケット","レザージャケット","ダウンジャケット","ライダースジャケット","ミリタリージャケット","ダウンベスト","ジャンパー/ブルゾン","ポンチョ","ロングコート","トレンチコート","ダッフルコート","ピーコート","チェスターコート","モッズコート","スタジャン","毛皮/ファーコート","スプリングコート","スカジャン","その他"]},
                  {layer2:"パンツ",layer2_chaild:["デニム/ジーンズ","ショートパンツ","カジュアルパンツ","ハーフパンツ","チノパン","ワークパンツ/カーゴパンツ","クロップドパンツ","サロペット/オーバーオール","オールインワン","サルエルパンツ","ガウチョパンツ","その他"]},
                  ]},
             {layer1:"インテリア・住まい・小物",layer1_chaild:[
                  {layer2:"キッチン/食器",layer2_chaild:["食器","調理器具","収納/キッチン雑貨","弁当用品","カトラリー(スプーン等)","テーブル用品","容器","エプロン","アルコールグッズ","浄水機","その他"]},
                  {layer2:"ベッド/マットレス",layer2_chaild:["セミシングルベッド","シングルベッド","セミダブルベッド","ダブルベッド","ワイドダブルベッド","クイーンベッド","キングベッド","脚付きマットレスベッド","マットレス","すのこベッド","ロフトベッド/システムベッド","簡易ベッド/折りたたみベッド","収納付き","その他"]},
                  ]},
             {layer1:"本・音楽・ゲーム",layer1_chaild:[
                  {layer2:"本",layer2_chaild:["文学/小説","人文/社会","ノンフィクション/教養","地図/旅行ガイド","ビジネス/経済","健康/医学","コンピュータ/IT","趣味/スポーツ/実用","住まい/暮らし/子育て","アート/エンタメ","洋書","絵本","参考書","その他"]},
                  {layer2:"漫画",layer2_chaild:["全巻セット","少年漫画","少女漫画","青年漫画","女性漫画","同人誌","その他"]},
                  {layer2:"雑誌",layer2_chaild:["アート/エンタメ/ホビー","ファッション","ニュース/総合","趣味/スポーツ","その他"]},
                  {layer2:"CD",layer2_chaild:["邦楽","洋楽","アニメ","クラシック","K-POP/アジア","キッズ/ファミリー","その他"]},
                  ]},
                ]
categories.each do |category|
  @layer1 = Category.create(layer:"#{category[:layer1]}")  #・・・親を保存
    category[:layer1_chaild].each do |layer1_chaild|
      @layer2 = @layer1.children.create(layer:layer1_chaild[:layer2])  #・・・子を保存
        layer1_chaild[:layer2_chaild].each do |layer2_chaild|
          @layer2.children.create(layer:layer2_chaild)    #・・・孫を保存
          end
      end
    end
```
## 終わったら下記を打って、tableにデータがあったら成功！
```
$ rake db:seed
```

## ちなみに１
孫要素がない時には一応　"layer2_chaild:[""]"と書かないと私の場合うまくいいかなかった。

## ちなみに２
やっぱり、めんどくさい！孫が多ければそりゃめんどくさいです。
いい方法が思いつかなかったので教えて欲しい！
ちなみに、私は下記のように検証ツールを加工しながら作りました。
この方法も最前ではないです。めんどくさかったので。
[ancestry'使用時,seedsに多階層カテゴリを書くのめんどくさいから、一気に置換してみる](https://qiita.com/yajiy/items/c03242e397c865f37159
)