"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に多階層カテゴリを書くのめんどくさいから、一気に置換してみる