Help us understand the problem. What is going on with this article?

sorcery でパスワードを更新(update)する

More than 3 years have passed since last update.

sorcery とは

Ruby on Rails にユーザアカウント認証機能を持たせようと思った場合、device を使うのが定石という風潮がありますが、よりシンプルな sorcery もなかなかに有用です。詳しくはこちらをご参考ください。

本題

パスワードを更新する

sorcery にはパスワードリマインダ機能があるので、いわゆる「パスワード忘れちゃった」系の要件については、パスワードリマインダを使えば良いことになっています。

で、それではなく、フォームを通してユーザに新しいパスワードを入力してもらい、それを新しいパスワードに設定する、というありがちな感じの機能を実装する場合、

user_controller.rb
user = current_user
user.password = params[:password]
user.password_confirmation = params[:password_confirmation]
if user.valid?
  user.save
else
  render :edit
end

みたいな書き方をしたくなるのですが、こうすると password と password_confirmation がうまく user モデルのバリデーションにかからず、password の内容でパスワードを更新してしまいます。

公式のWiki (注: 更新されました)を見ると、パスワードの検証は user モデルに

models/user.rb
validates :password, length: { minimum: 3 }, if: -> { new_record? || changes["password"] }
validates :password, confirmation: true, if: -> { new_record? || changes["password"] }
validates :password_confirmation, presence: true, if: -> { new_record? || changes["password"] }

こんな感じでバリデーションを書けば password と password_confirmation がうまく検証されるよーと書いてあります。これは確かにユーザを新規登録するときには有効に働くのですが、どうも既存ユーザのパスワードを更新する際にはうまくいかないっぽい。

これについていろいろ調べた結果、

user_controller.rb
user = current_user
user.password = params[:password]
user.password_confirmation = params[:password_confirmation]
if user.valid?
  user.save
else
  render :edit
end

コントローラ側はこのままでよくて、

models/user.rb
validates :password, length: { minimum: 3 }, if: -> { new_record? || changes[:crypted_password] }
validates :password, confirmation: true, if: -> { new_record? || changes[:crypted_password] }
validates :password_confirmation, presence: true, if: -> { new_record? || changes[:crypted_password] }

バリデーション側の changes["password"]changes[:crypted_password] にする必要があるらしいことが判りました。これに修正したところ、ユーザを新規作成するときと同様、パスワード更新時にも validates に記載した内容を検証してくれるようになりました。changes[:crypted_password] は user モデルの同名フィールドと連動しているため、それを指定してやる必要があるっぽい。

なお changes[:crypted_password] は、password と password_confirmation が指定されていない場合は「パスワードの更新なし」と判断しますので、パスワードの変更があるかどうかなどの部分について、分岐処理をコントローラ等に書く必要がないです。楽ちんですね。

ltcmdr927
趣味はボランティアです
https://about.me/ltcmdr927
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした