Railsチュートリアル 第2章 - Toyアプリケーション - ユーザーページの挙動

# 前提

[Railsチュートリアル 第2章 - Toyアプリケーション - アプリケーションの起動まで](https://qiita.com/rapidliner00/items/b5bb4f0309e071b1b4cb)からの続きです。

ホストは以下の状態であることを前提としています。

```:zsh
>>> pwd
~/docker/rails_tutorial_test/toy_app
```

Rails用のDockerコンテナが実行されており、以下の状態であることを前提としています。

```:bash
# pwd
/var/www/toy_app

# rails server
=> Booting Puma
=> Rails 5.1.6 application starting in development 
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.9.1 (ruby 2.5.1-p57), codename: Private Caller
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://0.0.0.0:3000
Use Ctrl-C to stop

{この時点の状態}
```

# `/users`を開く

一方で、`/users`を開いたときの表示内容は以下になります。

<img width="866" alt="スクリーンショット 2019-07-31 6.02.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/d70528d9-2bc6-c322-ecee-f94f600dd145.png">

「/users」を開いたとき、`rails server`は以下のメッセージを返しました。

```
Started GET "/users" for 172.17.0.1 at 2019-07-30 21:01:50 +0000
Cannot render console from 172.17.0.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by UsersController#index as HTML
  Rendering users/index.html.erb within layouts/application
  User Load (1.8ms)  SELECT "users".* FROM "users"
  Rendered users/index.html.erb within layouts/application (34.0ms)
Completed 200 OK in 1920ms (Views: 1849.9ms | ActiveRecord: 9.3ms)
```


データベース関連のメッセージがあるのは特筆すべき点です。

# `/users/new`を開く

さらに、「/users/new」を開いたときの表示内容は以下になります。

<img width="866" alt="スクリーンショット 2019-07-31 6.03.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/ace5e858-2c98-4a69-b240-1aaa9f924f28.png">

「/users/new」を開いたとき、`rails server`は以下のメッセージを返しました。

```
Started GET "/users/new" for 172.17.0.1 at 2019-07-30 21:03:16 +0000
Cannot render console from 172.17.0.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by UsersController#new as HTML
  Rendering users/new.html.erb within layouts/application
  Rendered users/_form.html.erb (75.2ms)
  Rendered users/new.html.erb within layouts/application (102.6ms)
Completed 200 OK in 421ms (Views: 364.0ms | ActiveRecord: 12.9ms)
```

# 実際にユーザーを追加する

Railsチュートリアル公式に倣って、名前を「Michael Hartl」、メールアドレスを「michael@example.com」としてユーザーを追加してみます。

<img width="866" alt="スクリーンショット 2019-07-31 6.10.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/57e1e823-7328-5a59-9cae-8ae8066ff48b.png">

「Create User」ボタンをクリック。

<img width="866" alt="スクリーンショット 2019-07-31 6.10.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/842ac510-2bc6-edf3-8674-7312600f3522.png">

「Create User」ボタンをクリックしてからの一連の処理で、`rails server`は以下のメッセージを返しました。

```
Started POST "/users" for 172.17.0.1 at 2019-07-30 21:10:39 +0000
Cannot render console from 172.17.0.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by UsersController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"略", "user"=>{"name"=>"Michael Hartl", "email"=>"michael@example.com"}, "commit"=>"Create User"}
   (0.1ms)  begin transaction
  SQL (22.7ms)  INSERT INTO "users" ("name", "email", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["name", "Michael Hartl"], ["email", "michael@example.com"], ["created_at", "2019-07-30 21:10:39.419769"], ["updated_at", "2019-07-30 21:10:39.419769"]]
   (16.9ms)  commit transaction
Redirected to http://localhost:8080/users/1
Completed 302 Found in 67ms (ActiveRecord: 39.8ms)

Started GET "/users/1" for 172.17.0.1 at 2019-07-30 21:10:39 +0000
Cannot render console from 172.17.0.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by UsersController#show as HTML
  Parameters: {"id"=>"1"}
  User Load (6.4ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  Rendering users/show.html.erb within layouts/application
  Rendered users/show.html.erb within layouts/application (3.4ms)
Completed 200 OK in 313ms (Views: 219.8ms | ActiveRecord: 6.4ms)
```

このメッセージでは、以下に示す点がポイントであろうと思います。

* `GET`ではなく`POST`が呼ばれていること
* `authenticity_token`が送信されていること
* `POST`では`UsersController#create`が呼ばれていること
  * `transaction`という語が出てきていること
  * データベースの`INSERT`が呼ばれていること
* `POST`からの一連の処理の最後が`302 Found`で終わっていること
  * リダイレクト先が`/users/1`であること
* `GET "/users/1"`での一連の処理
  * データベースの`SELECT`が呼ばれていること
  * 最後は`200 OK`で終わっていること

# `/users/1/edit`（今追加したユーザーの登録情報を編集する）を開く

<img width="866" alt="スクリーンショット 2019-07-31 18.27.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/a35cb1f8-fe29-d752-612f-ba36987ea20b.png">

`rails server`は以下のメッセージを返しました。

```
Started GET "/users/1/edit" for 172.17.0.1 at 2019-07-31 09:26:19 +0000
Cannot render console from 172.17.0.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by UsersController#edit as HTML
  Parameters: {"id"=>"1"}
  User Load (3.9ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  Rendering users/edit.html.erb within layouts/application
  Rendered users/_form.html.erb (2.6ms)
  Rendered users/edit.html.erb within layouts/application (27.9ms)
Completed 200 OK in 321ms (Views: 282.4ms | ActiveRecord: 3.9ms)
```

Michael Hartlさんのメールアドレスをmichael@example.comからmichael@example.orgに変更してみました。このとき、`rails server`は以下のメッセージを返しました。

```
Started PATCH "/users/1" for 172.17.0.1 at 2019-07-31 09:30:00 +0000
Cannot render console from 172.17.0.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by UsersController#update as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"略", "user"=>{"name"=>"Michael Hartl", "email"=>"michael@example.org"}, "commit"=>"Update User", "id"=>"1"}
  User Load (5.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
   (0.1ms)  begin transaction
  SQL (20.6ms)  UPDATE "users" SET "email" = ?, "updated_at" = ? WHERE "users"."id" = ?  [["email", "michael@example.org"], ["updated_at", "2019-07-31 09:30:00.394432"], ["id", 1]]
   (12.7ms)  commit transaction
Redirected to http://localhost:8080/users/1
Completed 302 Found in 66ms (ActiveRecord: 38.8ms)


Started GET "/users/1" for 172.17.0.1 at 2019-07-31 09:30:00 +0000
Cannot render console from 172.17.0.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by UsersController#show as HTML
  Parameters: {"id"=>"1"}
  User Load (5.8ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  Rendering users/show.html.erb within layouts/application
  Rendered users/show.html.erb within layouts/application (1.0ms)
Completed 200 OK in 297ms (Views: 261.7ms | ActiveRecord: 5.8ms)
```

このメッセージでは、以下に示す点がポイントであろうと思います。

* `GET`ではなく`PATCH`が呼ばれていること
* `authenticity_token`が送信されていること
* `POST`では`UsersController#update`が呼ばれていること
  * `transaction`という語が出てきていること
  * データベースの`SELECT`次いで`UPDATE`が呼ばれていること
  * `SELECT`でトランザクション処理が開始され、`UPDATE`でトランザクションがコミットされていること
* `PATCH`からの一連の処理の最後が`302 Found`で終わっていること
  * リダイレクト先が`/users/1`であること
* `GET "/users/1"`での一連の処理
  * データベースの`SELECT`が呼ばれていること
  * 最後は`200 OK`で終わっていること

# ユーザーを削除する

この状態から、さらに新しいユーザー情報を作成しました。下掲スクリーンショットの「Foo Bar」というユーザーがそれです。

<img width="866" alt="スクリーンショット 2019-07-31 21.57.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/cb4d65c7-8ce0-90a3-9986-7f72743a845b.png">

Foo Barさんをdestroyしてみます。

<img width="866" alt="スクリーンショット 2019-07-31 21.59.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/e8fa420e-b7c5-5bfe-40ea-1ad5738062b2.png">

無事destroyできたようです。指定ユーザーが削除されました。この処理において、`rails server`は以下のメッセージを返しています。

```
Started DELETE "/users/2" for 172.17.0.1 at 2019-07-31 12:59:18 +0000
Cannot render console from 172.17.0.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by UsersController#destroy as HTML
  Parameters: {"authenticity_token"=>"略", "id"=>"2"}
  User Load (4.8ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 2], ["LIMIT", 1]]
   (0.3ms)  begin transaction
  SQL (15.2ms)  DELETE FROM "users" WHERE "users"."id" = ?  [["id", 2]]
   (12.2ms)  commit transaction
Redirected to http://localhost:8080/users
Completed 302 Found in 49ms (ActiveRecord: 32.4ms)


Started GET "/users" for 172.17.0.1 at 2019-07-31 12:59:18 +0000
Cannot render console from 172.17.0.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by UsersController#index as HTML
  Rendering users/index.html.erb within layouts/application
  User Load (4.8ms)  SELECT "users".* FROM "users"
  Rendered users/index.html.erb within layouts/application (8.7ms)
Completed 200 OK in 288ms (Views: 248.7ms | ActiveRecord: 4.8ms)
```

このメッセージでは、以下に示す点がポイントであろうと思います。

* `GET`ではなく`DELETE`が呼ばれていること
* `authenticity_token`が送信されていること
* `DELETE`では`UsersController#destroy`が呼ばれていること
  * `transaction`という語が出てきていること
  * データベースの`SELECT`次いで`DELETE`が呼ばれていること
  * `SELECT`でトランザクション処理が開始され、`DELETE`でトランザクションがコミットされていること
* `DELETE`からの一連の処理の最後が`302 Found`で終わっていること
  * リダイレクト先が`/users`であること
* `GET "/users"`での一連の処理
  * データベースの`SELECT`が呼ばれていること
  * 最後は`200 OK`で終わっていること

# 演習 - ユーザーページ

## 1. CSSを知っている読者へ: 新しいユーザーを作成し、ブラウザのHTMLインスペクター機能を使って「User was successfully created.」の箇所を調べてみてください。ブラウザをリロードすると、その箇所はどうなるでしょうか?

ユーザー追加直後の時点で、"User was successfully created."と表示されている部分は、`p#notice`というブロックに含まれています。`notice`というid属性が付与されたp要素ですね。

<img width="846" alt="スクリーンショット 2019-08-01 5.55.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/fd3865f1-5ed5-2410-796a-b725e315716d.png">

この時点で`p#notice`に適用されているCSSは、DOMインスペクタによると以下のとおりです。

```css:p#notice
#notice {
    color: green;
}
p, ol, ul, td {
    font-family: verdana, arial, helvetica, sans-serif;
    font-size: 13px;
    line-height: 18px;
}
```

ここで[F5]キーを押し、ブラウザをリロードします。

リロード後にDOMインスペクタでHTMLソースを見ると、`<p id="notice"></p>`という行はありました。しかし、内容は空ですね。リロード後のスクリーンショットは以下です。

<img width="846" alt="スクリーンショット 2019-08-01 6.23.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/ff3f8761-60a6-1aa8-7b53-955efd92b6fb.png">

上述スクリーンショットの通り、`p#notice`は高さ0ピクセルとしてレンダリングされています。CSSにも、上述`p#notice`に適用するスタイルの定義自体は残っています。

## 2. emailを入力せず、名前だけを入力しようとした場合、どうなるでしょうか?

<img width="846" alt="スクリーンショット 2019-08-01 6.31.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/d3852ddf-da49-2177-4c79-9a2ce5d8bf66.png">

「Name」欄には「Hogera」と入力します。「Email」欄には何も入力しません。この状態で、「Create User」ボタンをクリックします。

<img width="846" alt="スクリーンショット 2019-08-01 6.32.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/f7847630-2ecf-8392-d7b8-886fcf293db7.png">

正常にユーザーデータの作成が完了したようですね。`rails server`はどんなメッセージを返したか確認してみましょう。

```
Started POST "/users" for 172.17.0.1 at 2019-07-31 21:31:28 +0000
Cannot render console from 172.17.0.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by UsersController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"略", "user"=>{"name"=>"Hogera", "email"=>""}, "commit"=>"Create User"}
   (0.1ms)  begin transaction
  SQL (16.8ms)  INSERT INTO "users" ("name", "email", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["name", "Hogera"], ["email", ""], ["created_at", "2019-07-31 21:31:28.223315"], ["updated_at", "2019-07-31 21:31:28.223315"]]
   (13.9ms)  commit transaction
Redirected to http://localhost:8080/users/4
Completed 302 Found in 40ms (ActiveRecord: 30.8ms)
```

`email`属性を空文字としてSQLの`INSERT`文が発行されているようです。

## 3. 「@example.com」のような間違ったメールアドレスを入力して更新しようとした場合、どうなるでしょうか?

まず、先程作成したユーザー「Hogera」さんのユーザー情報編集画面に入ります。`id=4`として追加されたので、`/users/4/edit`というURLから編集画面に入ることができます。

<img width="846" alt="スクリーンショット 2019-08-01 6.38.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/c6d0ebc5-3fb7-866d-d875-41a4fb79b897.png">

Email欄を「`＠example.com`」として「Update User」ボタンをクリックします。

<img width="846" alt="スクリーンショット 2019-08-01 6.43.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/075eb318-b19c-e57a-4e4a-693c0e9ad4ea.png">

ユーザー情報の編集は正常に完了したようです。`rails server`はどんなメッセージを返したか確認してみましょう。

```
Started PATCH "/users/4" for 172.17.0.1 at 2019-07-31 21:42:58 +0000
Cannot render console from 172.17.0.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by UsersController#update as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"R42TG5sbrRir7Uh87igXEQWRSbuve9yG7oT3WxoX/OShoA5xFihYZMM6YRj98TGwGSvLycHG9HuXlRpNj+gpag==", "user"=>{"name"=>"Hogera", "email"=>"＠example.com"}, "commit"=>"Update User", "id"=>"4"}
  User Load (3.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 4], ["LIMIT", 1]]
   (0.1ms)  begin transaction
  SQL (13.0ms)  UPDATE "users" SET "email" = ?, "updated_at" = ? WHERE "users"."id" = ?  [["email", "＠example.com"], ["updated_at", "2019-07-31 21:42:58.424201"], ["id", 4]]
   (12.6ms)  commit transaction
Redirected to http://localhost:8080/users/4
Completed 302 Found in 50ms (ActiveRecord: 29.0ms)
```

処理内容は、先程Michael Hartlさんのメールアドレスを編集したときと変わりません（もちろん対象する`id`は異なります）。

## 4. 上記の演習で作成したユーザーを削除してみてください。ユーザーを削除したとき、Railsはどんなメッセージを表示するでしょうか?

演習の3.が完了した時点での`toy_app`のユーザー一覧です。`Name`がHogera、`Email`が@example.comというユーザーも存在しますね。

<img width="846" alt="スクリーンショット 2019-08-01 6.46.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/31cb590c-a52d-ce97-d1b8-3e2d1e057f94.png">

では、`Name`がHogera、`Email`が@example.comというユーザーをDestroyしてみましょう。

<img width="846" alt="スクリーンショット 2019-08-01 6.48.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/6190d51a-d148-f684-3537-a8f50cd2a5ce.png">

正常にDestroyできたようです。ブラウザ画面には、"User was successfully destroyed."と表示されています。`rails server`はどんなメッセージを返したか確認してみましょう。

```
Started DELETE "/users/4" for 172.17.0.1 at 2019-07-31 21:48:26 +0000
Cannot render console from 172.17.0.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by UsersController#destroy as HTML
  Parameters: {"authenticity_token"=>"略", "id"=>"4"}
  User Load (3.4ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 4], ["LIMIT", 1]]
   (0.1ms)  begin transaction
  SQL (13.5ms)  DELETE FROM "users" WHERE "users"."id" = ?  [["id", 4]]
   (13.2ms)  commit transaction
Redirected to http://localhost:8080/users
Completed 302 Found in 46ms (ActiveRecord: 30.3ms)
```

処理内容は、先程Foo Barさんのユーザーデータを削除したときと変わりません（もちろん対象する`id`は異なります）。