開発環境は、以下になります。
Rails: 6.0.4.1
Ruby: 2.5.1
sorcery gemを使って、パスワードリセット機能を付けています。
現在やりたい事は、プロフィール画面で名前とEメールだけを編集して更新できるようにしたいです。
Userモデルは、以下のようになっています。
class User < ApplicationRecord authenticates_with_sorcery! validates :password, length: { minimum: 10 }, if: -> { new_record? || changes[:crypted_password] } validates :password, confirmation: true, if: -> { new_record? || changes[:crypted_password] } validates :password, presence: true, unless: -> { validation_context == :not_password_validation } ① validates :password_confirmation, presence: true, if: -> { new_record? || changes[:crypted_password] } validates :email, uniqueness: { case_sensitive: false }, presence: true validates :name, presence: true end
Usersコントローラは、以下のようになります。
class UsersController < ApplicationController before_action :require_login, only: %i[show edit update] def new @user = User.new end def create @user = User.new(user_params) if @user.save flash[:success] = t '.success_message' redirect_to login_path else flash.now[:danger] = t '.error_message' render :new end end def show @user = User.find(current_user.id) end def edit @user = User.find(current_user.id) end def update @user = User.find(current_user.id) @user.attributes = profile_params if @user.save(context: :not_password_validation) flash[:success] = t '.success_message' redirect_to profile_path else flash.now[:danger] = t '.error_message' render :edit end end private def user_params params.require(:user).permit(:name, :email, :password, :password_confirmation) end def profile_params params.require(:user).permit(:name, :email) end end
パスワードリセットコントローラは、以下のようになります。
class PasswordResetsController < ApplicationController # In Rails 5 and above, this will raise an error if # before_action :require_login # is not declared in your ApplicationController. # request password reset. # you get here when the user entered their email in the reset password form and submitted it. def new; end def create @user = User.find_by(email: params[:email]) # This line sends an email to the user with instructions on how to reset their password (a url with a random token) @user.deliver_reset_password_instructions! if @user # Tell the user instructions have been sent whether or not email was found. # This is to not leak information to attackers about which emails exist in the system. if logged_in? flash.now[:success] = t '.success_message' render template: 'profiles/show' else flash[:success] = t '.success_message' redirect_to login_path end end # This is the reset password form. def edit @token = params[:id] @user = User.load_from_reset_password_token(@token) if @user.blank? not_authenticated return end end # This action fires when the user has sent the reset password form. def update @token = params[:id] @user = User.load_from_reset_password_token(@token) if @user.blank? not_authenticated return end # the next line makes the password confirmation validation work @user.password = params[:user][:password] @user.password_confirmation = params[:user][:password_confirmation] # the next line clears the temporary token and updates the password if @user.valid? && @user.change_password(params[:user][:password]) flash[:success] = t '.success_message' redirect_to login_path else render :edit end end end
上記での①validates :password, presence: true
は、パスワードリセット時にパスワードの欄に入力せずパスワード再確認の欄にだけ入力してもバリデーションエラーにならない仕様になっていたので、自分で追加記載しました。
プロフィール画面では、名前とEメールを編集し更新できるようにしたいのですが、パスワード属性のバリデーションに引っかかってしまいます。
記事を参考にバリデーションのコンテキスト(onオプション)を使って、コンテキストを記述した時以外は通常通りバリデーションを実行されるようにしたいのですが、なかなかうまくできません。
パスワードのバリデーションを使う時のみ、saveやupdateの時にコンテキストを記述できない理由は、パスワード更新時のメソッドがchange_password(params[:user][:password])
となっており、updateのようにそのままコンテキストを記載できないためです。
###参考記事
https://www.timedia.co.jp/tech/rails-validation-not-on-context/
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。