Webエンジニアの森脇です。 Railsアプリケーションで採用しているDB設計(スキーマ定義)について紹介します。
※ Railsでは当たり前もの、Railsに依存していない内容も含んでいます。
前提
環境違えば、採用するルールも異なると思いますので、まずは弊社で利用している環境を記載します。
- DBはPostgreSQL 9.x
- 開発言語は、Rails 4.x,5.xを利用
命名ルール
Railsの規約に沿う命名を採用しています。DB設計にこだわりがあるメンバーにとっては、異論があるルールもあるのですが、アプリケーション開発の生産性も考慮しRailsの規約に寄り添うのがよいと判断をしました。
テーブル
- 動詞は使用せず、名詞とする
- 複数形とする
- 1:n のテーブル名は「単数形_複数形」 とする
- n:n のテーブル名は「複数形_複数形」とする
カラム
- カラム名にテーブル名のprefixは付与しない
- usersテーブルのユーザ名は「user_name」ではなく「name」とする
- 主キーは、idとする
- 外部キーは、「JOIN先のテーブル名(単数系)_id」とする
- boolean型は、true/falseが自明な名称にする
- xxxx_flagなど、true/falseの意味が自明ではないため利用しない
- is_xxxxやcan_xxxxなどの明確な名称にする
- 時間を記録するカラムは 受動態on、受動態atとする
- DATE型は「受動態_on」 とする
- TIMESTAMP型は「受動態_at」とする
インデックス
- 原則、Railsのmigrationでの自動生成ルールに任せる
- 自動生成で桁数オーバーする場合は、
idx_<テーブル名>_on_<カラム名>
をベースとして収まるように適宜調整
型
型もRailsのMigrationから生成される標準の型を利用しています。
数値
- 整数
- 特別な理由がない場合は、integerを利用する
- 浮動小数
- 特別な理由がない場合は、numericを利用する
- numeric とdecimalは同一のため使い分け不要
文字列
- 特別な理由がない場合は、varcharを利用する
- Rails 4.1以前で、migrationを作成時には、stringとtextの使い分けが必要
日付
- dateを利用する
時刻
- timeを利用する
日時
- timestampを利用する
制約など
データ整合性を担保するための制約は、極力利用する方針としています。
外部キー制約
使用する
- テストデータ作成が若干手間なのは否めないが、不整合があるデータを作ってしまい結局ハマることもあるので、DB側でガードしたい
- SQLで直接データ修正する場合も考慮すると、アプリケーションだけでのデータチェックでは不十分
ユニーク制約
使用する
- DB側で、データ整合性を担保するため
NOT NULL制約
付与可能なカラムには、必ず付与する
- DB側で、データ整合性を担保するため
- 既存テーブルへのカラム追加の場合は、以下の手順をとる
- NOT NULL 制約なしでカラム追加
- 該当カラムに値を設定
- NOT NULL 制約を追加
デフォルト値
利用しない
- デフォルト値に頼らず、アプリケション側で明確な意図を持って設定したい
Check制約
利用しない
- 複雑なチェック条件は、Check制約では対応できないため、利用しても中途半端になると判断
ON DELETE CASCADE
利用しない
- データの削除は、アプリケーション側で明確にコントロールしたい
最後に
以前はレビューの都度、制約などのあるべき論を議論をしてしまい、レビューに時間がかかってしまっていました。ガイドラインを整備することでチーム内の意識統一が容易になり、より本質的なレビューができるようになりました。