#パスワードの再設定
パスワードを忘れた時のパスワードの再設定に取り組めるようになりました。
メールレイアウト用と新しいパスワードの送信用のフォームが必要となります。
リソースとは、直訳すると「資源」と言う意味ですが、ウェブサイトにおいては、ウェブサイトを構成するもの一般(文書・画像・その他諸々のデータファイルなど)を指します。
アカウント有効化の際と似ていて、PasswordResetsリソースを作成して、再設定用のトークンとそれに対応するダイジェストを保存するのが今回の目的となります。
1.ユーザーがパスワードの再設定をリクエストすると、ユーザーが送信したメールアドレスをキーにしてデータベースからユーザーを見つける
2.該当のメールアドレスがデータベースにある場合は、再設定用トークンとそれに対応する再設定ダイジェストを生成する
3.再設定用ダイジェストはデータベースに保存しておき、再設定用トークンはメールアドレスと一緒に、ユーザーに送信する有効化用メールのリンクに仕込んでおく
4.ユーザーがメールのリンクをクリックしたら、メールアドレスをキーとしてユーザーを探し、データベース内に保存しておいた再設定用ダイジ
ェストと比較する(トークンを認証する)
5.認証に成功したら、パスワード変更用のフォームをユーザーに表示する
##PasswordResetsリソース
PasswordResetsリソースのモデリングを行う。
前章と同様に、今回も新たなモデルは作らずに、代わりに必要なデータ(再設定用のダイジェストなど)をUserモデルに追加していく。
$ git checkout -b password-reset
###PasswordResetsコントローラ
パスワード再設定用のコントローラを作ってみましょう。
ubuntu:~/environment/sample_app (password-reset) $ rails generate controller PasswordResets new edit --no-test-framework
# テストを生成しないというオプションを指定していることにご注目ください。
Running via Spring preloader in process 14763
create app/controllers/password_resets_controller.rb
route get 'password_resets/new'
get 'password_resets/edit'
invoke erb
create app/views/password_resets
create app/views/password_resets/new.html.erb
create app/views/password_resets/edit.html.erb
invoke helper
create app/helpers/password_resets_helper.rb
invoke assets
invoke scss
create app/assets/stylesheets/password_resets.scss
今回の実装では、新しいパスワードを再設定するためのフォームと、Userモデル内のパスワードを変更するためのフォームが必要になる。
そのためnew、create、edit、updateのルーティングも用意しましょう。
####パスワード再設定用リソースを追加する
config/routes.rb
Rails.application.routes.draw do
get 'password_resets/new'
get 'password_resets/edit'
get 'sessions/new'
root 'static_pages#home'
# 何の意味がわからん
# ホーム画面がhomeページなるらしい
get '/help', to: 'static_pages#help'
# static_pagesコントローラからhomeアクションに紐付けされる
# getでアクセルすることでページを取得することができる
get '/about', to: 'static_pages#about'
# 何を書いているかはわからない
get '/contact', to: 'static_pages#contact'
# aboutアクションにGETリクエストを送る
get '/signup', to: 'users#new'
# urlに/signupと書くとuserコントローラのnewアクションを起こす
get '/login', to: 'sessions#new'
# データを取得
post '/login', to: 'sessions#create'
# データを投稿
delete '/logout', to: 'sessions#destroy'
# 削除
resources :users
# /users/1の有効にするため
resources :account_activations, only: [:edit]
# editアクションへの名前付きルートが必要になるため
# ルーティングのアカウント有効化
resources :password_resets, only: [:new, :create, :edit, :update]
# 新しいパスワードを再設定するためのフォームと、Userモデル内のパスワードを変更するため
end
####パスワード再設定画面へのリンクを追加する
app/views/sessions/new.html.erb
<% provide(:title, "Log in") %>
<h1>Log in</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_with(url: login_path, scope: :session, local: true) do |f| %>
<!--セッションの場合はリソースのスコープとそれに対応するURLを具体的に指定する必要-->
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
<%= f.label :password %>
<%= link_to "(forgot password)", new_password_reset_path %>
<!--パスワードのリンクをつける-->
<%= f.password_field :password, class: 'form-control' %>
<%= f.label :remember_me, class: "checkbox inline" do %>
<!--remember_meチェックボックスを追加 うまく動作するために ラベルの内側に配置-->
<%= f.check_box :remember_me %>
<span>Remember me on this computer</span>
<% end %>
<%= f.submit "Log in", class: "btn btn-primary" %>
<% end %>
<p>New user? <%= link_to "Sign up now!", signup_path %></p>
</div>
</div>
###演習
1.
この時点で、テストスイートが green になっていることを確認してみましょう。
確認
表 12.1の名前付きルートでは、_pathではなく_urlを使うように記してあります。なぜでしょうか? 考えてみましょう。ヒント: アカウント有効化で行った演習(11.1.1.1)と同じ理由です。
メールで使うから