カテゴリ機能の実装

TECH::EXPERTで勉強し始めて19週目。

現在、最終カリキュラムであるチーム開発を行っています。

 

最終カリキュラムの課題は、「メルカリ」などを参考にして、

スクール側から与えられた仕様を備えたフリマアプリを作ることです。

 

大変なのは、初めてチーム開発をするため、gitでの管理の段取りがわからず、

masterブランチにmergeするたびにconflictが出るわ出るわの大騒動(笑)

 

開発初期にもgit関連のトラブルを私が起こしてしまい、

チームでなんとか解決を試みた(みなさん、とっても優しくて本当に感謝!!)のもあり、

だんだんgitに耐性がついてきた・・のではないかと思います。

 

現在私が担当しているのは、

[サーバーサイド]category機能の実装

というもの。

 

これはancestryというgemを使用すると、多階層のツリーが作れるらしく、

下記記事と、公式githubを参考にさせていただき、実装しました。

 

https://qiita.com/ATORA1992/items/03eb78e212080072ab9f

↓公式(英語ですが図もあり、わかりやすいです)

https://github.com/stefankroes/ancestry

 

 

 

categoriesテーブルを作る

categoriesテーブルの完成予定は下図の通りですが、

まずはnameカラムのみを加えたテーブルを作成します。

ancestryカラムはあとで加えます。

f:id:atsukofu:20200705210315p:plain

 

下記コマンドを実行↓

rails g model category

 

マイグレーションファイルを編集。

nameカラムを加えます。

class CreateCategories < ActiveRecord::Migration[5.2]
def change
create_table :categories do |t|
t.string :name, null: false
t.timestamps
end
end
end

 

次に、gemをインストールします。

gem "ancestry"

 

$ bundle install  → サーバー再起動を忘れずに。

 

次に、categoriesテーブルに「ancestry」カラムを追加するマイグレーションファイルを作成します。

下記コマンドを実行↓

$ rails g migration add_ancestry_to_categories ancestry:string:index

 

↓こんなマイグレーションファイルが作られます。

class AddAncestryToCategories < ActiveRecord::Migration[5.2]
def change
add_column :categories, :ancestry, :string
add_index :categories, :ancestry
end
end

 

再度 $ rails db:migrate

 

よっしゃ!

f:id:atsukofu:20200705211032p:plain

 

category.rb(モデルファイル)にancestryを記入。

class Category < ApplicationRecord
has_ancestry
end

 

 

挿入データを作成する

ancestryを使った多階層構造は、データベースに入ったデータを使って表現するため、

カテゴリーをデータベースに入れる必要があります。

データベースに最初からデータを入れるのには、db/seeds.rb というファイルを使用します。

今回は、入れるデータの量が多く、親カテゴリー毎にファイルを分けて作成したいので、

dbディレクトリ直下にseedディレクトリを作成し、

例えば、レディースカテゴリ → ladies.rb

というファイル名をつけ、seed.rbに下記のように記載し、引用します。

require './db/seeds/ladies.rb'

 

では、ladiesカテゴリーの子カテゴリ・孫カテゴリを作成していきます。

メルカリはスクレイピング禁止なので、何か良い方法はないかな・・と考えていたのですが、

なかなか見つかりませんので、探す間に全データ入れられそうです。

今回は手打ちで入れちゃいます。

とりあえず、子カテゴリは2つだけで試してみます。

 

# レディースの子カテゴリー配列
ladies_child_array =
[
'トップス',
'ジャケット/アウター'
]

# レディースの孫カテゴリー別配列
ladies_grandchild_array =
[
[ 'Tシャツ/カットソー(半袖/袖なし)',
'Tシャツ/カットソー(七分/長袖)',
'シャツ/ブラウス(半袖/袖なし)',
'シャツ/ブラウス(七分/長袖)',
'ポロシャツ',
'キャミソール',
'タンクトップ',
'ニット/セーター',
'チュニック',
'カーディガン/ボレロ',
'アンサンブル',
'ベスト/ジレ',
'パーカー'
],
[
'ノーカラージャケット',
'Gジャン/デニムジャケット',
'レザージャケット',
'ダウンジャケット',
'ミリタリージャケット',
'ダウンベスト',
'ジャンパー/ブルゾン',
'ポンチョ', 'ロングコート',
'トレンチコート',
'ダッフルコート',
'ピーコート'
]
]

 

子カテゴリは配列、孫カテゴリは配列の配列として作成します。

ここでこの形にする理由ですが、

子カテゴリの配列のインデックス番号と、孫カテゴリの配列のインデックス番号を合わせておくためです。

 

上記で記入したデータをデータベースに入れる命令を書きます。

まず、親カテゴリから。

parent = Category.create(name: 'レディース')

 

次に、子カテゴリですが、ループ処理で実行します。

ladies_child_array.each do |child|
child = parent.children.create(name: child)
end

 

孫カテゴリもループ処理で実行するのですが、上記のループ処理にネストする形で描きます。

ここで、子カテゴリのインデックス番号と孫カテゴリのインデックス番号を合わせておく必要がありますので、

子カテゴリの式をインデックス番号付きの物に書き換えています。

ladies_child_array.each.each_with_index do |child, i|
child = parent.children.create(name: child)
ladies_grandchild_array[i].each do |grandchild|
child.children.create(name: grandchild)
end
end

 

インデックス番号[ i ]の子カテゴリをデータベースに入れる際に、

孫カテゴリの[ i ]番目の塊をそれぞれデータベースに入れる、という処理です。

 

 最後に、下記コマンドを実行します。

$ rails db:seed

 

もしデータ内容に不備があった場合は、

$ rails db:migrate:reset

でseedsの内容を破棄後、修正分を

$ rails db:seed

で入れ直します。

 

 

テーブルの確認

sequel.proでデータベースの内容を確認すると...

f:id:atsukofu:20200705214637p:plain

無事に入っています!!!やったーーー!!!

 

ancestryカラムの見方ですが、

親カテゴリ → NULL

子カテゴリ → 親カテゴリのid

孫カテゴリ → 親カテゴリのid/子カテゴリのid

という形で関係性を見ることができます。

 

 

まとめ

多階層構造はよく見掛けますが、railsだとこうやって作ると簡単に確実に作れるのだと、勉強になりました!!

そして、新しいことができるようになると、

またプログラミングが楽しくなりました!

 

次は、データベースに入れたカテゴリーをビューに表示できるように実装していきたいと思います!