質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

解決済

バリデーションのコンテキストの条件を逆にしたい

higmonta
higmonta

総合スコア20

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

1回答

0リアクション

0クリップ

120閲覧

投稿2022/08/14 19:52

編集2022/08/14 20:10

開発環境は、以下になります。
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/

https://qiita.com/metafalse/items/872d0403e3030aa6db38

以下のような質問にはリアクションをつけましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

リアクションが多い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。