Help us understand the problem. What is going on with this article?

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

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

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

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

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

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


Gemfile
 gem 'ancestry'
$ bundle install
$ rails g migration add_ancestry_to_table ancestry:string

マイグレーションファイル

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

category.rb
class Category < ApplicationRecord
  has_many :products_categories
  has_many :products, through: :products_categories
  has_ancestry
end

データを入れる

seeds.rb に記述するとデータを流入できます。
まずは、categoriesにデータを格納する。

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:["孫1","孫2","孫3", ...]

categories保存する。

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

完成!

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

ちなみに1

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

ちなみに2

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

yajiy
究極の面倒くさがりなので、楽にできる方法を常に探して生きてます。 同じ結果なら楽な方がいいと思うので。 見つけたらシェアします。(めんどくさいから、見つけてからタイムラグあるけど。)
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした