Railsチュートリアル12章 パスワードの再設定
11章最後の起こった外部サービスが原因でメールが送れない問題ですが、無事に解決できました。
SendGrid社のフィルタリングに引っかかってしまい、アカウントが停止になってしまったようなので、
こういう場合はSendGrid社の米本社の方の文面を送ってほしいとFAQページに書いてあったので、英文で現状の報告とアカウント停止解除をお願いするメールを送りました。
数通のやり取りの後、SendGrid社のシステムを使えるようになり、無事に11章でのメールによるアカウント登録機能を完成させることができました。
無料ユーザーにもかかわらずSendGrid社のサポート担当の方の素早いご丁寧な対応に感謝いたします。
今回の12章はパスワードの再設定です。
再設定の流れとしては以下で、
ログイン画面でパスワードの再設定リンクを踏むと、メールアドレス入力フォームになり、
これにアドレスを入力すると再設定用のリンクを含んだメールが送られ、
メールのリンクを踏むと、パスワード再設定用のフォーム画面が表示され、これによってパスワードが再設定されます。
また、11章でパスワード再設定用のメイラーの基本部分は生成してあるので、これを利用します。
アルゴリズムとしては11章のアカウントメール登録機能と似たような仕組みで、メールリンクの後にパスワード再設定ファームに入力する部分がプラスになります。 以下サーバ側の処理の流れになります。
ユーザーがパスワードの再設定をリクエストすると、ユーザーが送信したメールアドレスをキーにしてデータベースからユーザーを見つける
該当のメールアドレスがデータベースにある場合は、再設定用トークンとそれに対応するリセットダイジェストを生成する
再設定用ダイジェストはデータベースに保存しておき、再設定用トークンはメールアドレスと一緒に、ユーザーに送信する有効化用メールのリンクに仕込んでおく
ユーザーがメールのリンクをクリックしたら、メールアドレスをキーとしてユーザーを探し、データベース内に保存しておいた再設定用ダイジェストと比較する (トークンを認証する)
認証に成功したら、パスワード変更用のフォームをユーザーに表示する
12.1.1 PasswordResetsコントローラ
11章ではメールリンクを踏むだけで本登録完了でしたので、 edit_account_activation GET /account_activations/:id/edit(.:format)にアクセスでeditアクションだけで完了でしたが、 12章ではメールリンクを踏むとフォーム画面を描画して、フォーム画面の入力を完了するとパスワードの変更完了という流れですので、 パスワード変更フォーム画面の描画をnew、パスワード変更の投稿をeditでしますので、newとeditアクションとURLがそれぞれ必要になるようです。
rails generate controller PasswordResets new edit --no-test-framework
そして新しいリソースとして以下を設定します
resources :password_resets, only: [:new, :create, :edit, :update]
HTTPリクエスト | URL | Action | 名前付きルート |
---|---|---|---|
GET | /password_resets/new | new | new_password_reset_path |
POST | /password_resets | create | password_resets_path |
GET | /password_resets/ |
edit | edit_password_reset_url(token) |
PATCH | /password_resets/ |
update | password_reset_url(token) |
ログイン画面にパスワード再設定画面へのリンクを追加して
reset_digest属性とreset_sent_at属性をUserモデルに追加、
app/views/password_resets/new.html.erbにパスワード再設定フォーム画面を作り、
コントローラ部分とメイラー部分を作っていきます。
12.3.1 editアクションで再設定
今回はeditアクション(メールリンクからアクセスした時のアクション)の他に、updateアクションがあり、両方でメールアドレス情報が必要です。 パスワードの再設定では、editアクションでパスワードの再設定フォーム画面を表示させ、そのフォームのパスワード情報をupdateアクションでデータベースに反映させます。 editアクションはリンクからメールアドレス情報を取得すればいいのですが、こフォームにはパスワード入力しかないのでupdateアクションは別の方法メールアドレス情報を取得しなければなりません。
そこで、editアクションで描画されたフォーム画面edit.html.erbから値を引き継ぐために、隠しフィールドとしてページ内にメールアドレスを保存する手法を取ります。
リスト 12.14: パスワード再設定のフォーム app/views/password_resets/edit.html.erb <% provide(:title, 'Reset password') %> <h1>Reset password</h1> <div class="row"> <div class="col-md-6 col-md-offset-3"> <%= form_for(@user, url: password_reset_path(params[:id])) do |f| %> <%= render 'shared/error_messages' %> <%= hidden_field_tag :email, @user.email %> #ここが隠しフィールド <%= f.label :password %> <%= f.password_field :password, class: 'form-control' %> <%= f.label :password_confirmation, "Confirmation" %> <%= f.password_field :password_confirmation, class: 'form-control' %> <%= f.submit "Update password", class: "btn btn-primary" %> <% end %> </div> </div>
12.3.2 パスワードを更新する
以下のコードの意味を少し忘れてしまっていたので、復習。
def user_params params.require(:user).permit(:password, :password_confirmation) end
require メソッドを利用することで、引数に設定した key の 値だけを取得することができ、
permit メソッドは許可したいパラメータだけをフィルタしてくれるようです。
つまり上のコードはパラメーターのキー:user内のpasswordとpassword_confirmationのみを受け取るということになる、という意味かな? paramsから受け取る情報を制限するコードです
今回はだいたい前章と同じような内容だったため、割とすんなり理解できました。
SendGridも自力の試行錯誤の結果使えるようになったのは嬉しかったです。
次回はログイン機構から離れ、いよいよ投稿機能に移っていくようで楽しみです。