【Rails】バリデーションを特定のコントローラで使う


はじめに

特定のバリデーションを特定のコントローラでのみ作動させたい場合にどうすれば良いかについて書いていきます。

具体例

例えばユーザー情報を登録させるとき、ステップごとに情報を登録させたいときを考えてみます。

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
step1コントローラ
def create
  @user = User.new(user_params)
  if @user.valid?(:step1) && @user.save
    return redirect_to step2_path
  end

  render :new
end
step2コントローラ
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で使い分けたい場合はこちらの記事を参考にしてください。(本投稿とかぶる部分もありますが…)