Rails、バリデーション設定を条件ごとに適用する
Railsでアプリを作成している際にユーザ登録ページでバリデーション設定をしていました。
複数のテーブルに同時に登録をすることや、後からデータ更新するなど、条件によって適用するバリデーション変更したかったので、自分なりに実施してみました。
なぜするのそんなこと?
Webサイトによくある新規会員登録のページを作成時の話。
元々は全データを一つのテーブルにいれてましたが、一部のデータをどうしても分ける必要性が出てきました。
そしてすでに新規会員登録のベースとなるプログラムは書き終えていたのですが、必要性と自己学習観点からも実装したかったので、複数のテーブルに同時に保存することにしました。
最初に考えていたデータ保存のながれ
初めは単純にユーザ情報なのでユーザテーブルに保存しておけばいいとばっかり思ってました。
個人情報を扱うテーブル構造へ変更
ユーザの個人情報に関するデータをProfileテーブルに移行しました。後々実施するSNS利用によるログイン機能に必要なデータがあることも分かったので、ログイン情報周りをUserテーブルに保存する形としました。
やりたいこと
新規会員登録を複数ページに分けて実施
今回、ユーザ情報登録を2ページに跨がって作成しておき、ユーザが順番に情報を入力することで登録が完了するような内容を想定。
>記事記載の都合上、下記の表現を利用する。
※まず登録できることを目標としているので、途中のページで中止したことによるトランザクション処理は考慮していません。
具体的な手順
- P1でユーザ情報保存時にUserとProfileへ同時にデータを保存する。その時、必要なバリデーションのみを適用したい
- P2にてProfileへデータ保存時に必要なバリデーションを適用したい
初めに設定したUserテーブルバリデーションが下図。
メールアドレスとカナ入力に対して正規表現を利用しています。
やったこと
バリデージョンに条件分岐を設定
新規作成時とアップデート時に分けてバリデーションを設定することで、データ登録を正常にできるようにした。
正直なところ、始めによく分かっていなかった為、バリデーションエラーによって登録できない状態となった為、本記事をかくきっかけとなった。
具体的な手順
- P1での情報登録時にはProfileには一部のデータのみ保存する為、保存しないデータについてはバリデーションの対象外とした。
- P2での情報登録時は、Profile保存済みのデータができているので、アップデートとしてデータを追加。
やった内容
複数テーブルに保存を実装
まず、保存先が複数テーブルになっているため同時に保存することができるようにしました、
※実は、バリデーションをかけたまま実装していたので、permitで送信していないデータがバリデーションエラーとなっていきなりはまってました。
データ保存の通りは下図のとおりでした。
※黒字カラムは本内容実装時はまだ未実装でした。
見直したバリデーション
そして、Profileテーブルに移行したカラムについて、バリデーションをこのように見直しました。
最初のデータ保存時にProfileテーブルの全てにバリデーションを設定したままであった為、paramsで送信しないデータは対象外にしました。
具体的には、次のページで保存するデータは後から追加保存(更新)する方法をとることにしたので、更新時のみバリデーションを設定することにしました。
on: :updateという記述によりアップデート時にのみバリデーションを適用することで、本仕様を実現させました。
また、with_optionsメソッドによってまとめて設定できることが分かりましたので、住所登録ページの内容をまとめることができました。
さいごに
バリデーションを意識したテーブル設計と機能実装を必要と実感
今までは登録出来ることが出来れば良いと思ってましたが、結局あとからデータ保存観点で困ったことが発生することになりました。
本内容実装後にニックネームの編集機能を考えていたのですが、ここでも同じテーブルに登録しているがゆえのバリデーション問題を抱えることになりました。
結局のところ、これだけバリデーションに対して条件分岐するなら、そもそものデータベース仕様や、複数テーブルに保存している所を見直す方が良いと感じました。
今回の機能実装によって、設定するべきバリデーションを意識したデータベース設計の重要性を認識することができました。