Ruby on Rails チュートリアル(第4版)　第12章

##12.1.1　演習
1.この時点で、テストスイートが greenになっていることを確認してみましょう。
　省略

2.表 12.1の名前付きルートでは、_pathではなく_urlを使うように記してあります。なぜでしょうか? 考えてみましょう。ヒント: アカウント有効化で行った演習 (11.1.1.1) と同じ理由です。
　メールでURLを送付するから。

##12.1.2　演習
1.リスト 12.4のform_forメソッドでは、なぜ@password_resetではなく:password_resetを使っているのでしょうか? 考えてみてください。
　よく分からなかったので、[Railsのform_forにシンボルを与えるときはどのようなときか？](https://ja.stackoverflow.com/questions/18099/rails%E3%81%AEform-for%E3%81%AB%E3%82%B7%E3%83%B3%E3%83%9C%E3%83%AB%E3%82%92%E4%B8%8E%E3%81%88%E3%82%8B%E3%81%A8%E3%81%8D%E3%81%AF%E3%81%A9%E3%81%AE%E3%82%88%E3%81%86%E3%81%AA%E3%81%A8%E3%81%8D%E3%81%8B%EF%BC%89)こちらを参考に。
　複数のビューでform_forメゾット使う時に使い分けてくれるって感じなのかな？

##12.1.3　演習
1.試しに有効なメールアドレスをフォームから送信してみましょう (図 12.6)。どんなエラーメッセージが表示されたでしょうか?
　wrong number of arguments (given 1, expected 0)

2.コンソールに移り、先ほどの演習課題で送信した結果、(エラーと表示されてはいるものの) 該当するuserオブジェクトにはreset_digestとreset_sent_atがあることを確認してみましょう。また、それぞれの値はどのようになっていますか?

```

　SQL (2.5ms)  UPDATE "users" SET "reset_digest" = ?, "updated_at" = ? WHERE "users"."id" = ?  [["reset_digest", "$2a$10$HBKO270gNm.cJbXLUiK42.kbtr6rHK54A5shhjJ3AuyxdZ8CwKR2G"], ["updated_at", "2020-07-23 14:35:37.103987"], ["id", 1]]
   (7.2ms)  commit transaction
   (0.0ms)  begin transaction
  SQL (1.5ms)  UPDATE "users" SET "updated_at" = ?, "reset_sent_at" = ? WHERE "users"."id" = ?  [["updated_at", "2020-07-23 14:35:37.129134"], ["reset_sent_at", "2020-07-23 14:35:37.128433"], ["id", 1]]
```

##12.2.1　演習
1.ブラウザから、送信メールのプレビューをしてみましょう。「Date」の欄にはどんな情報が表示されているでしょうか?
　`Date:Thu, 23 Jul 2020 14:43:18 +0000`

2.パスワード再設定フォームから有効なメールアドレスを送信してみましょう。また、Railsサーバーのログを見て、生成された送信メールの内容を確認してみてください。

```
    <h1>Password reset</h1>

<p>To reset your password click the link below:</p>

<a href="https://f85f995d89d545089c7ba0ef0e279d4c.vfs.cloud9.ap-northeast-1.amazonaws.com/password_resets/IcIj_J0Zlrd0_hygj_87Nw/edit?email=example%40railstutorial.org">Reset password</a>

<p>This link will expire in two hours.</p>

<p>
If you did not request your password to be reset, please ignore this email and
your password will stay as it is.
</p>
  </body>
```

3.コンソールに移り、先ほどの演習課題でパスワード再設定をしたUserオブジェクトを探してください。オブジェクトを見つけたら、そのオブジェクトが持つreset_digestとreset_sent_atの値を確認してみましょう。

```
>> user = User.find_by(id:1)
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
=> #<User id: 1, name: "Example User", email: "example@railstutorial.org", created_at: "2020-07-18 13:20:13", updated_at: "2020-07-23 14:41:35", password_digest: "$2a$10$9v5S4oJk16x9pfbMXkf/ievaQhPA50XBMqFztNrZnqj...", remember_digest: nil, admin: true, activation_digest: "$2a$10$OBqUPKe0HwaDUBtqARDRzO9NSFaoKAPHmjNzuTvoqz1...", activated: true, activated_at: "2020-07-18 13:20:13", reset_digest: "$2a$10$fAY5aKaX/6mcO7tbFS/AZOWhoYOcj3CgMvjiRgx/AEd...", reset_sent_at: "2020-07-23 14:41:35">
```

1.メイラーのテストだけを実行してみてください。このテストは greenになっているでしょうか?
　GREEN。

2.リスト 12.12にある２つ目のCGI.escapeを削除すると、テストが redになることを確認してみましょう。
　REDになった。

##12.3.1　演習
1.12.2.1.1で示した手順に従って、Railsサーバーのログから送信メールを探し出し、そこに記されているリンクを見つけてください。そのリンクをブラウザから表示してみて、図 12.11のように表示されるか確かめてみましょう
　省略

2.先ほど表示したページから、実際に新しいパスワードを送信してみましょう。どのような結果になるでしょうか?

　Unknown action
　The action 'update' could not be found for PasswordResetsController
　エラーでドキッ！updateアクションまだ書いてないもんね。

##12.3.2　演習
1.12.2.1.1で得られたリンク (Railsサーバーのログから取得) をブラウザで表示し、passwordとconfirmationの文字列をわざと間違えて送信してみましょう。どんなエラーメッセージが表示されるでしょうか?
　`Password confirmation doesn't match Password`

2.コンソールに移り、パスワード再設定を送信したユーザーオブジェクトを見つけてください。見つかったら、そのオブジェクトのpassword_digestの値を取得してみましょう。次に、パスワード再設定フォームから有効なパスワードを入力し、送信してみましょう (図 12.13)。パスワードの再設定は成功したら、再度password_digestの値を取得し、先ほど取得した値と異なっていることを確認してみましょう。ヒント: 新しい値はuser.reloadを通して取得する必要があります。

　`password_digest: "$2a$10$B6393nyZgIhwI4l1sFvZqe7ut877uijFjhDoVSizLdy..."`→
　`password_digest: "$2a$10$qFFzrhOelczLx3DO.2p6quDaFlV5T1ciSrCbDXTe44d..."`

##12.3.3　演習
1.リスト 12.6にあるcreate_reset_digestメソッドはupdate_attributeを２回呼び出していますが、これは各行で１回ずつデータベースへ問い合わせしていることになります。リスト 12.20に記したテンプレートを使って、update_attributeの呼び出しを１回のupdate_columns呼び出しにまとめてみましょう (これでデータベースへの問い合わせが１回で済むようになります)。また、変更後にテストを実行し、 greenになることも確認してください。ちなみにリスト 12.20にあるコードには、前章の演習 (リスト 11.39) の解答も含まれています。
　`update_columns(reset_digest:  User.digest(reset_token), reset_sent_at: Time.zone.now)`

2.リスト 12.21のテンプレートを埋めて、期限切れのパスワード再設定で発生する分岐 (リスト 12.16) を統合テストで網羅してみましょう (12.21 のコードにあるresponse.bodyは、そのページのHTML本文をすべて返すメソッドです)。期限切れをテストする方法はいくつかありますが、リスト 12.21でオススメした手法を使えば、レスポンスの本文に「expired」という語があるかどうかでチェックできます (なお、大文字と小文字は区別されません)。
　`assert_match /expired/i, response.body`

3.２時間経ったらパスワードを再設定できなくする方針は、セキュリティ的に好ましいやり方でしょう。しかし、もっと良くする方法はまだあります。例えば、公共の (または共有された) コンピューターでパスワード再設定が行われた場合を考えてみてください。仮にログアウトして離席したとしても、２時間以内であれば、そのコンピューターの履歴からパスワード再設定フォームを表示させ、パスワードを更新してしまうことができてしまいます (しかもそのままログイン機構まで突破されてしまいます!)。この問題を解決するために、リスト 12.22のコードを追加し、パスワードの再設定に成功したらダイジェストをnilになるように変更してみましょう5 。
　省略

4.リスト 12.18に１行追加し、１つ前の演習課題に対するテストを書いてみましょう。ヒント: リスト 9.25のassert_nilメソッドとリスト 11.33のuser.reloadメソッドを組み合わせて、reset_digest属性を直接テストしてみましょう。
　　`assert_nil user.reload.reset_digest`

##12.4　演習
1.production環境でユーザー登録を試してみましょう。ユーザー登録時に入力したメールアドレスにメールは届きましたか?
　省略
2.メールを受信できたら、実際にメールをクリックしてアカウントを有効化してみましょう。また、Heroku上のログを調べてみて、有効化に関するログがどうなっているのか調べてみてください。ヒント: ターミナルからheroku logsコマンドを実行してみましょう。
　省略
3.アカウントを有効化できたら、今度はパスワードの再設定を試してみましょう。正しくパスワードの再設定ができたでしょうか?
　We're sorry, but something went wrong.
　If you are the application owner check the logs for more information.
　エラーが出てしまった。heroku logsで確認してもエラー確認出来ず。メール送ったことになってる。
　
　`$ heroku run rails db:migrate`をもう一度やってみる。ダメ。
　`$ heroku run rake db:seed`もやってみる。ダメ。
　DBをリセットしてみた。
　やっぱり駄目だった・・・どうして。

　ローカル環境では問題ない、エラーが出るのはメールが送信される時だけなのでSendGrid凍結の疑い。
　[Railsチュートリアル11章 SendGrid 凍結問題を解決する](https://qiita.com/yuppymam/items/50f893df99cfb1683234)
　こちらを参考に新しくデプロイし直ししたら無事解決！また凍結されるかもしれないけれども。
　なんとか無事に12章終わり！

##メモ
- `user.reload`で新しい値を取得できる(Rails console)
-