Railsチュートリアル(第6版)　第7章　ユーザー登録

#ユーザー登録
いよいよユーザーの登録ページに入っていく。
ユーザーを登録するさいのフォームに画像やサイドバー、成功時と失敗時のメッセージ、ストロングパラメーターなど覚えることはたくさんある。

##ユーザーを表示する
まずは、ユーザーの名前とプロフィール写真を表示するためのページを作る。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/f8add2f2-e3c6-1cb2-3e52-c21423c9fa36.png)
参照：railsチュートリアル

こんなかんじ

ではブランチをつくる
`$ git checkout -b sign-up`

###デバッグとRails環境
`debug`メソッドと`params`変数を追記

```ruby:app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  .
  .
  .
  <body>
    <%= render 'layouts/header' %>
    <div class="container">
      <%= yield %>
      <%= render 'layouts/footer' %>
      <%= debug(params) if Rails.env.development? %>
    </div>
  </body>
</html>
```

`if Rails.env.development?`
これをいれておけば、開発環境だけデバッグ情報が表示されるようになる。
本番のアプリでは挿入されないのでOK

・Railsの3つの環境
　・テスト環境(test)
　・開発環境(development)
　・本番環境(production)
  開発環境にだけデバッグ情報があればOK


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

Railsオブジェクトに対し、`env`という属性を使えば、論理値(boolean)を取れる。

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

他の環境でconsoleを実行する必要が生じた場合は、環境をパラメータとしてconsoleに渡せる。

```
$ rails server --environment production
```

明示的に他の環境を実行できる。

```
$ rails db:migrate RAILS_ENV=production
```

本番環境で本番データベースを作成できる。


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

Herokuの本番環境を確認できる。



デバッグ出力を整形する。

```scss:app/assets/stylesheets/custom.scss
@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のミックイン機能を利用。
ミックスイン機能を使えば、CSSルールをパッケージ化して、複数の要素に適用できる。

```scss
.debug_dump {
  .
  .
  .
  @include box_sizing;
}
```

`@include`を使えば下のような形で実行される。

```scss
.debug_dump {
  .
  .
  .
  -moz-box-sizing:    border-box;
  -webkit-box-sizing: border-box;
  box-sizing:         border-box;
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/b044ec89-55c8-cece-e340-49f3ec7c3ce0.png)
画面下の方にデバッグ情報が出た。

コントローラーとアクションが書いてあり、これはparamsに含まれている内容で、YAMLという形式で書かれている。
YAMLは基本的にハッシュで構成されている。

演習

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/bc98d03e-5aee-dbef-6176-978e964ebcdb.png)
aboutページのやつ

###Usersリソース
RESTアーキテクチャの慣習に倣い、HTTP標準の作成、表示、更新、削除をリソースとして扱う。
HTTP標準には4つの基本操作POST、GET、PATCH、DELETEが定義される。

リソース名/idとすれば、そのユーザーを参照できる。
`/users/1`このような形

まだルーティング未定義なのでエラーになる。

`resources :users`を`config/routes.rb`に追加する。

| HTTPリクエスト | URL | アクション |名前付きルート|用途|
|:-----------|:------------|:------------|:------------|:------------|
| GET      | /users       | index         |users_path|すべてのユーザーを一覧するページ|
| GET     | /users/1      | show       |user_path(user)|特定のユーザーを表示するページ|
| GET       | /users/new        | new         |new_user_path|ユーザーを新規作成するページ（ユーザー登録）|
| POST         | /users          | create           |users_path|ユーザーを作成するアクション|
| GET       | /users/1/edit       | edit      |edit_user_path(user)|id=1のユーザーを編集するページ|
| PATCH    | /users/1    | update     |user_path(user)|ユーザーを更新するアクション|
| DELETE    | /users/1     | destroy      |user_path(user)|ユーザーを削除するアクション|

`resources :users`を追加しただけで、RESTfulなルートがあっという間に構築できるので大変便利


次にやることは、ビューに表示するための埋め込みRubyの記述(仮)

```ruby:app/views/users/show.html.erb
<%= @user.name %>, <%= @user.email %>
```

Usersコントローラー内に上記の`show`ページに対するたくしょんを追加し、`@user`変数を定義する。

```ruby:app/controllers/users_controller.rb
  def show
    @user = User.find(params[:id])
  end
```

`params[:id]の部分は、`/users/1`の1の部分に該当し、**findメソッドの引数に渡すことで文字列型から整数型に変換される。**
idが1なら、`User.find(1)`と同じ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/e47f6bb1-447b-8c60-a544-7baafed1af60.png)

`show`ページに行き、idを確認すると「1」となっていることが分かる。
`id: 1`は、params[:id]によって/users/`:id`から取得したもの
また、actionは`show`で、controllerは`users`となっている。

演習

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/e07ee2d5-fbd0-feb6-85c7-01fa931c9326.png)

```
<%= @user.created_at %><br>
<%= @user.updated_at %>
<%= Time.now %>
```

###debuggerメソッド
`debug`メソッドでデバッグ情報をみる事ができた。
さらに直感的に分かるよう、`byebug`gemによる`debugger`メソッドを、アプリケーションに入れることで、`debugger`が読まれた時点のデバッグ情報をみることができる。

こんな感じで、`debugger`を差し込んだ時点で止まる。

```
Processing by UsersController#show as HTML
  Parameters: {"id"=>"1"}
  User Load (0.1ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  ↳ app/controllers/users_controller.rb:4:in `show'
Return value is: nil

[1, 10] in /home/ubuntu/environment/sample_app/app/controllers/users_controller.rb
    1: class UsersController < ApplicationController
    2:   
    3:   def show
    4:     @user = User.find(params[:id])
    5:     debugger
=>  6:   end
    7:   
    8:   def new
    9:   end
   10: end
(byebug) 
```

Ctrl-Dを押すと抜け出せる。
デバッグしたいところに差し込むので、終わったら`debugger`は削除しよう。

###Gravatar画像とサイドバー
Q：Gravatarとは？
A：Gravatar（Globally Recognized AVATAR）の略。無料サービスで写真とメールアドレスの紐づけができる。

おかげさまで、写真のアップロードする時の面倒さ作業が画像の置き場所の悩みを解決できる。

`gravatar_for`ヘルパーメソッドを使って画像を利用できるようにする。

```ruby:app/views/users/show.html.erb
<% provide(:title, @user.name) %>
<h1>
  <%= gravatar_for @user %>
  <%= @user.name %>
</h1>
```

ヘルパーファイルで定義されているメソッドは自動的にすべてのビューで利用できるということで、利便性を考えて、`gravatar_for`をUsersコントローラーに結び付けれたヘルパーファイルに置くことにする。

```ruby:app/helpers/users_helper.rb
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
```

Rubyでは、Digestライブラリのhexdigestメソッドを使うと、MD5のハッシュ化が可能となる。
メールアドレスは、大文字と小文字を区別しないが、MD5ハッシュは大文字と小文字を区別する。なので、`downcase`メソッドを使って、`hexdigest`の引数を小文字に変換する。
(コールバック処理で小文字に変換されたメールアドレスを利用しているため、ここの小文字変換はなくても結果は同様だが、将来`gravatar_for`メソッドが別の場所から呼ばれた際に有意義となる)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/d08e940c-20db-54b7-d029-6f4255642a8f.png)
画像が表示された。

こんどはレイアウトを変える

```ruby:app/views/users/show.html.erb
<% 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>
```

CSSも手を加える。

```css:app/assets/stylesheets/custom.scss
/* 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;
}
```

左に寄った。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/cfb6c593-f018-10db-e805-5528d1aaa2d3.png)


##ユーザー登録フォーム
プロフィールページが動いたので、ユーザー登録フォームを作る。

###`form_with`を使用する
フォームを読み込むには、`form_with`ヘルパーメソッドを使い、Active Recordのオブジェクトを取り込んで、そのオブジェクトの属性からフォームを構築するもの。

`new`アクションで必要となる`@user`変数の定義をする。

```ruby:app/controllers/users_controller.rb
  def new
    @user = User.new
  end
```

erbとscssも変更する。

```ruby:app/views/users/new.html.erb
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>

<div class="row">
  <div class="col-md-6 col-md-offset-3">
    <%= form_with(model: @user, local: true) 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>
```

```scss:app/assets/stylesheets/custom.scss
/* forms */

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

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

ユーザーフォームの画面ができた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/f6d14a08-1796-42eb-6bc9-22f033037679.png)

演習の解答
`foobar`はメタ構文変数なので意味がない。メタ構文変数とは意味のないただの文字。何かテストユーザーを作るときの田中太郎とか花子とかそんな感じ
また、formの頭文字を取ったものとして`f`は分かりやすい。

###フォームHTML
フォームを理解するために、`form_with`って何かを理解する。
(以前のrailsでは、`form_for`だったけど、新しいrailsでは`form_with`になっている。詳しくは調べてください)

```erb
<%= form_with(model: @user, local: true) do |f| %>
  .
<% end %>
```

・`do`キーワードは、`form_with`1つの変数を持つブロックを取るということ

・ハッシュ引数の`local: true`とすることで、Ajaxをオフにできる。Ajaxをオンにするには、`remote: true`

・`f`オブジェクトは、HTMLフォーム要素に対応するメソッドが呼びされたとき、@user属性を設定するために設計されたHTMLを返す。例えば、、、

```html
<%= f.label :name %>
<%= f.text_field :name %>
```

とすることで、name属性を設定するラベル付きテキストフィール要素を作るHTMLを作成する。
従って、下のようなHTMLを生成することになる。

```html
<label for="user_name">Name</label>
<input id="user_name" name="user[name]" type="text" />
```

・`type="text"`、`type="email"`、`type="password"`の違い
　・`type="text"`は、内容をそのまま表示
　・`type="email"`は、モバイル端末の入力フォームにて、最適化されたキーボードが表示される。
　・`type="password"`は、セキュリティ上文字が隠蔽される。

・`input`タグの`name`属性を使って、初期化したハッシュを`params`変数経由で構成する。

・`form`タグを作成する際、`@user`オブジェクトを使うが、ユーザーが新しいユーザーかどうかで処理が分かれる。今回、`@user`は新しいユーザーなので、`post`メソッドを使うと判断する。

```
<form action="/users" class="new_user" id="new_user" method="post">
```

上で大事なのは、`action="/users"`と`method="post"`の部分になる。/usersに対して、postリクエストを送信する。

・`form`タグの内側では下のようなHTMLが生成されている。

```erb
<input name="authenticity_token" type="hidden"
       value="NNb6+J/j46LcrgYUC60wQ2titMuJQ5lLqyAbnbAUkdo=" />
```

これは、CSRF(Cross-Site Request Forgery)という攻撃を阻止するためのトークンを含めている。

##ユーザー登録失敗
無効なデータを送信した際にエラーの一覧がでるようにする。

###正しいフォーム
以前、`resources :users`を追加したことで、RESTful URIに応答するようになった。
ということで、全体の流れとしては、、、

①`/signup`ページでフォームにデータが入る
②`users`コントローラーの`create`アクションでフォームのデータを受け取る
③`User.new`で新しいユーザーオブジェクトを作成する
④ユーザーオブジェクトを保存する。保存できなかったら、`render`で登録ページを表示する。

`create`アクション内で、新しいユーザーオブジェクトを作成する際、以下のような方法で行う。
`@user = User.new(params[:user])`
この`[:user]`は、`params`ハッシュで各リクエスト情報が入っている。そして、この`params`は入れ子になっており、送られたデータ情報が含まれている。
このような感じに

```
"user" => { "name" => "Foo Bar",
            "email" => "foo@invalid",
            "password" => "[FILTERED]",
            "password_confirmation" => "[FILTERED]"
          }
```

Railsでは、文字列として渡すのではなく、`params[:user]`のようにシンボルとしてUsersコントローラーに渡している。
`User.new`の引数とハッシュの値は完全に一致する。
従って

```ruby
@user = User.new(params[:user])
```

と

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

は同じであるということ。

しかし、マスアサインメントというのは、脆弱性があるため現在では**Strong Parameters**を使うようになった。

###Storong Parameters
前回のコードにあった
`@user = User.new(params[:user])`
というものは、マスアサインメントの脆弱性があったため、Rails 4.0以降ではエラーを引き起こすようになった。
`params`ハッシュ全体を初期化する行為は、セキュリティ上非常に危険なことだ。Userモデルに`admin`属性というのがった際、`admin=1`という値を`params[:user]`に紛れ込ませてしまえば、この属性を`true`にさせることができ、管理者権限を奪い取れてしまう。

こういった危険性を回避するため、**Strong Parameters**を使おうねってなった。これは、**必須のパラメーター**と**許可されたパラメーター**を指定することができるもの。

この場合、`params`ハッシュでは、`:user`属性を必須として、名前、メールアドレス、パスワード、パスワードの確認属性を許可して、それ以外を許可しないようにしたい。

```ruby
params.require(:user).permit(:name, :email, :password, :password_confirmation)
```

こういったパラメーターを使いやすくするために、`user_params`という外部メソッドを使うのが慣例で、さらにこの外部メソッドは、privateの中に書くことで、外部からこのメソッドが使えないようにする。

```ruby:app/controllers/users_controller.rb
class UsersController < ApplicationController
  .
  .
  .
  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
end
```

まだこの時点では、間違ったデータを送信してもフィードバックがない。また、新しいユーザーが作成されることもない。
これらを次は解決する。

演習
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/8d7a3b00-0faa-dc94-8167-6bb33e6b7ba4.png)


###エラーメッセージ
現時点では、間違った値を送信した時のエラーメッセージが出ない。

```
$ rails console
>> user = User.new(name: "Foo Bar", email: "foo@invalid",
?>                 password: "dude", password_confirmation: "dude")
>> user.save
=> false
>> user.errors.full_messages
=> ["Email is invalid", "Password is too short (minimum is 6 characters)"]
```

`errors.full_messages`オブジェクトは、エラーメッセージの配列を持っている。
このエラーメッセージのパーシャルをユーザーの`new`ページでパーシャル出力すればOK。
同時に、Bootstrapの`form-control`というCSSクラスを追加すれば、良い感じにいなる。

```ruby:app/views/users/new.html.erb
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>

<div class="row">
  <div class="col-md-6 col-md-offset-3">
    <%= form_with(model: @user, local: true) 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>
```

`<%= render 'shared/error_messages' %>`というパーシャルから`render`するようにまとめている。
ので、作成する。
`$ touch app/views/shared/_error_messages.html.erb`
そして下記のものが、エラーメッセージのパーシャル。

```ruby:app/views/shared/_error_messages.html.erb
<% 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 %>
```

・`user.errors.any?`は、エラーが一つでもあれば、`true`
　`user.errors.empty?`は、逆の動作をする。

・`user.errors.count`は、エラーの数をカウントする。

・`pluralize`というテキストヘルパーは、英語専用(複数形の時は語尾に`s`が付くやつ、、、）日本語だとないかな？日本語は数え方が変わるけど(一本、一冊、一人）

```
>> helper.pluralize(1, "error")
=> "1 error"
>> helper.pluralize(5, "error")
=> "5 errors"
```

なので、`<%= pluralize(@user.errors.count, "error") %>`とすれば、エラーの数を数えた数字を、第二引数の`error`にくっつけて、単数か複数かで単語を変える。

そして、エラーメッセージが出た時に赤く囲ってくれるようにCSSを追加

```scss:app/assets/stylesheets/custom.scss
#error_explanation {
  color: red;
  ul {
    color: red;
    margin: 0 0 30px 0;
  }
}

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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/6de94c67-8103-f39f-0111-421211fd7347.png)
エラーメッセージがでた。
しかし、`Password can't be blank`が2つあるので、後々修正する。

演習
１
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/c29c8225-05e4-69aa-8ce7-19d75cd891fc.png)

###失敗時のテスト
テスト機能を持ったWebフレームワークがなかった時代では、フォームのテストを毎回手動で行っていた。
一つ一つページを表示して、値を入力して、、、みたいな地道な作業である。

Railsではフォーム用のテストを自動化できる。
なので、新規ユーザー登録用の統合テストを生成する。

```
$ rails generate integration_test users_signup
```

このテストでは、無効なユーザーを登録しようとした時に、作成されないことを確認する。

```ruby:test/integration/users_signup_test.rb
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
```

テスト概要
①`get signup_path`でユーザー登録ページにアクセス

②`assert_no_difference 'User.count' do`登録前と登録後でユーザーの数が変わってないかチェック
下記のデータをpostして作成する。(下記のユーザー情報は検証に弾かれるものにする）

```ruby
 post users_path, params: { user: { name:  "",
                                     email: "user@invalid",
                                     password:              "foo",
                                     password_confirmation: "bar" } }
```

③送信失敗時に、`new`アクションが再描画されるので、`assert_template 'users/new'`でエラーメッセージが表示されているかの確認

テストした結果OKだった。

演習
1.エラーメッセージに対するテストを追加

```ruby:test/integration/users_signup_test.rb
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.field_with_errors'
  end
end
```

##ユーザー登録成功
ここから、実際に新規ユーザーを登録できるようにしていく。
ユーザーが登録、保存できたら、ブラウザの表示を例ダイレクトして、登録されたユーザーのプロフィールページを表示する。

###登録フォームの完成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/3afa2e51-dfac-64ae-59d5-ba11f1b4c283.png)


現状は正しいユーザー情報を入力しても、テンプレートがないと出る。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/8fd12cc6-0f4b-adc1-aec7-135a803097a8.png)

今回、Railsの慣習に倣い、ユーザー登録成功時にはページを描画せず、別のページにリダイレクトさせるようにする。
リダイレクト先は、ユーザーのプロフィールページにする。

```ruby:app/controllers/users_controller.rb
  def create
    @user = User.new(user_params)
    if @user.save
      redirect_to @user
    else
      render 'new'
    end
  end
```

`redirect_to @user`に関して
この辺り、学習まとめを作っている人の中で**謎ポイント**としてよく取り上げられている気がする。
「なにこれ？よーわからん」的な

Railsチュートリアルの説明引用
>これはredirect_to @userというコードから（Railsエンジニアが）user_url(@user)といったコードを実行したいということを、Railsが推察してくれた結果になります。

これ、Railsの省略の書き方を応用したもので、省略しまくった結果`redirect_to @user`になっている。

この方の説明が大変参考になった。
[redirect_to @userが何を省略しているかわかりますか？〜挫折しないRailsチュートリアル７章〜](https://qiita.com/Kawanji01/items/96fff507ed2f75403ecb)

###flash
登録できたら、「登録完了」等のメッセージが欲しい。
ただし、2度目以降はそのページにメッセージを表示させない事。

これを可能にしてくれるのが、`flash`という特殊な変数。
この変数はハッシュのように扱える。

```ruby:app/controllers/users_controller.rb
  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
```

`flash[:success]`に登録成功時のメッセージを格納する。

続いて、htmlにメッセージ表示を実装

```erb:app/views/layouts/application.html.erb
  <body>
    <%= render 'layouts/header' %>
    <div class="container">
      <% flash.each do |message_type, message| %>
        <div class="alert alert-<%= message_type %>"><%= message %> </div>
      <% end %>
      <%= yield %>
      <%= render 'layouts/footer' %>
      <%= debug(params) if Rails.env.development? %>
    </div>
```

`alert-<%= message_type %>`に`success`とか`danger`とかが入る。

演習
答え：`:success`とか`:danger`のシンボルを式展開すると`:`が除かれたものが出力される。

###実際のユーザー登録
一旦サンプルアプリケーションのユーザーをリセット
`$ rails db:migrate:reset`
そして、Webサーバーを再起動する。

サンプルユーザーとして
名前：Rails Tutorial
メールアドレス：example@railstutorial.org
で登録する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/db68a579-7005-94ec-6ce5-f10d2c1d4cef.png)

再読み込みすると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/787472e4-64a0-ebbe-47ef-8816e89b2a95.png)

演習

```
> User.find_by(email: "example@railstutorial.org")
   (0.4ms)  SELECT sqlite_version(*)
  User Load (1.6ms)  SELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT ?  [["email", "example@railstutorial.org"], ["LIMIT", 1]]
 => #<User id: 1, name: "Rails Tutorial", email: "example@railstutorial.org", created_at: "2021-05-26 22:20:03", updated_at: "2021-05-26 22:20:03", password_digest: [FILTERED]> 
```

###成功時のテスト
前回は無効な値の送信時のテストだったが、今回はデータベースの中身が正しいかどうか検証する。
つまり、有効な情報でユーザーが作成できたかどうかをチェックする。

```
assert_difference 'User.count', 1 do
  post users_path, ...
end
```

このように書いてあげればよい。登録前と登録後でユーザーが一人増えてれば良いのだ。
成功時のテスト

```ruby:test/integration/users_signup_test.rb
  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
```

postリクエスト送信した時に、`follow_redirect!`というメソッドを使えば、リダイレクト先に遷移する。
そして、`assert_template 'users/show'`にとって、`show`アクションと`show.html.erb`ビューが正しく動作しているか確認している。
さらに、`assert_template 'users/show'`はページ全体のテストもしているので、この1行は大切だ。

演習
1.flashに対するテスト
`assert_not flash.empty?`あるいは、`blank?`を使っても良いと思う。

2.より読みやすいコードに変更。`content_tag`に変更
`<%= content_tag(:div,message,class:"alert alert-#{message_type}") %>`


##プロのデプロイ
ここにきてやっと、実際のデータを操作できるデプロイを行える。
ユーザー作成と保存ができる段階まで来た。

ここまでの段階をコミットし、masterにマージしておこう。

###本番環境でのSSL
ユーザー登録フォームで送信した名前やメールアドレス、パスワード等のデータが暗号化されていないとネットワーク越しに漏洩してしまうリスクがある。
そのため、`Transport Layer Security（TLS）`を使う。別称では、`SSL（Secure Socket Layer）`とも呼ばれる。

SSL有効かの手順は簡単
`production.rb`の設定ファイルを1行修正すればOK

```ruby:config/environments/production.rb
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
```

また、本来であればドメイン毎にSSL証明書を購入するのだが、今回はHerokuのSSL証明書に便乗する。

###本番環境用のWebサーバー
Herokuのデフォルトでは、WEBrickというWebサーバーを使用しているが、トラフィックの増加に弱いので、今回はWEBrickからPumaサーバーに置き換える。
Pumaサーバーは多数のリクエストを捌けるので、本番環境に適している。

Rails5以降では、Pumaはデフォルトの設定で使えるため、Pumaの設定を書き込むだけでOK

```ruby:config/puma.rb
# Pumaの設定ファイル
max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
threads min_threads_count, max_threads_count
port        ENV.fetch("PORT") { 3000 }
environment ENV.fetch("RAILS_ENV") { ENV['RACK_ENV'] || "production" }
pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }
workers ENV.fetch("WEB_CONCURRENCY") { 2 }
preload_app!
plugin :tmp_restart
```

最後に、Pumaのプロセスを走らせるProcfileと呼ばれる設定ファイルを作成する。

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

###本番データベースを設定する
本番環境で使うデータベースは、PostgreSQL。(HerokuのRails6向けでは、PostgreSQLが推奨されているため)

```ruby:config/database.yml
production:
  adapter: postgresql
  encoding: unicode
  # For details on connection pooling, see Rails configuration guide
  # https://railsguides.jp/configuring.html#データベース接続をプールする
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  database: sample_app_production
  username: sample_app
  password: <%= ENV['SAMPLE_APP_DATABASE_PASSWORD'] %>
```

あとは、デプロイすればOK

```
$ rails test
$ git add -A
$ git commit -m "Use SSL and the Puma webserver in production"
$ git push && git push heroku
```

演習
1.鍵マークの確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/83bd8e09-86d7-d4e3-4c47-7ce72caf6040.png)
鍵マークついているので、OK

#最後に
ユーザー登録機能の実装でいよいよWEBアプリケーションっぽくなってきた。
railsチュートリアルをやっている人なら、この章以降に難易度が着実に上がっていっていくという実感は湧くはず。