(ギリ)20代の地方公務員がRailsチュートリアルに取り組みます【第7章】

##前提
・Railsチュートリアルは第4版
・今回の学習は3周目（9章以降は2周目）
・著者はProgate一通りやったぐらいの初学者
##基本方針
・読んだら分かることは端折る。
・意味がわからない用語は調べてまとめる（記事最下段・用語集）。
・理解できない内容を掘り下げる。
・演習はすべて取り組む。
・コードコピペは極力しない。

第7章はログインと認証システムの開発・第２段回目、ユーザー登録機能を追加していきます。

雨が激しい昼刻（執筆時）、本日のBGMはこちらです。
[羊文学 "Blue.ep"](https://www.youtube.com/watch?v=vB5FmGDw1E4&t=1601s)
再び羊文学。最近のお気に入り。一曲目の「雨」、いいかんじです。

　
####【7.1.1　デバッグとRails環境　演習】
1.　ブラウザから /about にアクセスし、デバッグ情報が表示されていることを確認してください。このページを表示するとき、どのコントローラとアクションが使われていたでしょうか? paramsの内容から確認してみましょう。
→　controller: static_pages
　　action: about

　
2.　Railsコンソールを開き、データベースから最初のユーザー情報を取得し、変数userに格納してください。その後、puts user.attributes.to_yamlを実行すると何が表示されますか? ここで表示された結果と、yメソッドを使ったy user.attributesの実行結果を比較してみましょう。
→　下記。この書き方がYAMLということ。結果は一緒です。

```
>> user = User.first
  User Load (0.6ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> #<User id: 1, name: "nakamura", email: "mhartl@example.com", created_at: "2020-09-10 02:37:56", updated_at: "2020-09-10 03:07:11", password_digest: "$2a$10$A5n.HFBigQfwnWVJZw2N0e4M9sxPaR8ndLZwqtZWYS7...">

>> puts user.attributes.to_yaml
---
id: 1
name: nakamura
email: mhartl@example.com
created_at: !ruby/object:ActiveSupport::TimeWithZone
  utc: &1 2020-09-10 02:37:56.040628000 Z
  zone: &2 !ruby/object:ActiveSupport::TimeZone
    name: Etc/UTC
  time: *1
updated_at: !ruby/object:ActiveSupport::TimeWithZone
  utc: &3 2020-09-10 03:07:11.190666000 Z
  zone: *2
  time: *3
password_digest: "$2a$10$A5n.HFBigQfwnWVJZw2N0e4M9sxPaR8ndLZwqtZWYS7gJGH/Ulohe"
=> nil

>> y user.attributes
---
id: 1
name: nakamura
email: mhartl@example.com
created_at: !ruby/object:ActiveSupport::TimeWithZone
  utc: &1 2020-09-10 02:37:56.040628000 Z
  zone: &2 !ruby/object:ActiveSupport::TimeZone
    name: Etc/UTC
  time: *1
updated_at: !ruby/object:ActiveSupport::TimeWithZone
  utc: &3 2020-09-10 03:07:11.190666000 Z
  zone: *2
  time: *3
password_digest: "$2a$10$A5n.HFBigQfwnWVJZw2N0e4M9sxPaR8ndLZwqtZWYS7gJGH/Ulohe"
=> nil
```


　
####【7.1.2　Usersリソース　演習】
1.　埋め込みRubyを使って、マジックカラム (created_atとupdated_at) の値をshowページに表示してみましょう (リスト 7.4)。
2.　埋め込みRubyを使って、Time.nowの結果をshowページに表示してみましょう。ページを更新すると、その結果はどう変わっていますか? 確認してみてください。
→　まとめてドン！（くっついて表示されるのがうっとうしかったのでpタグで改行してます）　ページ更新すると現時刻が更新されて表示されます。

```ruby:show.html.erb
<p>
  <%= @user.name %>, <%= @user.email %>
</p>
<p>
  <%= @user.created_at %>, <%= @user.updated_at %>
</p>
<p>
  <%= Time.now %>
</p>
```


　
####【7.1.3　debuggerメソッド　メモと演習】
　よく分からない挙動があったら、トラブルが起こっていそうなコードの近くにdebeggerを差し込もう！

1.　showアクションの中にdebuggerを差し込み (リスト 7.6)、ブラウザから /users/1 にアクセスしてみましょう。その後コンソールに移り、putsメソッドを使ってparamsハッシュの中身をYAML形式で表示してみましょう。ヒント: 7.1.1.1の演習を参考にしてください。その演習ではdebugメソッドで表示したデバッグ情報を、どのようにしてYAML形式で表示していたでしょうか?
→　下記

```
(byebug) puts @user.attributes.to_yaml
---
id: 1
name: nakamura
email: mhartl@example.com
created_at: !ruby/object:ActiveSupport::TimeWithZone
  utc: &1 2020-09-10 02:37:56.040628000 Z
  zone: &2 !ruby/object:ActiveSupport::TimeZone
    name: Etc/UTC
  time: *1
updated_at: !ruby/object:ActiveSupport::TimeWithZone
  utc: &3 2020-09-10 03:07:11.190666000 Z
  zone: *2
  time: *3
password_digest: "$2a$10$A5n.HFBigQfwnWVJZw2N0e4M9sxPaR8ndLZwqtZWYS7gJGH/Ulohe"
nil
```

　
2.　newアクションの中にdebuggerを差し込み、/users/new にアクセスしてみましょう。@userの内容はどのようになっているでしょうか? 確認してみてください。
→　下記

```
(byebug) @user
Started GET "/users/new" for 49.104.6.138 at 2020-09-10 06:51:27 +0000
#<User id: 1, name: "nakamura", email: "mhartl@example.com", created_at: "2020-09-10 02:37:56", updated_at: "2020-09-10 03:07:11", password_digest: "$2a$10$A5n.HFBigQfwnWVJZw2N0e4M9sxPaR8ndLZwqtZWYS7...">
```

　
####【7.1.4　Gravatar画像とサイドバー　演習】
　ここでエラーが。Gravatarの画像が表示されない。念のため手書きしたコードをコピペで上書きしても表示されない。ということは…。
　SCSSでdisplay: none;でもしてたか？と思いつつ、検索してみるとやっぱり。第5章の演習で画像を消したときのが残ってました。kittenの仕業じゃ！！でも可愛いから許す！！imgタグのコードを消したら解決しました。

1.　(任意) Gravatar上にアカウントを作成し、あなたのメールアドレスと適当な画像を紐付けてみてください。メールアドレスをMD5ハッシュ化して、紐付けた画像がちゃんと表示されるかどうか試してみましょう。
→　画像登録して、コンソールで新しいユーザー作ったら表示されました。
![gravatar.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680946/5dc09e5f-5e9e-de9c-7b98-dcb43afca9e8.png)

　
2.　7.1.4で定義したgravatar_forヘルパーをリスト 7.12のように変更して、sizeをオプション引数として受け取れるようにしてみましょう。うまく変更できると、gravatar_for user, size: 50といった呼び出し方ができるようになります。重要: この改善したヘルパーは10.3.1で実際に使います。忘れずに実装しておきましょう。
→　リスト7.12のとおり書くだけ。

　
3.　オプション引数は今でもRubyコミュニティで一般的に使われていますが、Ruby 2.0から導入された新機能「キーワード引数 (Keyword Arguments)」でも実現することができます。先ほど変更したリスト 7.12を、リスト 7.13のように置き換えてもうまく動くことを確認してみましょう。この２つの実装方法はどういった違いがあるのでしょうか? 考えてみてください。
→　んー、いろいろ調べたけど挙動の違いがいまいち分からない。表記を簡潔にできるのがメリットだってのは分かった。それぞれの用語の意味も調べてわかった。

キーワード引数：引数にキーを設定した引数。何を引数に入れてるのか明確。
オプション引数：柔軟にいろいろな値を渡せる。拡張性が高い。が、ゆえに渡す値が増えると後々のメンテが大変に。可読性も下がる。

　んで、キーワード引数は後のバージョンから導入されたということは、コードを簡潔に書くことが目的にあるのか。オプション引数の方の書き方だと、sizeの定義で余分にコード書いてるもんね。そんな回答で良かろうか。


　
####【7.2.1　form_forを使用する　演習】
1.　試しに、リスト 7.15にある:nameを:nomeに置き換えてみましょう。どんなエラーメッセージが表示されるようになりますか?
→　undefined method `nome' for #<User:0x00007f6b8d40b370>
　
2.　試しに、ブロックの変数fをすべてfoobarに置き換えてみて、結果が変わらないことを確認してみてください。確かに結果は変わりませんが、変数名をfoobarとするのはあまり良い変更ではなさそうですね。その理由について考えてみてください。
→　単純に書くのがめんどくさいのと、fはformのfでしょ。脈絡のない単語を使うと読みにくくなる。（証拠は貼ってないけど、わざわざ全部foobarに書き直したよ！）

　
####【7.2.2　フォームHTML　演習】
1.　Learn Enough HTML to Be DangerousではHTMLをすべて手動で書き起こしていますが、なぜformタグを使わなかったのでしょうか? 理由を考えてみてください。
→　読んでへんから知らんけど、入力・送信を使用してないからですって。（そら使わんやろ）

　
####【7.3.2　Strong Parameters　メモと演習】
　7.3.1で出てきたマスアサインメントの脆弱性は[こちらの記事が分かりやすいかも。](https://qiita.com/tbpgr/items/63028f5e19a2d1617e40)

1.　/signup?admin=1 にアクセスし、paramsの中にadmin属性が含まれていることをデバッグ情報から確認してみましょう。
→　これか。
--- !ruby/object:ActionController::Parameters
parameters: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
  admin: '1'
  controller: users
  action: new
permitted: false

　　
####【7.3.3　エラーメッセージ　メモと演習】
empty?メソッド：オブジェクトが空であればtrue、それ以外はfalse
any?メソッド：要素が一つでもあればtrue、ない場合false
pluralizeメソッド：単語の意味は「複数（形）にする」。意味のとおり、来所に与えた引数の整数に基づいて、後に与えた引数の英単語を複数形にしてくれる。

1.　最小文字数を5に変更すると、エラーメッセージも自動的に更新されることを確かめてみましょう。
→　下記。Password is too short (minimum is 5 characters)が表示されます。

```ruby:/models/user.rb
validates :password, presence: true, length: { minimum: 5 }
```

　
2.　未送信のユーザー登録フォーム (図 7.12) のURLと、送信済みのユーザー登録フォーム (図 7.18) のURLを比べてみましょう。なぜURLは違っているのでしょうか? 考えてみてください。
→　送信前：　~/signup　　※ ~はAWSのアドレス
　 送信後：　~/users
　ユーザー登録のためにPOSTリクエストしてるから、usersリソースに応じて/usersに飛んでるって理解でいいかな？（チュートリアル中の表7.1参照）

　
####【7.3.4　失敗時のテスト　メモと演習】
　countメソッドはあらゆるActive Recordクラスで使用可能。
　ここらへんからテストの内容がややこしくなってきます。一つ一つのコードの意味を追っていきましょう。ここの演習はヘビーですが、じっくり考えてみます。（間違っててもご容赦を）

1.　リスト 7.20で実装したエラーメッセージに対するテストを書いてみてください。どのくらい細かくテストするかはお任せします。リスト 7.25にテンプレートを用意しておいたので、参考にしてください。
→　テンプレに従うと、エラーメッセージのCSSidとclassが表示されているかテストするわけだから、該当箇所を下記のとおり書き換えればテストはGREENです。

```ruby:users_signup_test.rb
assert_select 'div#error_explanation'
assert_select 'div.field_with_errors'
```

　
2.　ユーザー登録フォームのURLは /signup ですが、無効なユーザー登録データを送付するとURLが /users に変わってしまいます。これはリスト 5.43で追加した名前付きルート (/signup) と、RESTfulなルーティング (リスト 7.3) のデフォルト設定との差異によって生じた結果です。リスト 7.26とリスト 7.27の内容を参考に、この問題を解決してみてください。うまくいけばどちらのURLも /signup になるはずです。あれ、でもテストは greenのままになっていますね...、なぜでしょうか? (考えてみてください)
→　リスト7.26のルーティング設定によって、登録失敗後に２つの目的地がある状態（URLが/usersと/signup）。それにより、どっちもテストで検知できる状態なので、REDにならない。

　
3.　リスト 7.25のpost部分を変更して、先ほどの演習課題で作った新しいURL (/signup) に合わせてみましょう。また、テストが greenのままになっている点も確認してください。
→　users_pathをsignup_pathに変更。テストで検知するものを変えただけなのでGREENのまま。

```ruby:users_signup_test.rb
  test "invalid signup information" do
    get signup_path
    assert_no_difference 'User.count' do
      post signup_path, params: { user: { name: "",
  # （以下略）
```
　
4.　リスト 7.27のフォームを以前の状態 (リスト 7.20) に戻してみて、テストがやはり greenになっていることを確認してください。これは問題です! なぜなら、現在postが送信されているURLは正しくないのですから。assert_selectを使ったテストをリスト 7.25に追加し、このバグを検知できるようにしてみましょう (テストを追加して redになれば成功です)。その後、変更後のフォーム (リスト 7.27) に戻してみて、テストが green になることを確認してみましょう。ヒント: フォームから送信してテストするのではなく、'form[action="/signup"]'という部分が存在するかどうかに着目してテストしてみましょう。
→　form_for(@user, url: signup_path)から「, url: signup_path」を取り除く。この状態で実際に登録失敗するとURLは/usersに。これじゃダメだよってことで、検知できるように下記の一文をテストに追加。結果はREDに。そこでformの目的地を再び/singupにすべくリスト7.27の状態に戻すと、テストはGREEN。
　理解するのに時間がかかりました。演習２が理解できないと、その続きも理解できませんね。あきらめず理解できるまで調べて考えて解いていきましょう。

```ruby:users_signup_test.rb
assert_select 'form[action="/signup"]'
```

　
####【7.4.1　登録フォームの完成　メモと演習】
　redirect_to @user →　redurect_to user_url(@user)
とRailsfが勝手に解釈して実行してくれる。ここで、redirect_toとrederの違いって何なん？って気になりませんか？気になりますよね。[気になったので調べました。](https://qiita.com/morikuma709/items/e9146465df2d8a094d78)
　redirec_toはURLを指定するため、ルーターをとおす一連の動作を行っているみたいですね。データ更新等がある場合に使用。renderは直でviewを表示していると。データ変更を伴わない単純な処理の場合です。

1.　有効な情報を送信し、ユーザーが実際に作成されたことを、Railsコンソールを使って確認してみましょう。
→　実際の登録画面からユーザー登録し、コンソールで適当にfindすればOK。

2.　リスト 7.28を更新し、redirect_to user_url(@user)とredirect_to @userが同じ結果になることを確認してみましょう。
→　同じ結果になります。
　
####【7.4.2　flash　演習】
1.　コンソールに移り、文字列内の式展開 (4.2.2) でシンボルを呼び出してみましょう。例えば"#{:success}"といったコードを実行すると、どんな値が返ってきますか? 確認してみてください。
→　下記。文字列が返ってきます。

```
>> "#{:success}"
=> "success"
```

　
2.　先ほどの演習で試した結果を参考に、リスト 7.30のflashはどのような結果になるか考えてみてください。
→　いまいち何を求めているのか分からないけど、こういうこと？

```
>> flash = { success: "It worked!", danger: "It failed." }
=> {:success=>"It worked!", :danger=>"It failed."}
>> "#{flash[:success]}"
=> "It worked!"
>> "#{flash[:danger]}"
=> "It failed."
```

　
####【7.4.3　実際のユーザー登録　演習】
1.　Railsコンソールを使って、新しいユーザーが本当に作成されたのかもう一度チェックしてみましょう。結果は、リスト 7.32のようになるはずです。
→　やってみるだけ。

　
2.　自分のメールアドレスでユーザー登録を試してみましょう。既にGravatarに登録している場合、適切な画像が表示されているか確認してみてください。
→　これもやってみるだけ。

　
####【7.4.4　成功時のテスト　演習】
1.　7.4.2で実装したflashに対するテストを書いてみてください。どのくらい細かくテストするかはお任せします。リスト 7.34に最小限のテンプレートを用意しておいたので、参考にしてください (FILL_INの部分を適切なコードに置き換えると完成します)。ちなみに、テキストに対するテストは壊れやすいです。文量の少ないflashのキーであっても、それは同じです。筆者の場合、flashが空でないかをテストするだけの場合が多いです。
→　FILL_INにはempty?メソッドを入れればOK。

2.　本文中でも指摘しましたが、flash用のHTML (リスト 7.31) は読みにくいです。より読みやすくしたリスト 7.35のコードに変更してみましょう。変更が終わったらテストスイートを実行し、正常に動作することを確認してください。なお、このコードでは、Railsのcontent_tagというヘルパーを使っています。
→　指示通り実行。

　
3.　リスト 7.28のリダイレクトの行をコメントアウトすると、テストが失敗することを確認してみましょう。
→　失敗します。

　
4.　リスト 7.28で、@user.saveの部分をfalseに置き換えたとしましょう (バグを埋め込んでしまったと仮定してください)。このとき、assert_differenceのテストではどのようにしてこのバグを検知するでしょうか? テストコードを追って考えてみてください。
→　下記のエラーが。ユーザー数増えてねえよってことか。

```
 "User.count" didn't change by 1.
        Expected: 1
          Actual: 0
```

　
####【7.5.3　成功時のテスト　演習】
1.　ブラウザから本番環境 (Heroku) にアクセスし、SSLの鍵マークがかかっているか、URLがhttpsになっているかどうかを確認してみましょう。
→　鍵かかってました。

　
2.　本番環境でユーザーを作成してみましょう。Gravatarの画像は正しく表示されているでしょうか?
→　表示されてました。

　
###第7章まとめ
・やっぱりSass便利。
・RESTfullなルートと個別設定のルートの違い・使い分けに気をつけよう。
・Gravatarってどこまで一般的なの？wordpressやから普及してるの？
・form_forはform_withに置き換わってるようなので参考までに。
・renderとredirect_toの使い分け。
・flashメッセージを表示。
・Strong　Parametersでマスアサインメントの脆弱性対策。
・SSLでセキュリティ向上。

　
　この章は演習が歯応えありました。なぜそうなるのか、一つ一つのコードと動作を考える必要がありますね。考えることをあきらめずに取り組んでいきましょう。
　次は第8章、ログイン機構を備えていきましょう。

　
⇨　[第8章へ！](https://qiita.com/t-kawamura1/items/78fa212873cb31995358)
⇦　[第6章はこちら](https://qiita.com/t-kawamura1/items/98aa4c06c5630c2eb798)
[学習にあたっての前提・著者ステータスはこちら](https://qiita.com/t-kawamura1/items/9c955177c02871b5249c)
　
####なんとなくイメージを掴む用語集
・assert_difference（assert_no_difference）
　（この章の使い方で想定すると）引数で与えられた数値（結果）が、ブロックの処理を実行する前後で違いがあるかどうかテストする。前者が違いがある、no_differenceは違いがないことを確かめている。

・SSL（Secure Sockets Layer） 
　セキュリティを要求される通信を行うためのプロトコル。現在はTLS（Transport Layer Security）に置き換わっているが、昔の名残でSSLと呼ばれる。