LoginSignup
6
6

More than 3 years have passed since last update.

【Rails】ユーザー編集時だけパスワードのバリデーションを無効にする(devise)

Posted at

環境

macOS: Big Sur Ver11.2.2
Rails: 6.0.0
Ruby: 2.6.5

この記事の目標

devise のデフォルトのユーザー編集画面ではパスワードの変更ができるが、現在のパスワードを入力しないとユーザー情報が編集できないようになっている。

そこで、
①現在のパスワードを入力しなくてもユーザー情報ができるようにする
②ユーザー編集のときだけモデルに設定しているパスワードのバリデーションを解除し、パスワード変更欄が空欄のままでもユーザー編集ができるようにする

の2点を実装することを目標とします。

現在のパスワードを入力不要にする

これについては多くの記事が出ています。以下が参考になります。

参考①
参考②
GitHub公式のwiki

ユーザー編集時だけパスワードのバリデーションを解除する

まず、Userモデルのバリデーションは以下のとおり

app/models/user.rb
class User < ApplicationRecord
  has_many :menus

  extend ActiveHash::Associations::ActiveRecordExtensions
  belongs_to :prefecture
  belongs_to :category

  has_one_attached :image

  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  # パスワードは半角英数混合で8文字
  validates :password, format: { with: /\A(?=.*?[a-z])(?=.*?\d)[a-z\d]{8}\z/i }
  with_options presence: true do
    validates :shop_name
    validates :address
    validates :business_hours
    validates :holiday
    validates :image
    validates :phone_number, format: { with: /\A0[1-9]\d{0,3}[-(]\d{1,4}[-)]\d{4}\z/ }
    with_options numericality: { other_than: 0, message: 'を選択してください' } do
      validates :category_id
      validates :prefecture_id
    end
  end
end

真ん中あたりにパスワードカラムのバリデーションに関する記述があり、正規表現を使っているため自動的に presence: true の存在性のバリデーションが効いています。
これは新規登録時には必須なのですが、編集時にパスワードを変えずに他の項目だけ変更したい場合にバリデーションエラーのもとになってしまいます。

解決策(オプションを記述する)

上記のパスワードカラムに対するバリデーションに on: :create オプションを記述します。
これにより新規登録時のみバリデーションがかかるようになります!
参考:Railsガイド「onオプション」

app/models/user.rb
class User < ApplicationRecord
()

  # on: :createオプションを追記
  validates :password, format: { with: /\A(?=.*?[a-z])(?=.*?\d)[a-z\d]{8}\z/i }, on: :create
  with_options presence: true do
    validates :shop_name
    validates :address
    validates :business_hours
    validates :holiday
    validates :image
    validates :phone_number, format: { with: /\A0[1-9]\d{0,3}[-(]\d{1,4}[-)]\d{4}\z/ }
    with_options numericality: { other_than: 0, message: 'を選択してください' } do
      validates :category_id
      validates :prefecture_id
    end
  end
end

ただし、これではユーザー編集時にパスワードに関するバリデーション(今回は半角英数混合で8文字)がまったく効かなくなってしまい、「abc」とかでもパスワード設定できてしまいます。
そこで、今回はバリデーションの記述を2行に分け、allow_blank: true オプションを追記します。

ということで、最終的なモデルのコードはこんな感じ。

app/models/user.rb
class User < ApplicationRecord
  has_many :menus

  extend ActiveHash::Associations::ActiveRecordExtensions
  belongs_to :prefecture
  belongs_to :category

  has_one_attached :image

  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  # パスワードに関するバリデーションをcreateとupdateで別々に記述しました
  validates :password, format: { with: /\A(?=.*?[a-z])(?=.*?\d)[a-z\d]{8}\z/i }, on: :create
  validates :password, format: { with: /\A(?=.*?[a-z])(?=.*?\d)[a-z\d]{8}\z/i, message: 'は半角英数混合で8文字です' }, allow_blank: true, on: :update
  with_options presence: true do
    validates :shop_name
    validates :address
    validates :business_hours
    validates :holiday
    validates :image
    validates :phone_number, format: { with: /\A0[1-9]\d{0,3}[-(]\d{1,4}[-)]\d{4}\z/ }
    with_options numericality: { other_than: 0, message: 'を選択してください' } do
      validates :category_id
      validates :prefecture_id
    end
  end

  def update_without_current_password(params)
    if params[:password].blank? && params[:password_confirmation].blank?
      params.delete(:password)
      params.delete(:password_confirmation)
    end
    update(params)
  end

end

これでユーザー編集時にパスワードの変更をしない場合は空欄のまま変更ができ、パスワードの変更をする場合は正規表現を適用することができました!

以上!

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6