はじめに
特定のバリデーションを特定のコントローラでのみ作動させたい場合にどうすれば良いかについて書いていきます。
具体例
例えばユーザー情報を登録させるとき、ステップごとに情報を登録させたいときを考えてみます。
Usersテーブル
|column|type|
|------|----|------|
|name|string| |
|email|string| |
|password|string| |
|address|string| |
|image|string| |
1ページ目:name, email, password
2ページ目:address, image
というように、name, email, passwordを保存してから、adress, imageを保存するという処理を考えます。
全てのカラムを必須項目にしたい場合、モデルにpresence: true
をただ書いてしまうと、1ページ目の登録の際にエラーになります。(address, imageが空になっているため)
1ページ目と2ページ目でバリデーションを使い分けたい時はどうすれば良いでしょう?
やり方
with_options
というものを使って各アクションごとに使い分ければOKです。
イメージ的には、モデルにwith_options on: 〜 do
としてバリデーションのグループに名前をつけておいて、コントローラでvalid?(名前)
のメソッドを使ってバリデーションのチェックをする感じです。
具体的な書き方は以下のようになります。(少し端折って書いてる部分もあるのでご注意ください)
with_options on: :step1 do
validates :name, presence: true
validates :email, uniqueness: true
validates :password, presence: true, length: { minimum: 8 }
validates :password, confirmation: true
end
with_options on: :step2 do
validates :address, presence: true
validates :image, uniqueness: true
end
def create
@user = User.new(user_params)
if @user.valid?(:step1) && @user.save
return redirect_to step2_path
end
render :new
end
def update
@user = User.find(params[:id])
if @user.valid?(:step2) && @user.update(user_params)
return redirect_to user_path
end
render :edit
end
補足
同時に全てのバリデーションをかけたい場合は、valid?(:step1) && valid?(:step2)
のように書く必要があるので少々面倒です…
(valid?だけで全てのwith_optionsを使ってくれないかと思いましたがダメでした)
ちなみにcreateとupdateで使い分けたい場合はこちらの記事を参考にしてください。(本投稿とかぶる部分もありますが…)