こんにちは、ジョンです。
今回は技術的な内容です。
ユーザー作成ページなどが複数ページに渡っているため、
Validationを各ページごとに置きたい、けど情報が足りてないから .valid?
では回せない…
と困っていたので、ちょっと工夫してみました。
N番煎じかもしれませんが、どなたかの役に立てば幸いです。
状況
以下のようなソースがあったとします。
def confirm
user = User.new(user_params)
unless user.valid?
redirect_to new_user_path and return
end
end
Userテーブルには、
– name (氏名)
– email (Email)
– address (住所)
– password (パスワード)
というカラムがあるとします。(全て必須)
構造
1ページ目:入力ページ(/users/new)
2ページ目:入力内容確認&パスワード入力画面(/users/confirm)
3ページ目:作成完了画面(/users/create)
問題点
1ページ目では、氏名、Email、住所のみを入力し、
次の確認画面で問題なければ、パスワードを設定する、というフローを踏んでいた場合、
1ページ目のValidationを確認する際、 .valid?
では常にNGになってしまっていました。
作ったコード
そこで、指定したカラムのみValidationを走らせる方法はないかと考え、以下のソースコードを作成しました。
app/controllers/users_controller.rb
def confirm
user = User.new(user_params)
user.valid?
unless user.valid_of_specified?(:name, :email, :address)
redirect_to new_user_path and return
end
end
コントローラーはあんまり変化なしです。
valid?とは別に、独自メソッドである valid_of_specified?
を用意しました。
こちらは、以下のmodelを見て頂ければ分かるのですが、
app/models/user.rb
def valid_of_specified?(*columns)
columns.each do |column|
return false if self.errors.messages.include?(column)
end
true
end
エラーメッセージにその要素が存在するか?で判定しております。
そのため、 user.valid?
を噛まさないとエラーが出力されないため、user.valid?
を条件分岐の前に置いている感じです。
結果
うまく動きました。
とりあえず限定カラムのみ、Validationが通るか否かを確認したいだけなら、
これで良いかなと思いました。
ただ、 user.valid?
をそのまま設置しておかなきゃいけないってのが
なんか気持ち悪さが残るので、もうちょい改良出来たら良いなと思ってます。