---
# System prepended metadata

title: 7章

---

## 前回の分からなかったこと
テスト駆動開発とは？？？
<u><a href="https://teratail.com/questions/121833" target="_blank">ここ</a></u>を見たが、まあ、経験を踏めばわかってくる概念であり、分かりにくいことが分かった。チュートリアルを通してもっと深く理解していきたい。
　
# 7章
## デバックとrails環境
サイトのレイアウトにデバック情報を追加する。
**app/views/layouts/application.html.erb**

```html
<%= debug(params) if Rails.env.development? %>
```

ビルトインのdebugメソッドとparams変数を使って、各プロフィールページにデバッグ用の情報が表示されるようにする。
**.development?** で、Railsの3つのデフォルト環境のうち、開発環境 (development) だけで表示されるようになる。
　
3つのデフォルト環境の使い分けについてだが、
・普段のrails consoleでは、

```bash
$ rails console
  Loading development environment
  >> Rails.env
  => "development"
  >> Rails.env.development?
  => true
  >> Rails.env.test?
  => false
```

development環境である。
　
・テスト環境のデバッグなど、他の環境でconsoleを実行する必要が生じた場合は、環境をパラメータ(変数)としてconsoleスクリプト(即座に実行できるプログラム)に渡すことができる。

```bash
$ rails console test
  Loading test environment
  >> Rails.env
  => "test"
  >> Rails.env.test?
  => true
```

・Herokuは本番サイト用のプラットフォームなので、実行されるアプリケーションはすべて本番環境となる。


```bash
$ heroku run rails console
  >> Rails.env
  => "production"
  >> Rails.env.production?
  => true
```

詳しくは<u><a href="https://railstutorial.jp/chapters/sign_up?version=5.1#sec-rails_environments" target="_blank">コラム7.1</a></u>を見てください。
　
次にデバック表示を整形する。

**app/assets/stylesheets/custom.scss**

```scss
@import "bootstrap-sprockets";
@import "bootstrap";

/* mixins, variables, etc. */

$gray-medium-light: #eaeaea;

@mixin box_sizing {
  -moz-box-sizing:    border-box;
  -webkit-box-sizing: border-box;
  box-sizing:         border-box;
}
.
.
.
/* miscellaneous */

.debug_dump {
  clear: both;
  float: left;
  width: 100%;
  margin-top: 45px;
  @include box_sizing; /*定義したミックスイン*/
}
```

Sassのミックスインという機能が使われている。パッケージ化して、閣僚を減らす。見やすくする。

表示されたデバック出力には描画されたページの情報が含まれる。この **params** の内容は **YAML** という形式で書かれている。基本的にハッシュで、人間だけではなく、このコンピュータにとっても読みやすい形式。
　
## 演習
1.ブラウザから /about にアクセスし、デバッグ情報が表示されていることを確認してください。このページを表示するとき、どのコントローラとアクションが使われていたでしょうか? paramsの内容から確認してみましょう。
A.
デバック出力は以下のようになる。

```string
--- !ruby/object:ActionController::Parameters
parameters: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
  controller: static_pages
  action: about
  permitted: false
```

static_pagesコントローラのaboutアクションが使われたことが分かる。

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

```bash
user = User.find(1)
  User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
=> #<User id: 1, name: "Takukin", email: "mhartl@example.com", created_at: "2020-01-17 11:27:03", updated_at: "2020-01-18 05:35:38", 
password_digest: "$2a$10$ZhxNCTARw/sPxesOSdbX2.1bQpTioIhOYk6WvXISOUO...">
```

次に、 **puts user.attributes.to_yaml**

```bash
---
id: 1
name: Takukin
email: mhartl@example.com
created_at: !ruby/object:ActiveSupport::TimeWithZone
  utc: &1 2020-01-17 11:27:03.438851000 Z
  zone: &2 !ruby/object:ActiveSupport::TimeZone
    name: Etc/UTC
  time: *1
updated_at: !ruby/object:ActiveSupport::TimeWithZone
  utc: &3 2020-01-18 05:35:38.851927000 Z
  zone: *2
  time: *3
password_digest: "$2a$10$ZhxNCTARw/sPxesOSdbX2.1bQpTioIhOYk6WvXISOUOYSD2o/l/5e"
=> nil
```

次に、 **y user.attributes**

```bash
---
id: 1
name: Takukin
email: mhartl@example.com
created_at: !ruby/object:ActiveSupport::TimeWithZone
  utc: &1 2020-01-17 11:27:03.438851000 Z
  zone: &2 !ruby/object:ActiveSupport::TimeZone
    name: Etc/UTC
  time: *1
updated_at: !ruby/object:ActiveSupport::TimeWithZone
  utc: &3 2020-01-18 05:35:38.851927000 Z
  zone: *2
  time: *3
password_digest: "$2a$10$ZhxNCTARw/sPxesOSdbX2.1bQpTioIhOYk6WvXISOUOYSD2o/l/5e"
=> nil
```

出力結果は、 **puts user.attributes.to_yamlとy user.attributesは一緒。**
　
## Userリソース
データの作成、表示、更新、削除をリソース(Resourceとして扱えるようにする。

**config/routes.rb**

```ruby
resources :users
```

これを **リソースルーティング** と呼ぶらしい。これを使うことによって、コントローラの **index、show、new、edit、create、update、destroyアクション** を個別に宣言しなくても1行で宣言が完了。これにより、今回の場合、 ***/users/1*** にアクセスできる。
しかし、
ルーティングテーブルは作れるが、ジェネレーターを使ってないので、アクションとビューは自分で作らなければならない。
　
まず、 **app/views/users/show.html.erb** にビューファイルを手動で作る。
**app/views/users/show.html.erb**

```html
<%= @user.name %>, <%= @user.email %>
```

　
次に、Userコントローラにshowアクションを定義。
**app/controllers/users_controller.rb**

```ruby
class UsersController < ApplicationController

  def show
    @user = User.find(params[:id])
  end

  def new
  end
end
```

これで、 ***/users/1*** にアクセスできる。
　
## 演習
1.埋め込みRubyを使って、マジックカラム (created_atとupdated_at) の値をshowページに表示してみましょう (リスト 7.4)。
A.
**app/views/users/show.html.erb**

```ruby
<%= @user.name %>, <%= @user.email %>, <%= @user.created_at %>, <%= @user.updated_at %>
```

のように、マジックカラム (created_atとupdated_at)を追加。
　
2.埋め込みRubyを使って、Time.nowの結果をshowページに表示してみましょう。ページを更新すると、その結果はどう変わっていますか? 確認してみてください。 
A.
**app/views/users/show.html.erb**

```ruby
<%= @user.name %>, <%= @user.email %>, <%= @user.created_at %>, <%= @user.updated_at %>, <%= Time.now %>
```

のように、埋め込みRubyでTime.nowを追加。ブラウザを更新した時間が表示される。
　
## debuggerメソッド
もっと直接的にデバックする。 **byebug gemによるdebuggerメソッド**
使い方は直接debuggerをUserコントローラに差し込む。

**app/controllers/users_controller.rb**

```ruby
class UsersController < ApplicationController

  def show
    @user = User.find(params[:id])
    debugger
  end

  def new
  end
end
```

そうして、ブラウザから /users/1 にアクセスし、Railsサーバーを立ち上げたターミナルを見て(byebug)というプロンプトがあれば成功。
ここで、Windows民はエラーを吐くので<u><a href="https://qiita.com/kusano_pg/items/eb38466f70dc05238fdb" target="_blank">ここで改善するとできるよ</a></u>gemのインストール。
　
(byebug)はRailsコンソールのようにコマンドを呼び出すことができて、アプリケーションのdebuggerが呼び出された瞬間の状態を確認することができる。

```bash
(byebug) @user.name
"Takukin"
(byebug) @user.email
"mhartl@example.com"
(byebug) params[:id]
"1"
```


Ctrl-Dを押すとプロンプトから抜け出すことができる。もう必要ないので消しておく。わからないことがあったらdebuggerを差し込んで、アプリケーション内のエラーを追跡したりデバッグするのがコツ。
　　
## 演習
1.showアクションの中にdebuggerを差し込み (リスト 7.6)、ブラウザから /users/1 にアクセスしてみましょう。その後コンソールに移り、putsメソッドを使ってparamsハッシュの中身をYAML形式で表示してみましょう。ヒント: 7.1.1.1の演習を参考にしてください。その演習ではdebugメソッドで表示したデバッグ情報を、どのようにしてYAML形式で表示していたでしょうか? 
A.

```bash
((byebug) puts params.to_yaml
--- !ruby/object:ActionController::Parameters
parameters: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
  controller: users
  action: show
  id: '1'
permitted: false
nil
```

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

**/app/controllers/users_controller.rb**

```ruby
def new
  debugger
end
```

byebugにて

```bash
(byebug) @user
nil
```


となる。
　
## Gravatar画像とサイドバー
**Gravatarとは** ：無料のサービスで、プロフィール写真をアップロードして、指定したメールアドレスと関連付けることができるもの。
　
まずはビューから
**app/views/users/show.html.erb**

```html
<% provide(:title, @user.name) %>
<h1>
  <%= gravatar_for @user %>
  <%= @user.name %>
</h1>
```
　　
次に、ヘルパーメソッドを定義する。ヘルパーファイルのどこでも定義できるが、分かりやすくするため、usersのヘルパーファイルにする。
**app/helpers/users_helper.rb**

```ruby
module UsersHelper

  # 引数で与えられたユーザーのGravatar画像を返す
  def gravatar_for(user)
    gravatar_id = Digest::MD5::hexdigest(user.email.downcase)
    gravatar_url = "https://secure.gravatar.com/avatar/#{gravatar_id}"
    image_tag(gravatar_url, alt: user.name, class: "gravatar")
  end
end
```

gravatar_idの定義はuserのemailをハッシュ化してgravatarのURLで使えるようにし、gravatar_urlで画像を取ってくるイメージ？？
alt属性を入れることでブラウザが読み上げてくれる。
　
　
デフォルトのメールアドレスをコンソール上で変え、デザインも整える。
**rails c**

```bash
$ rails console
>> user = User.first
>> user.update_attributes(name: "Example User",
?>                        email: "example@railstutorial.org",
?>                        password: "foobar",
?>                        password_confirmation: "foobar")
=> true
```


よって。ロゴが変わる。

　
デザインも変える。
**app/views/users/show.html.erb**

```html
<% provide(:title, @user.name) %>
<div class="row">
  <aside class="col-md-4">
    <section class="user_info">
      <h1>
        <%= gravatar_for @user %>
        <%= @user.name %>
      </h1>
    </section>
  </aside>
</div>
```

ここでてくる、 **rowやcol-md-4クラス** はbootstrapで定義されたクラス名。
　
CSSも追加。
**app/assets/stylesheets/custom.scss**

```css
/* sidebar */

aside {
  section.user_info {
    margin-top: 20px;
  }
  section {
    padding: 10px 0;
    margin-top: 20px;
    &:first-child {
      border: 0;
      padding-top: 0;
    }
    span {
      display: block;
      margin-bottom: 3px;
      line-height: 1;
    }
    h1 {
      font-size: 1.4em;
      text-align: left;
      letter-spacing: -1px;
      margin-bottom: 3px;
      margin-top: 0px;
    }
  }
}

.gravatar {
  float: left;
  margin-right: 10px;
}

.gravatar_edit {
  margin-top: 15px;
}
```

　
## 演習
1,(任意) Gravatar上にアカウントを作成し、あなたのメールアドレスと適当な画像を紐付けてみてください。メールアドレスをMD5ハッシュ化して、紐付けた画像がちゃんと表示されるかどうか試してみましょう。 
A.
<u><a href="https://ja.gravatar.com/" target="_blank">Gravatar</a></u>にて、アカウントを作り、プロフィール画像を設定して、rails console上でサンプルデータ(User.first)のメールアドレスを登録したアドレスに変更したらできた。
　
2.7.1.4で定義したgravatar_forヘルパーをリスト 7.12のように変更して、sizeをオプション引数として受け取れるようにしてみましょう。うまく変更できると、gravatar_for user, size: 50といった呼び出し方ができるようになります。重要: この改善したヘルパーは10.3.1で実際に使います。忘れずに実装しておきましょう。
A.
コピペ。
　
3.オプション引数は今でもRubyコミュニティで一般的に使われていますが、Ruby 2.0から導入された新機能「キーワード引数 (Keyword Arguments)」でも実現することができます。先ほど変更したリスト 7.12を、リスト 7.13のように置き換えてもうまく動くことを確認してみましょう。この２つの実装方法はどういった違いがあるのでしょうか? 考えてみてください。 
A.
コピペ。
　
## ユーザ登録フォーム
## form_forを使用する
**form_for** ：ヘルパーメソッド。Active Recordのオブジェクトを取り込み、そのオブジェクトの属性を使ってフォームを構築する。

まずは、newアクションに@user変数を追加。

**app/controllers/users_controller.rb**

```ruby
class UsersController < ApplicationController

  def show
    @user = User.find(params[:id])
  end

  def new
    @user = User.new
  end
end
```

　
次に、HTML、CSSの変更。
**app/views/users/new.html.erb**

```html
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>

<div class="row">
  <div class="col-md-6 col-md-offset-3">
    <%= form_for(@user) do |f| %>
      <%= f.label :name %>
      <%= f.text_field :name %>

      <%= f.label :email %>
      <%= f.email_field :email %>

      <%= f.label :password %>
      <%= f.password_field :password %>

      <%= f.label :password_confirmation, "Confirmation" %>
      <%= f.password_field :password_confirmation %>

      <%= f.submit "Create my account", class: "btn btn-primary" %>
    <% end %>
  </div>
</div>
```

　
CSSに追加。
**app/assets/stylesheets/custom.scss**

```css
/* forms */

input, textarea, select, .uneditable-input {
  border: 1px solid #bbb;
  width: 100%;
  margin-bottom: 15px;
  @include box_sizing;
}

input {
  height: auto !important;
}
```

開設は次のトピックでやるらしい。
　

## 演習
1.試しに、リスト 7.15にある:nameを:nomeに置き換えてみましょう。どんなエラーメッセージが表示されるようになりますか? 
A.
**NoMethodError in Users#new**
**undefined method `nome'**
　
2.試しに、ブロックの変数fをすべてfoobarに置き換えてみて、結果が変わらないことを確認してみてください。確かに結果は変わりませんが、変数名をfoobarとするのはあまり良い変更ではなさそうですね。その理由について考えてみてください。 
A.
結果は変わらない。
メタ構文変数（意味を持たない名前）として認識されるため、日本語では「ほにゃらら」などの意味で、変数名としてふさわしくないため。
　
## フォームHTML
前のHTMLの設定
**app/views/users/new.html.erb**

```html
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>

<div class="row">
  <div class="col-md-6 col-md-offset-3">
    <%= form_for(@user) do |f| %>
      <%= f.label :name %>
      <%= f.text_field :name %>

      <%= f.label :email %>
      <%= f.email_field :email %>

      <%= f.label :password %>
      <%= f.password_field :password %>

      <%= f.label :password_confirmation, "Confirmation" %>
      <%= f.password_field :password_confirmation %>

      <%= f.submit "Create my account", class: "btn btn-primary" %>
    <% end %>
  </div>
</div>
```

は、ブラウザで以下のように置換される。

```html
<form accept-charset="UTF-8" action="/users" class="new_user"
      id="new_user" method="post">
  <input name="utf8" type="hidden" value="&#x2713;" />
  <input name="authenticity_token" type="hidden"
         value="NNb6+J/j46LcrgYUC60wQ2titMuJQ5lLqyAbnbAUkdo=" />
  <label for="user_name">Name</label>
  <input id="user_name" name="user[name]" type="text" />

  <label for="user_email">Email</label>
  <input id="user_email" name="user[email]" type="email" />

  <label for="user_password">Password</label>
  <input id="user_password" name="user[password]"
         type="password" />

  <label for="user_password_confirmation">Confirmation</label>
  <input id="user_password_confirmation"
         name="user[password_confirmation]" type="password" />

  <input class="btn btn-primary" name="commit" type="submit"
         value="Create my account" />
</form>
```

変換された後に以下のコードが加えられている。

```ruby
<input name="utf8" type="hidden" value="&#x2713;" />
<input name="authenticity_token" type="hidden"
       value="NNb6+J/j46LcrgYUC60wQ2titMuJQ5lLqyAbnbAUkdo=" />
```

このコードは、正しい文字コードを送信できたり、攻撃阻止するために信頼できるトークンを含めたりしている。
このように埋め込みRubyで超便利にコードが書ける。また、セキュリティのコードも生成してくれる。

　
## 演習
1.Learn Enough HTML to Be DangerousではHTMLをすべて手動で書き起こしていますが、なぜformタグを使わなかったのでしょうか? 理由を考えてみてください。 
A.
formタグってのは入力・送信フォームを作成する時に使うタグでであり、
Learn Enough HTML to Be Dangerousの中では入力・送信フォームを作成していないから。
単純に扱っていない。
　
## ユーザ登録失敗
エラー一覧を表示する。
## 正しいフォーム
まずは、ユーザ登録の失敗に対応できるcreateアクションを追加。
**app/controllers/users_controller.rb**

```ruby
class UsersController < ApplicationController

  def show
    @user = User.find(params[:id])
  end

  def new
    @user = User.new
  end

  def create
    @user = User.new(params[:user])    # 実装は終わっていないことに注意!
    if @user.save
      # 保存の成功をここで扱う。
    else
      render 'new'
    end
  end
end
```

ここで定義した
**@user = User.new(params[:user])** は、

```bash
@user = User.new(name: "Foo Bar", email: "foo@invalid",
                 password: "foo", password_confirmation: "bar")
```

と同じ意味になる。

しかしこれでは、脆弱性がある。
　
## Strong Parameters
paramsハッシュ全体を初期化するのはセキュリティ的に問題が発生する。
　
解決法
**app/controllers/users_controller.rb**

```ruby
def create
    @user = User.new(user_params)
    if @user.save
      # 保存の成功をここで扱う。
    else
      render 'new'
    end
  end

  private

    def user_params
      params.require(:user).permit(:name, :email, :password,
                                   :password_confirmation)
    end
```

このように、 **private** キーワードというものを使って、外部から使えないメソッドを定義し、@userに代入する仕組み。
これで解決
　
## 演習
1./signup?admin=1 にアクセスし、paramsの中にadmin属性が含まれていることをデバッグ情報から確認してみましょう。 
A.
**http://localhost:3000//signup?admin=1**

```bash
--- !ruby/object:ActionController::Parameters
parameters: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
  admin: '1'
  controller: users
  action: new
permitted: false
```

　
## エラーメッセージ
エラーメッセージのパーシャルを作っていく。
まず、 **app/views/users/new.html.erb** にrenderとか、boot-strapが機能するように　クラス名も定義していく。
**app/views/users/new.html.erb**

```ruby
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>

<div class="row">
  <div class="col-md-6 col-md-offset-3">
    <%= form_for(@user) do |f| %>
      <%= render 'shared/error_messages' %>

      <%= f.label :name %>
      <%= f.text_field :name, class: 'form-control' %>

      <%= f.label :email %>
      <%= f.email_field :email, class: 'form-control' %>

      <%= f.label :password %>
      <%= f.password_field :password, class: 'form-control' %>

      <%= f.label :password_confirmation, "Confirmation" %>
      <%= f.password_field :password_confirmation, class: 'form-control' %>

      <%= f.submit "Create my account", class: "btn btn-primary" %>
    <% end %>
  </div>
</div>
```

次に、パーシャルを作る。今回はディレクトリも生成する。

```bash
$ mkdir app/views/shared
$ touch app/views/shared/_error_messages.html.erb
```

**app/views/shared/_error_messages.html.erb**

```html
<% if @user.errors.any? %>
  <div id="error_explanation">
    <div class="alert alert-danger">
      The form contains <%= pluralize(@user.errors.count, "error") %>.
    </div>
    <ul>
    <% @user.errors.full_messages.each do |msg| %>
      <li><%= msg %></li>
    <% end %>
    </ul>
  </div>
<% end %>
```

**any?** メソッドは、エラーが一つでもあれば発動する。empty?の逆。
**pluralize** は、第一引数によって、単数形か複数形にいてくれる。
また、CSSも追加する。

**app/assets/stylesheets/custom.scss**

```css
#error_explanation {
  color: red;
  ul {
    color: red;
    margin: 0 0 30px 0;
  }
}

.field_with_errors {
  @extend .has-error;
  .form-control {
    color: $state-danger-text;
  }
}
```

ここでは、
Sassの@extend関数を使ってBootstrapのhas-errorというCSSクラスを適用している。
ここについて調べる。
　
## 演習
1.最小文字数を5に変更すると、エラーメッセージも自動的に更新されることを確かめてみましょう。 
A.
**app/models/user.rb**

```ruby
  validates :password, presence: true, length: { minimum: 5 }
```

にする。エラーメッセージも5になる。
　
2.未送信のユーザー登録フォーム (図 7.12) のURLと、送信済みのユーザー登録フォーム (図 7.18) のURLを比べてみましょう。なぜURLは違っているのでしょうか? 考えてみてください。 
A.
ここ自信がないが、 **app/views/users/new.html.erb** をブラウザに変更しtら時、formタグのアクションが **"/users"** となるため。


```html
<form accept-charset="UTF-8" action="/users" class="new_user"
      id="new_user" method="post">
```

　
## 失敗時のテスト
統合テストを生成して、登録フォームをテストする。
まず、統合テストを生成する。

```bash
rails generate integration_test users_signup
```

そこに、無効なデータを入れたとき、ユーザの数が変わらないかどうか、つまり変なデータができないかどうかのテスト
**test/integration/users_signup_test.rb**

```ruby
require 'test_helper'

class UsersSignupTest < ActionDispatch::IntegrationTest

  test "invalid signup information" do
    get signup_path
    assert_no_difference 'User.count' do
      post users_path, params: { user: { name:  "",
                                         email: "user@invalid",
                                         password:              "foo",
                                         password_confirmation: "bar" } }
    end
    assert_template 'users/new'
  end
end
```

テストはGREENになる。
　
## 演習
1.リスト 7.20で実装したエラーメッセージに対するテストを書いてみてください。どのくらい細かくテストするかはお任せします。リスト 7.25にテンプレートを用意しておいたので、参考にしてください。 
A.
**test/integration/users_signup_test.rb**

```ruby
require 'test_helper'

class UsersSignupTest < ActionDispatch::IntegrationTest

  test "invalid signup information" do
    get signup_path
    assert_no_difference 'User.count' do
      post users_path, params: { user: { name:  "",
                                         email: "user@invalid",
                                         password:              "foo",
                                         password_confirmation: "bar" } }
    end
    assert_template 'users/new'
    assert_select 'div#error_explanation'
    assert_select 'div.alert'  
  end
end
```

CSSのクラス、idについてのテストを書いた。
　
2.ユーザー登録フォームのURLは /signup ですが、無効なユーザー登録データを送付するとURLが /users に変わってしまいます。これはリスト 5.43で追加した名前付きルート (/signup) と、RESTfulなルーティング (リスト 7.3) のデフォルト設定との差異によって生じた結果です。リスト 7.26とリスト 7.27の内容を参考に、この問題を解決してみてください。うまくいけばどちらのURLも /signup になるはずです。あれ、でもテストは greenのままになっていますね...、なぜでしょうか? (考えてみてください)
A.
それぞれをコピペする。テストでは、ユーザ登録数の差異で判断してるから？
　
3.リスト 7.25のpost部分を変更して、先ほどの演習課題で作った新しいURL (/signup) に合わせてみましょう。また、テストが greenのままになっている点も確認してください。 
A.
**test/integration/users_signup_test.rb**

```ruby
require 'test_helper'

class UsersSignupTest < ActionDispatch::IntegrationTest

  test "invalid signup information" do
    get signup_path
    assert_no_difference 'User.count' do
      post signup_path, params: { user: { name:  "",
                                         email: "user@invalid",
                                         password:              "foo",
                                         password_confirmation: "bar" } }
    end
    assert_template 'users/new'
    assert_select 'div#error_explanation'
    assert_select 'div.alert'  
  end
end
```

　

4.リスト 7.27のフォームを以前の状態 (リスト 7.20) に戻してみて、テストがやはり greenになっていることを確認してください。これは問題です! なぜなら、現在postが送信されているURLは正しくないのですから。assert_selectを使ったテストをリスト 7.25に追加し、このバグを検知できるようにしてみましょう (テストを追加して redになれば成功です)。その後、変更後のフォーム (リスト 7.27) に戻してみて、テストが green になることを確認してみましょう。ヒント: フォームから送信してテストするのではなく、'form[action="/signup"]'という部分が存在するかどうかに着目してテストしてみましょう。
A.
コピペし、統合テストに以下を追加。

**est/integration/users_signup_test.rb**

```ruby
require 'test_helper'

class UsersSignupTest < ActionDispatch::IntegrationTest

  test "invalid signup information" do
    get signup_path
    assert_no_difference 'User.count' do
      post signup_path, params: { user: { name:  "",
                                         email: "user@invalid",
                                         password:              "foo",
                                         password_confirmation: "bar" } }
    end
    assert_template 'users/new'
    assert_select 'div#error_explanation'
    assert_select 'div.alert'  
    assert_select 'form[action="/signup"]'
  end
end
```

アクションが存在しないのでREDになる。
　
## ユーザー登録成功
Railsではcreateアクションに対応するビューがないため、慣習的にリダイレクトするようにしている。

**app/controllers/users_controller.rb**

```ruby
class UsersController < ApplicationController
  .
  .
  .
  def create
    @user = User.new(user_params)
    if @user.save
      redirect_to @user
    else
      render 'new'
    end
  end

  private

    def user_params
      params.require(:user).permit(:name, :email, :password,
                                   :password_confirmation)
    end
end
```

このようになる。
ここでのリダイレクトコードは


```ruby
redirect_to user_url(@user)
```

これと同じ意味で、これの方が分かりやすいが省略された。

　
## 演習
1.有効な情報を送信し、ユーザーが実際に作成されたことを、Railsコンソールを使って確認してみましょう。 
A.
signupしてrails cで確認したらできていた。　
　
2.リスト 7.28を更新し、redirect_to user_url(@user)とredirect_to @userが同じ結果になることを確認してみましょう。
A.
省略。
　

## flash
フラッシュメッセージを追加していく。

**app/controllers/users_controller.rb**

```ruby
class UsersController < ApplicationController
  .
  .
  .
  def create
    @user = User.new(user_params)
    if @user.save
      flash[:success] = "Welcome to the Sample App!"
      redirect_to @user
    else
      render 'new'
    end
  end

  private

    def user_params
      params.require(:user).permit(:name, :email, :password,
                                   :password_confirmation)
    end
end
```

次に、レイアウトにflashを追加。
**app/views/layouts/application.html.erb**

```ruby
<% flash.each do |message_type, message| %>
  <div class="alert alert-<%= message_type %>"><%= message %></div>
<% end %>
```

　
## 演習
1.コンソールに移り、文字列内の式展開 (4.2.2) でシンボルを呼び出してみましょう。例えば"#{:success}"といったコードを実行すると、どんな値が返ってきますか? 確認してみてください。
A.
rails cにて

```bash
puts "#{:success}"
success
```

　
2.先ほどの演習で試した結果を参考に、リスト 7.30のflashはどのような結果になるか考えてみてください。 
A.
rails cにて

```bash
"#{flash[:success]}"
=> "It worked!"
```

　
## 実際にユーザ登録
実際に登録してみる。その際、データベースを一旦リセットする。

```bash
rails db:migrate:reset
```

また、サーバも再起動させる。
　
## 演習
1.Railsコンソールを使って、新しいユーザーが本当に作成されたのかもう一度チェックしてみましょう。結果は、リスト 7.32のようになるはずです。 
A.
省略
　
2.自分のメールアドレスでユーザー登録を試してみましょう。既にGravatarに登録している場合、適切な画像が表示されているか確認してみてください。 
A.
省略
　
## 成功時のテスト
ユーザが登録成功したときの統合テストを書く。

以下のようになる。
**test/integration/users_signup_test.rb**

```ruby
require 'test_helper'

class UsersSignupTest < ActionDispatch::IntegrationTest
  .
  .
  .
  test "valid signup information" do
    get signup_path
    assert_difference 'User.count', 1 do
      post users_path, params: { user: { name:  "Example User",
                                         email: "user@example.com",
                                         password:              "password",
                                         password_confirmation: "password" } }
    end
    follow_redirect!
    assert_template 'users/show'
  end
end
```


ここでは、User.countでユーザの数を比較しながら、 follow_redirect!でしっかり'users/show'へ移動できたかをテストしている。
　
## 演習
1.7.4.2で実装したflashに対するテストを書いてみてください。どのくらい細かくテストするかはお任せします。リスト 7.34に最小限のテンプレートを用意しておいたので、参考にしてください (FILL_INの部分を適切なコードに置き換えると完成します)。ちなみに、テキストに対するテストは壊れやすいです。文量の少ないflashのキーであっても、それは同じです。筆者の場合、flashが空でないかをテストするだけの場合が多いです。
A.
**test/integration/users_signup_test.rb**

```ruby
assert_not flash.empty?   
```

を追加。
　
2.本文中でも指摘しましたが、flash用のHTML (リスト 7.31) は読みにくいです。より読みやすくしたリスト 7.35のコードに変更してみましょう。変更が終わったらテストスイートを実行し、正常に動作することを確認してください。なお、このコードでは、Railsのcontent_tagというヘルパーを使っています。
A.
コピペ
　
3.リスト 7.28のリダイレクトの行をコメントアウトすると、テストが失敗することを確認してみましょう。
A.
省略。
　
4.リスト 7.28で、@user.saveの部分をfalseに置き換えたとしましょう (バグを埋め込んでしまったと仮定してください)。このとき、assert_differenceのテストではどのようにしてこのバグを検知するでしょうか? テストコードを追って考えてみてください
A.
リダイレクトした際に、本当ならば、ユーザが登録され、User.countが増えるはずなのにできていないから、REDになる。
　
## プロのデプロイ
まずは、マージしてmasterブランチに移動する。
## 本番環境でのSSL
Secure Sockets Layer(SSL)を使うことによって、ローカルのサーバからネットワークに流れる前に、大事な情報を暗号化してくれる。
本番環境用の設定ファイルであるproduction.rbのコードをたった1行変更するだけでSSLを強制し、httpsによる安全な通信を確立できる。
**config/environments/production.rb**

```ruby
Rails.application.configure do
  .
  .
  .
  # Force all access to the app over SSL, use Strict-Transport-Security,
  # and use secure cookies.
  config.force_ssl = true
  .
  .
  .
end
```

## 本番環境用のWebサーバー
**config/puma.rb**

```ruby
workers Integer(ENV['WEB_CONCURRENCY'] || 2)
threads_count = Integer(ENV['RAILS_MAX_THREADS'] || 5)
threads threads_count, threads_count

preload_app!

rackup      DefaultRackup
port        ENV['PORT']     || 3000
environment ENV['RACK_ENV'] || 'development'

on_worker_boot do
  # Worker specific setup for Rails 4.1+
  # See: https://devcenter.heroku.com/articles/
  # deploying-rails-applications-with-the-puma-web-server#on-worker-boot
  ActiveRecord::Base.establish_connection
end
```

中身は理解しなくて良いらしい。
　
次に、 Pumaが使うようにProcfileで定義する。また、ルートディレクトリに作成。
**./Procfile**

```ruby
web: bundle exec puma -C config/puma.rb
```

　
## 本番環境へデプロイ
## 演習
1.ブラウザから本番環境 (Heroku) にアクセスし、SSLの鍵マークがかかっているか、URLがhttpsになっているかどうかを確認してみましょう。 
A.
省略。
　
2.本番環境でユーザーを作成してみましょう。Gravatarの画像は正しく表示されているでしょうか? 
A.
省略。
　
