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

##10.1.1　演習
1.先ほど触れたように、target="_blank"で新しいページを開くときには、セキュリティ上の小さな問題があります。それは、リンク先のサイトがHTMLドキュメントのwindowオブジェクトを扱えてしまう、という点です。具体的には、フィッシング (Phising) サイトのような、悪意のあるコンテンツを導入させられてしまう可能性があります。Gravatarのような著名なサイトではこのような事態は起こらないと思いますが、念のため、このセキュリティ上のリスクも排除しておきましょう。対処方法は、リンク用のaタグのrel (relationship) 属性に、"noopener"と設定するだけです。早速、リスト 10.2で使ったGravatarの編集ページへのリンクにこの設定をしてみましょう。

```ruby:/app/views/users/edit.html.erb
<a href="http://gravatar.com/emails" rel="noopener" target="_blank">change</a>
```

2.リスト 10.5のパーシャルを使って、new.html.erbビュー (リスト 10.6) とedit.html.erbビュー (リスト 10.7) をリファクタリングしてみましょう (コードの重複を取り除いてみましょう)。ヒント: 3.4.3で使ったprovideメソッドを使うと、重複を取り除けます3 。(関連するリスト 7.27の演習課題を既に解いている場合、この演習課題をうまく解けない可能性があります。うまく解けない場合は、既存のコードのどこに差異があるのか考えながらこの課題に取り組んでみましょう。例えば筆者であれば、リスト 10.5で用いた変数を渡すテクニックを使って、リスト 10.6やリスト 10.7で必要になるURLをリスト 10.5に渡してみるでしょう。)

　難しい。<%= form_for(@user, `url: signup_path`) do |f| %>これをnew.html.erbで指定したいというところまでは分かったのだけど。
カンニングしてしまった。[Ruby on Rails チュートリアル 5.0（第4版） 第10章 演習と解答まとめ](https://qiita.com/mochikichi321/items/aba85a9b744803f70078)
new にはsignup_path、editにはuser_pathを渡すために、
<%= form_for(@user, `url: yield(:url)`) do |f| %>を使ってprovideで各々指定できるようにするのね。
見たらなるほどって思うのに。まだまだ勉強。

##10.1.2　演習
1.編集フォームから有効でないユーザー名やメールアドレス、パスワードを使って送信した場合、編集に失敗することを確認してみましょう。
　省略

##10.1.3　演習
1.リスト 10.9のテストに１行追加し、正しい数のエラーメッセージが表示されているかテストしてみましょう。ヒント: 表 5.2で紹介したassert_selectを使ってalertクラスのdivタグを探しだし、「The form contains 4 errors.」というテキストを精査してみましょう。


```ruby:/test/integration/users_edit_test.rb
    assert_template 'users/edit'
    assert_select "div", "The form contains 4 errors."
```

##10.1.4　演習
1.実際に編集が成功するかどうか、有効な情報を送信して確かめてみましょう。
　省略

2.もしGravatarと紐付いていない適当なメールアドレス (foobar@example.comなど) に変更した場合、プロフィール画像はどのように表示されるでしょうか? 実際に編集フォームからメールアドレスを変更して、確認してみましょう。
　初期画像になる

##10.2.1　演習
1.デフォルトのbeforeフィルターは、すべてのアクションに対して制限を加えます。今回のケースだと、ログインページやユーザー登録ページにも制限の範囲が及んでしまうはずです (結果としてテストも失敗するはずです)。リスト 10.15のonly:オプションをコメントアウトしてみて、テストスイートがそのエラーを検知できるかどうか (テストが失敗するかどうか) 確かめてみましょう。
　REDになる。

##10.2.2　演習
1.何故editアクションとupdateアクションを両方とも保護する必要があるのでしょうか? 考えてみてください。
　GETとPATCHのどっちも保護するため。

2.上記のアクションのうち、どちらがブラウザで簡単にテストできるアクションでしょうか?
　GETのeditアクション。

##10.2.3　演習
1.フレンドリーフォワーディングで、渡されたURLに初回のみ転送されていることを、テストを書いて確認してみましょう。次回以降のログインのときには、転送先のURLはデフォルト (プロフィール画面) に戻っている必要があります。ヒント: リスト 10.29のsession[:forwarding_url]が正しい値かどうか確認するテストを追加してみましょう。

　正直まったく分からなかった。もう一度LOGOUTしてLOGINしなおして、ってテストを書こうとしていた。
　カンニングした結果、正しい値かテストして、redirectした後にsession[:forwarding_url]がnilになってることを確認したら良かったのね。
　テスト読めるようになってきたけど、書くのはまだまだ難しい。

2.7.1.3で紹介したdebuggerメソッドをSessionsコントローラのnewアクションに置いてみましょう。その後、ログアウトして /users/1/edit にアクセスしてみてください (デバッガーが途中で処理を止めるはずです)。ここでコンソールに移り、session[:forwarding_url]の値が正しいかどうか確認してみましょう。また、newアクションにアクセスしたときのrequest.get?の値も確認してみましょう (デバッガーを使っていると、ときどき予期せぬ箇所でターミナルが止まったり、おかしい挙動を見せたりします。熟練の開発者になった気になって (コラム 1.1)、落ち着いて対処してみましょう)。

```
(byebug) session[:forwarding_url]
"https://f85f995d89d545089c7ba0ef0e279d4c.vfs.cloud9.ap-northeast-1.amazonaws.com/users/1/edit"
(byebug) request.get?
true
```

##10.3.2　演習
1.レイアウトにあるすべてのリンクに対して統合テストを書いてみましょう。ログイン済みユーザーとそうでないユーザーのそれぞれに対して、正しい振る舞いを考えてください。ヒント: log_in_asヘルパーを使ってリスト 5.32にテストを追加してみましょう。

`http://localhost:3000/rails/info/routes`　ここでrootの確認が出来た。

```
  def setup
    @user = users(:michael)
  end

  test "login layout links" do
    log_in_as(@user)
    get user_path(@user)
    assert_template 'users/show'
    assert_select "a[href=?]", root_path, count: 2
    assert_select "a[href=?]", help_path
    assert_select "a[href=?]", users_path
    assert_select "a[href=?]", user_path
    assert_select "a[href=?]", edit_user_path
    assert_select "a[href=?]", logout_path
    assert_select "a[href=?]", about_path
    assert_select "a[href=?]", contact_path
  end
```

##10.43でエラー。
rails db:migrate:resetが出来ない。
[【Ruby on rails】rails db:migrate:resetコマンドでFATAL: Listen error: unable to monitor directories for changes.と表示される。【Rails tutorial】](https://qiita.com/taraka/items/68cc0c75724784b28d91)
こちらを参考に。無事にリセット出来た。

##10.3.2　演習
1.試しに他人の編集ページにアクセスしてみて、10.2.2で実装したようにリダイレクトされるかどうかを確かめてみましょう。
　省略

##10.3.3　演習
1.Railsコンソールを開き、pageオプションにnilをセットして実行すると、１ページ目のユーザーが取得できることを確認してみましょう。

```
>> User.paginate(page: nil)
  User Load (0.9ms)  SELECT  "users".* FROM "users" LIMIT ? OFFSET ?  [["LIMIT", 11], ["OFFSET", 0]]
   (0.1ms)  SELECT COUNT(*) FROM "users"
=> #<ActiveRecord::Relation [#<User id: 1, name: "Example User", email: "example@railstutorial.org", created_at: "2020-07-17 15:51:35", updated_at: "2020-07-17 15:51:35", password_digest: "$2a$10$AuTCwuUNnCZuTNwRbrsVSesT/amD5udXECfFwLukAO/...", remember_digest: nil>, #<User id: 2, name: "Bryce Ankunding", email: "example-1@railstutorial.org", created_at: "2020-07-17 15:51:35", updated_at: "2020-07-17 15:51:35", password_digest: "$2a$10$5p89xzKXEVzaZcRw8u6zq.NfcrKzdxNx1nK7lp6TnsD...", remember_digest: nil>, #<User id: 3, name: "Orion Nienow", email: "example-2@railstutorial.org", created_at: "2020-07-17 15:51:35", updated_at: "2020-07-17 15:51:35", password_digest: "$2a$10$Q4mnCkDQUEgTIY8axp9eb.7NB7tTp/Em7G9xzp3oGIG...", remember_digest: nil>, #<User id: 4, name: "Kaden Schmidt", email: "example-3@railstutorial.org", created_at: "2020-07-17 15:51:36", updated_at: "2020-07-17 15:51:36", password_digest: "$2a$10$JpUu/kJRq3MNoj3XXJR.OOIekw9evjNdcqWh51ADZd1...", remember_digest: nil>, #<User id: 5, name: "Raphaelle Eichmann", email: "example-4@railstutorial.org", created_at: "2020-07-17 15:51:36", updated_at: "2020-07-17 15:51:36", password_digest: "$2a$10$2Ss/AtQAM1tFCBCUa3JHcewK7WpyRrQ5B3ItLQu8OOM...", remember_digest: nil>, #<User id: 6, name: "Amalia Weissnat DDS", email: "example-5@railstutorial.org", created_at: "2020-07-17 15:51:36", updated_at: "2020-07-17 15:51:36", password_digest: "$2a$10$lI1EozhueJiMP3H5DCyO4ucanx8utEYlCHiEiJfuYoz...", remember_digest: nil>, #<User id: 7, name: "Nathanial  rona", email: "example-6@railstutorial.org", created_at: "2020-07-17 15:51:36", updated_at: "2020-07-17 15:51:36", password_digest: "$2a$10$TQ6PJpwVOUDRYvaCpBPcfOW9/8khYAu.1EJ2wvRaNkR...", remember_digest: nil>, #<User id: 8, name: "Alessandro Turner", email: "example-7@railstutorial.org", created_at: "2020-07-17 15:51:36", updated_at: "2020-07-17 15:51:36", password_digest: "$2a$10$m8Sv9OMmkvN0JdLfYAliH.BmAfJrNF1OoVP.gg/RG0O...", remember_digest: nil>, #<User id: 9, name: "Dee Johnson", email: "example-8@railstutorial.org", created_at: "2020-07-17 15:51:36", updated_at: "2020-07-17 15:51:36", password_digest: "$2a$10$MYmPLUp7jYGpsMLFG0EbBO4stFAzZpvtH7EDysRY6Qd...", remember_digest: nil>, #<User id: 10, name: "Lois Runte I", email: "example-9@railstutorial.org", created_at: "2020-07-17 15:51:36", updated_at: "2020-07-17 15:51:36", password_digest: "$2a$10$hrBZ3A2SP.FDizGg32uMHOXHx64tfC7uZ9VblXHrjIZ...", remember_digest: nil>, ...]>
```

2.先ほどの演習課題で取得したpaginationオブジェクトは、何クラスでしょうか? また、User.allのクラスとどこが違うでしょうか? 比較してみてください。

```
>> User.paginate(page: 1).class
=> User::ActiveRecord_Relation
>> User.all.class
=> User::ActiveRecord_Relation
```

##10.48でエラー。
GREENになるはずのテストがRED。
NoMethodError: undefined method 'paginate'とのこと。
[RAILS_ENV=test時のみ、paginateメソッドがundefinedになる](https://teratail.com/questions/139648)同じ症状の人がいたので。
`bundle`→`spring stop`したらGREENになった。良かった。

##10.3.4　演習
1.試しにリスト 10.45にあるページネーションのリンク (will_paginateの部分) を２つともコメントアウトしてみて、リスト 10.48のテストが redに変わるかどうか確かめてみましょう。
　RED。

2.先ほどは２つともコメントアウトしましたが、１つだけコメントアウトした場合、テストが greenのままであることを確認してみましょう。will_paginateのリンクが２つとも存在していることをテストしたい場合は、どのようなテストを追加すれば良いでしょうか? ヒント: 表 5.2を参考にして、数をカウントするテストを追加してみましょう。

```ruby:/test/integration/users_index_test.rb
assert_select 'div.pagination', count: 2
```

##10.3.5　演習
1.リスト 10.52にあるrenderの行をコメントアウトし、テストの結果が redに変わることを確認してみましょう。
　RED。

##10.4.1　演習
1.Web経由でadmin属性を変更できないことを確認してみましょう。具体的には、リスト 10.56に示したように、PATCHを直接ユーザーのURL (/users/:id) に送信するテストを作成してみてください。テストが正しい振る舞いをしているかどうか確信を得るために、まずはadminをuser_paramsメソッド内の許可されたパラメータ一覧に追加するところから始めてみましょう。最初のテストの結果は redになるはずです。

　`admin: true `以外の部分が全く分からず。またしてもカンニング。情けない。
　理解するのがかなり難しくなってきてしまった。

##10.4.2　演習
1.管理者ユーザーとしてログインし、試しにサンプルユーザを２〜３人削除してみましょう。ユーザーを削除すると、Railsサーバーのログにはどのような情報が表示されるでしょうか?

```
DELETE FROM "users" WHERE "users"."id" = ?  [["id", 2]]
```

##10.4.3　演習
1.試しにリスト 10.59にある管理者ユーザーのbeforeフィルターをコメントアウトしてみて、テストの結果が redに変わることを確認してみましょう。
　RED。

##メモ
- Railsは、`form_for(@user)`を使ってフォームを構成すると、`@user.new_record?`が`true`のときには`POST`を、`false`のときには`PATCH`を使う。
- `before`フィルターを使うと、特定のアクションが実行される直前にメソッドを呼び出すことができる。
- `boolean型`の`admin属性`をUserモデルに追加すると、`admin?`という論理オブジェクトを返すメソッドが自動的に追加される。
- `rails db:seed`コマンドは、`db/seeds.rb`にあるサンプルデータをデータベースに流し込む。