先日実装した「furimaアプリ」の実装について
記録を残すため記事を書いてみようと思います。
FURIMAの必須機能
ユーザーのログイン機能
商品出品 / 購入
必要なテーブルを洗い出す
「ユーザー情報」「商品情報」「発送先情報」を保存する必要がある。
ここまではわかったのですが、「売り切れ」を表示するために、商品に「購入記録」を結びつける必要があると考えました。
「購入記録」と「発送先情報」のテーブルを一緒にすることもできますが、発送先情報だけでも郵便番号、都道府県、市区町村など多くの情報を含むので、管理しやすいように別々の情報として考えました。
よって、最初に必要なテーブルは「ユーザー情報」「商品情報」「購入記録」「発送先情報」の4つとなりました。
実装条件を見て必要なカラムを洗い出す
今回、ActiveHashを使用する指示があったものは「〜_id」というカラム名にしました。(ActiveHashについては別の記事で書きます)
保存している情報が分かるように命名するのは、私にとってまだまだ課題だな。と感じました。
テーブル | カラム | カラム名 |
---|---|---|
ユーザー(users) | ニックネーム | nickname |
メールアドレス | ||
パスワード | encrypted_password | |
苗字(全角) | family_name | |
名前(全角) | first_name | |
苗字カナ(全角) | family_name_kana | |
名前カナ(全角) | first_name_kana | |
生年月日 | birth_day | |
商品情報(items) | 出品者 | user |
商品名 | name | |
商品の説明 | explanation | |
カテゴリー | category_id | |
商品の状態 | condition_id | |
配送料の負担 | postage_id | |
発送元の地域 | prefecture_id | |
発送までの日数 | preparation_id | |
価格 | price | |
発送先情報(addresses) | 購入記録 | order |
郵便番号 | post_code | |
都道府県 | prefecture_id | |
市区町村 | city | |
番地 | address | |
建物名 | building_name | |
電話番号 | phone_number | |
購入記録(orders) | 誰が | user |
どの商品を | item |
テーブル間の関係性を考える
①ユーザー情報と商品情報のテーブルについて
「新規登録(ログイン)をしたユーザーは、いくつ商品を出品することができるか?」という点に着目。
自分が普段利用している某フリマアプリを想像。たくさん出品してるな。
ということで、ユーザーはたくさんの商品を持つことができる。
自分が出品した商品の出品者は自分一人だけのはずなので、ユーザーと商品情報は1対多になりました。
②ユーザー情報と購入記録のテーブルについて
「新規登録(ログイン)をしたユーザーは、いくつ商品を購入することができるか?」という点に着目。
自分が某フリマアプリで何を買ったかな?ダンスの衣装、結婚式の小物...たくさん買ってる! お世話になってるなあ。
自分の名前は購入記録にたくさん刻まれている。
1つの商品に対して、買主は1人なので、ユーザーと購入記録は1対多になりました。
③商品情報と購入記録のテーブルについて
1つ1つの商品は、購入されると売り切れとなります。つまり、「1つの商品につき、購入できるのは1回」ということです。
1対1の場合、has_oneというアソシエーションの知識が必要になります。
「一方が存在しないと存在できない」という考え方が必要になってきます。
商品は購入記録がなくても存在することができますが、 購入記録は商品ありきの購入記録です。
なので、親子関係を考えると、商品が親、購入記録は子になります。
親が「has_one」のアソシエーションを持つので、商品情報にhas_oneのアソシエーションを持たせました。
④発送先情報と購入記録のテーブルについて
初め、ユーザーに発送先情報が紐づくのかなと思っていたのですが...
実装条件に「配送先の住所情報も購入の都度入力」とあり、必ずしもユーザーの住所が発送先になるわけではないと認識。
じゃあ発送先はどこに紐づくんだろう。と少し悩みました。
購入記録に発送先が記録されるので、ここだな。と認識。
1つの購入記録ごとに1つの発送先が登録されるので、ここも1対1。
初めは同じ住所あるかもしれん!って思い、1対多?とも思ったのですが、
実装条件に「配送先の住所情報も購入の都度入力」(強調)という仕様になっており、1つの商品は1つの住所にしか行けないと考えることができるので、1対1になる。
購入記録は「誰が」「何を」買ったのか記録されるテーブルで、発送先がなくても行き先待ちの状態で存在はできます。
発送先は購入記録がないと行き先として登録してもらえません。
なので、購入記録に親として「has_one」 のアソシエーションを持たせました。
ここが1番躓いたなと。実装条件をしっかり読み取るのって難しい。
READMEに記載
実装条件とアソシエーションを踏まえてOptionsを記載。
発送先の建物名は任意であるため、Optionsは不要。
今回、ActiveHashを使用する指示があったものは「integer型」にしてます。(ActiveHashについては別の記事で書きます)
README.md
# README ## users テーブル | Column | Type | Options | | ------------------ | ------ | ----------- | | nickname | string | null: false | | email | string | null: false, unique: true | | encrypted_password | string | null: false | | family_name | string | null: false | | first_name | string | null: false | | family_name_kana | string | null: false | | first_name_kana | string | null: false | | birth_day | date | null: false | ### Association - has_many :items - has_many :orders ## items テーブル | Column | Type | Options | | -----------------| ---------- | ------------------------------ | | user | references | null: false, foreign_key: true | | name | string | null: false | | price | integer | null: false | | explanation | text | null: false | | category_id | integer | null: false | | condition_id | integer | null: false | | postage_id | integer | null: false | | prefecture_id | integer | null: false | | preparation_id | integer | null: false | ### Association - belongs_to :user - has_one :order ## addresses テーブル | Column | Type | Options | | -----------------| ---------- | ------------------------------ | | order | references | null: false, foreign_key: true | | post_code | string | null: false | | prefecture_id | integer | null: false | | city | string | null: false | | address | string | null: false | | building_name | string | | | phone_number | string | null: false | ### Association - belongs_to :order ## orders テーブル | Column | Type | Options | | -----------------| ---------- | ------------------------------ | | user | references | null: false, foreign_key: true | | item | references | null: false, foreign_key: true | ### Association - belongs_to :user - belongs_to :item - has_one :address
感想
DB設計をするためには
登場人物を書き出して、システムを使う人の目線で「このシステムは、こんなことができるのね」と、考えることが大切だと感じました。
考えるためには、ユースケース図を用いるのがいいのかなと。
オリジナルアプリを作るときにもこの経験を活かしていきたいです。