Rails
devise
RubyOnRais

deviseでステップフォームを実装する際、ステップごとにバリデーションをかけるのに苦労した。


deviseでステップフォームを実装する

長くなってしまうため、ステップフォームを実装するコードの記載や説明は省略します。

deviseのgithubをよく読むこととsessionを使うことで実装できます。

参考までに

https://github.com/plataformatec/devise/tree/master


本題

さて、本題に入ります。


ステップごとにバリデーションをかける

バリデーションがかかるタイミングを指定したいため、

validatesメソッドのonオプションを使います。

登録のステップ1ということでregistration_step_1にします。

ステップ2,3・・・とステップがあるだけ以下のように記述しましょう。


user.rb

# ステップ1のバリデーション

with_options on: [:registration_step_1] do
validates :nickname, presence: true
end

# ステップ2のバリデーション
with_options on: [:registration_step_2] do
validates :phone_number, presence: true
end


onオプションについて詳しく書いてある記事

https://qiita.com/kadoppe/items/061d137e6022fa099872


devise特有の問題

deviseではあらかじめemailカラムとpasswordカラムにバリデーションが用意されています。

そのため、emailとpasswordを打つステップのみでそのバリデーションを読まないといけません。


deviseの問題解決

まずdeviseのgithubを見て、どこで条件分岐しなければいけないか見当をつけます。

password_required?メソッドでpassword、

email_required?メソッドでemailのバリデーションをかけるか判定しています。


lib/devise/models/validatable.rb

protected

def password_required?
!persisted? || !password.nil? || !password_confirmation.nil?
end

def email_required?
true
end



条件分岐をさせる記述方法

onオプションで条件分岐をさせたい場合は以下のように記述します。


user.rb


protected
def password_required?
# ステップ1のときだけバリデーションがかかるように条件分岐
if validation_context == :registration_step_1 
!persisted? || !password.nil? || !password_confirmation.nil?
end
end

def email_required?
# ステップ1のときだけバリデーションがかかるように条件分岐
if validation_context == :registration_step_1
true
end
end



最後に

これが一番良い方法というのはわからないので、参考までに!!