Rails Tutorial 第6版 学習まとめ 第7章

###概要
この記事は私の知識をより確実なものにするためにRailsチュートリアル解説記事を書くことで理解を深め
勉強の一環としています。稀にとんでもない内容や間違えた内容が書いてあるかもしれませんので
ご了承ください。
できればそれとなく教えてくれますと幸いです・・・

出典
[Railsチュートリアル第6版](https://railstutorial.jp/)

###この章でやること
前章でUserモデルを作成したのでユーザー登録機能を実装する。
ここからRESTfulなページを実装していく。

###ユーザーを表示する
いつも通りトピックブランチを作成して作業する。
```git checkout -b sign-up```

####デバッグとRails環境
レイアウトファイルにデバッグ情報が表示されるようにする。

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

Railsには3つの環境があり、それぞれ
test:テスト環境
development:開発環境
production:本番環境
となっておりこの場合は本番環境やテスト環境ではデバッグはいらないため
development環境の時のみデバッグ情報を表示するよう設定している。

レイアウトにデバッグ情報を入れたのでCSSも追加する。

```css
.debug_dump{
  clear: both;
  float: left;
  width: 100%;
  margin-top: 45px;
  @include box_sizing;
}
```
ここではSaasのミックスイン機能を使ってパッケージ化したCSSルールを読み込んでいる。

デバッグ情報をのぞいてみる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617753/d9d9fbab-95c9-36db-bc94-a1e7c8463491.png)

コントローラとアクションが書いてあるのがわかる。
これらはparamsに含まれていてYAMLという形式で書かれている。YAMLはハッシュで構成されている。
どんな形式で書かれているかは直後の演習で確認する。


#####演習
1.static_pagesのaboutアクションだとわかる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617753/f5136bb1-6e94-185b-6379-629a9a0868b5.png)

2.```to_yaml```とyメソッドは同じ効果で
userオブジェクトの属性をYAMLに変換してくれる。

```
>> y user.attributes
---
id: 1
name: taketake
email: take@gmail.com
created_at: !ruby/object:ActiveSupport::TimeWithZone
  utc: &1 2020-06-10 12:51:23.959140000 Z
  zone: &2 !ruby/object:ActiveSupport::TimeZone
    name: Etc/UTC
  time: *1
updated_at: !ruby/object:ActiveSupport::TimeWithZone
  utc: &3 2020-06-10 13:09:09.579353000 Z
  zone: *2
  time: *3
password_digest: "$2a$12$xkZDNGfs2Dnjzbm5XxfCfu.sB3I4ug4PFtTHukKdp0EF9YLLsE5Sm"
=> nil
```

####Usersリソース
RESTの原則通りに実装していくとデータの作成、表示、更新、削除を
HTTPの基本操作(GET,POST,PATCH,DELETE)として各アクションに割り当てる。
User情報表示ページはそれぞれのユーザーを一意に識別する属性でリソースを参照する。
リソース名/IDが基本
IDが1のユーザーの表示ページは/users/1となる。
(現段階ではルーティングが未定義なのでエラー)

ルーティングを有効にするためroutes.rbに以下の一行を追加する。
```resources :users```
この一行でRESTfulなUsersリソースで必要になる基本のアクションが利用できるようになる。

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

Railsチュートリアル第6版より
https://railstutorial.jp/chapters/sign_up?version=6.0#table-RESTful_users

ルーティングを実装したので表示するページとアクションを作成すれば動くようになる。

さっそくユーザー表示ページ(showページ)の雛形を作成していく。
ジェネレータを使っていないので手動でapp/views/users内にshow.html.erbを作成する。

```erb:show.html.erb
<%= @user.name %>,<%= @user.email %>
```
ここでは@user変数を使っているが定義されていないので使えない。
そこでUsersコントローラのshowアクションに@user変数を定義することで使えるようにする。

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

params[:id]は文字型の"1"が格納されているがfindメソッドの引数に指定した場合自動的に整数型に変換される。
params[:id]にはURLの/users/1の1の部分が格納されている。

#####演習
1.

```erb:show.html.erb
<%= @user.name %>,<%= @user.email %><br>
<%= @user.created_at %><br>
<%= @user.updated_at %>
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617753/5148b74f-22fb-f3b1-e416-e4c219d126f2.png)

2.

```erb:show.html.erb
<%= @user.name %>,<%= @user.email %><br>
<%= Time.now %>
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617753/450a1495-a356-2145-82bd-50c1adc4218f.png)


####debuggerメソッド
debugメソッドを使うことでアプリケーションの状態を確認できた。
debuggerメソッドも使ってデバッグしてみる。

debuggerを差し込むとdebuggerが読まれた時点での変数などの状態を確認することができるため
デバッグに非常に便利。
今後のアプリ開発で正体不明なエラーなどが出てきたらdebuggerを差し込んで細かく見ると
エラーの原因がわかるかもしれない。

#####演習
1.paramsにto_yamlをくっつける。

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

2.コントローラ内で何も定義していないのでnil

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


※debuggerをさしっぱなしにすると必ずその行で止まるようになるので使わないときは消しておく。

####Gravatar画像とサイドバー
Gravatarというサービスを使って画像とメールアドレスを関連付けておけばGravatarの画像パスを構成するだけで
自動的にGravatarに登録した画像が登録される優れもの。

gravatar_forメソッドを定義していく。
gravatar_forはユーザーオブジェクトを渡すと画像ファイルを返すヘルパーメソッド

```
  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
```
例のごとく、最後のimage_tagは暗黙の返り値になっていることに注意

ユーザーのメールアドレスをGravatarで画像に紐づけたメールアドレスに変更する。

```
>> User.first.update_attribute(:email,"take.webengineer@gmail.com")
   (0.4ms)  SELECT sqlite_version(*)
  User Load (0.1ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
   (0.1ms)  begin transaction
  User Update (9.9ms)  UPDATE "users" SET "email" = ?, "updated_at" = ? WHERE "users"."id" = ?  [["email", "take.webengineer@gmail.com"], ["updated_at", "2020-06-11 12:21:07.548685"], ["id", 1]]
   (3.1ms)  commit transaction
=> true
```

モックアップに近づけるためにshow.html.erbとcustom.scssを編集する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617753/3558c12e-3982-03c2-6176-441d42d14dd9.png)

ちょっとスタイリッシュになる。

#####演習
1.やっているので省略。

2.オプションハッシュsizeに代入する(デフォルト値は80)

```rb
  def gravatar_for(user,options={ size: 80})
    size = options[:size]
    gravatar_id = Digest::MD5::hexdigest(user.email.downcase)
    gravatar_url = "https://secure.gravatar.com/avatar/#{gravatar_id}?s=#{size}"
    image_tag(gravatar_url, alt: user.name, class:"gravatar")
  end
```

3.キーワード引数sizeに代入する(デフォルト値は80)

```rb
```rb
  def gravatar_for(user,size: 80)
    gravatar_id = Digest::MD5::hexdigest(user.email.downcase)
    gravatar_url = "https://secure.gravatar.com/avatar/#{gravatar_id}?s=#{size}"
    image_tag(gravatar_url, alt: user.name, class:"gravatar")
  end
```

オプションハッシュは
オプション名={ハッシュ}の形式で指定する。ただし入れ子になったハッシュなので
size = options[:size]としないとsizeとしては使えない。
キーワード変数として指定するとデフォルト値を指定することができ、デフォルト値が指定されているときは
引数を省略してもOKという便利もの
感覚的にオプションハッシュの使いやすいバージョンみたいな感じで使える。

###ユーザー登録フォーム
ユーザープロフィールページがとりあえず出来上がったのでユーザー登録フォームを作成する。

####form_withを使用する
form_withはActiveRecordオブジェクトを取り込み、それらの属性でフォームを構築する。
ユーザー作成ページ/signupはusers#newに紐づけられているので
newアクションにform_withで必要になるUserオブジェクトを定義しておく。
```@user = User.new```
formのerbとscssも作成する。

#####演習
1.

```erb
<div class="row">
  <div class="col-md-6 col-md-offset-3">
    <%= form_with(model: @user, local: true) do |foobar| %>
      <%= foobar.label :name %>
      <%= foobar.text_field :name %>

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

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

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

      <%= foobar.submit "Create my account", class: "btn btn-primary" %>
    <% end %>
  </div>
</div>
```
これでも動くには動くが
formの略称としてfを用いているためfoobarなどのような意味のない、関係のない文字列を使うのはよろしくない。

####フォームHTML
要点を簡潔にまとめる。

・local: trueはデフォルトだとAjaxを使って送信する。Ajaxによる送信をキャンセルするオプション。

・fオブジェクトはHTMLフォーム要素に対応するメソッドに対して@userの属性を設定するためのHTMLを返す。

・form_withで生成されるHTMLを確認したい場合はブラウザでソースを確認する。Windows民はF12キーで閲覧可能。

・テキスト、メールアドレス、パスワードにそれぞれtypeを指定するとパスワードなら文字が隠蔽されたり、メールアドレスなら
スマホなどでメールアドレス入力用のキーボードが表示されたりなどの違いがある。

・inputタグのname属性の値を使って初期化したハッシュ(params)を構成する。

・form_withに@userを指定した際新しいUserか既に存在するUserかで処理が分かれる。
今回は@userは作成したばかりの新しいUserオブジェクトなので新しいオブジェクトを作成するために
POSTリクエストを送信するためformタグのmethod属性もPOSTになる。

・form_withでフォームを生成した際にはCSRFと呼ばれる攻撃を防ぐためのHTMLを自動で生成してくれる。

#####演習
1．HTMLだけではformを使ってデータを送信することはできないから。

###ユーザー登録失敗
無効なデータを送信した際エラーを返して再入力を促すようなフォームを作成する。

####正しいフォーム
newアクションのフォームページで入力した内容はcreateアクションへ送られる。
処理の流れは
signupページでフォームにデータが入力される。
↓
createアクションにデータが送られる。
↓
createアクション内でUser.newを使ってユーザーオブジェクトを作成
↓
作成したユーザーオブジェクトを保存→失敗したらもう一度signupページを表示するように設定する。


createアクションにこのような記述がある。
```@user = User.new(params[:user])```
この行ではフォームページで入力したデータがparamsハッシュに入っており:userシンボルを渡すことで
代入できる。
```@user = User.new(params[:user])```
このコードは古いRailsなら動作するが新しいRailsではマスアサインメント脆弱性があるので、
エラーとなる。

この対策としてStrong Parametersと呼ばれるものを使う。

####Strong Parameters
以前作成したコードの中に
```@user = User.new(params[:user])```
という行があった。
この行はセキュリティ上大変危険な実装でRails4以降はエラーをはくようになった
何が危険かというと
admin=1のようなユーザーが編集できないはずの属性をpostリクエスト中に紛れ込ませた
だけでデータベースの内容が上書きされてしまうから。
StrongParameterを使うことにより、必須のパラメータと許可するパラメータを指定できる。
これにより安全にデータベースの内容を更新できる。

このStrongParameterを使いやすくするために外部メソッドでuser_paramsを定義するのが一般的。
さらにこのメソッドは外部ユーザーが使う必要はないためprivateの中に書く。そうすることで外部からこのメソッドが使えないようになる。

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

このメソッドを定義し、StrongParameterとして渡すことでとりあえずエラーは起こらなくなるが
まだデータ保存の成功時、失敗時の処理などを実装していないので何もフィードバックがない。
これらをこれから実装していく。

#####演習
1.

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


####エラーメッセージ
ユーザー登録に失敗した時のエラーメッセージを実装していく。

検証に引っかかったオブジェクトは```errors.full_messages```に配列としてエラーメッセージが格納される。

```irb
>> user.save
   (0.1ms)  begin transaction
  User Exists? (0.7ms)  SELECT 1 AS one FROM "users" WHERE "users"."email" IS NULL LIMIT ?  [["LIMIT", 1]]
   (0.1ms)  rollback transaction
=> false
>> user.errors.full_messages
=> ["Password can't be blank", "Password can't be blank", "Password is too short (minimum is 6 characters)", "Name can't be blank", "Email can't be blank", "Email is invalid"]
```

このエラーメッセージをnewページ(signupページ)でパーシャルにまとめて出力し、Bootstrapのform-controlクラスを追加することで
それっぽいエラー表示が出来上がる

```erb:_error.messages.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 %>
```

↑新規作成したerror_messagesパーシャル
```pluralize(@user.errors.count,"error") ```
これにより@user.errors.countが複数(2以上)の時は勝手にerrorsと複数形に直してくれる便利メソッド。
```if @user.errors.any?```
これは@users.errorsに1つでもエラーがある場合にtrueになる。
empty?の逆の効果がある。

#####演習
1.バリデーションを書き換えるとエラー文もそれに合わせて変わることがわかる↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617753/f9922de8-7552-74fc-455e-857852942d62.png)

2.新規作成ページ(newページ)でフォームを送信するとcreateへ飛ぶ。
createではデータの保存に失敗した際、renderでnewアクションを描画するように指定しているため
URLはcreateページのものになる。

#####失敗時のテスト
新規ユーザー登録の一連の動作の統合テストを書く。
```rails g integration_test users_signup```

```rb: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
```

```assert_no_difference 'User.count' do```
でブロック内の処理を行う前と後で引数(User.count)の値が変わらないことをチェックする。
```post users_path,params {user:{~```
はcreateアクションにparams[:user]の値(フォームの入力値)を送信している。

#####演習
1.テンプレートを埋めるならばこのような形

```rb
  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
```

細かい内容を追加するならばCSSのalert-dangerなどをテストしてもいい。
```assert_select 'div.alert-danger'```

####登録フォームの完成

現段階では無効データの処理はできているが有効なデータの処理ができていないので
有効なデータを入力してsubmitするとフリーズしてしまう。

```
No template found for UsersController#create, rendering head :no_content
Completed 204 No Content in 348ms (ActiveRecord: 8.5ms | Allocations: 6337)
```

これはcreateアクションに有効なビューがないため。
アクションでは処理が終わったら対応するビューを読み込むため
データが有効な場合```if @user.save```でtrueになりそのままアクションの処理が終わるので
createビューを読みに行く。createビューは作成していないためエラーになる。
しかし今回はcreateアクションではユーザーを新規作成(データベースに保存)できればいいのでビューを作らず
ユーザーを保存した後は作成したユーザのプロフィールページに飛ぶようにする。

```rb
  def create
    @user = User.new(user_params)
    if @User 
      redirect_to @user ##redirect_toは指定したページにリダイレクトするメソッド
    else
      render 'new'
    end
  end
```

ここで```redirect_to @user```という行があるが
これ、**意味不ポイント!!**
ここでしっかり理解しないとこれからもずっと????状態のため
頑張って理解してほしいポイント...
```redirect_to @user```は正確には```redirect_to user_path(@user)```となる。
Userリソースのオブジェクトを渡すとそのユーザーのプロフィール(個別ページ)が見たいんだなと
Railsが勝手に察してくれるため、```redirect_to @user```でも動く。
効率化のための機能だが私たち初学者には詰みの原因になるので勘弁していただきたいところ。
まあ覚えれば便利なのでしっかり理解して進もう。

#####演習
1.

```irb
>> User.create(name:"Anpanman",email:"anpantabetai@sample.com",password:"foobar",password_confirmation:"foobar")
   (1.4ms)  SELECT sqlite_version(*)
   (0.1ms)  begin transaction
  User Exists? (0.7ms)  SELECT 1 AS one FROM "users" WHERE "users"."email" = ? LIMIT ?  [["email", "anpantabetai@sample.com"], ["LIMIT", 1]]
  User Create (3.9ms)  INSERT INTO "users" ("name", "email", "created_at", "updated_at", "password_digest") VALUES (?, ?, ?, ?, ?)  [["name", "Anpanman"], ["email", "anpantabetai@sample.com"], ["created_at", "2020-06-13 14:33:31.718157"], ["updated_at", "2020-06-13 14:33:31.718157"], ["password_digest", "$2a$12$WJ1/TrXoJLq.c3Q9KetVq.h4VmV6cTkrGf92wzQcpigckRj1ZCKPm"]]
   (18.0ms)  commit transaction
=> #<User id: 4, name: "Anpanman", email: "anpantabetai@sample.com", created_at: "2020-06-13 14:33:31", updated_at: "2020-06-13 14:33:31", password_digest: [FILTERED]>
```

2.

```rb
  def create
    @user = User.new(user_params)
    if @user.save
      redirect_to user_url(@user)
    else
      render 'new'
    end
  end
```
これでも同じ動作をする。

####flash
ユーザーを作成した場合には”ユーザーが作成されました!”とか
削除した際には”削除しました”というようなそのページ内から移動するまでのほんの少しの間表示する
ステータスメッセージを表示する。
投稿に成功しました、というようなメッセージも大体これ。

このような同じページ内でその時だけ表示される一時的なメッセージを作成したい場合はRailsでは
flashという特殊な変数を使う。

```rb
  def create
    @user = User.new(user_params)
    if @user.save
      flash[:success] = "Welcome to the Sample App!"
      redirect_to user_url(@user)
    else
      render 'new'
    end
  end
```
flash[:success]にユーザー作成に成功した際のメッセージを格納しておく。
こうすることでリダイレクト先で一度だけそのメッセージを表示することができる。

あとはflashに代入したメッセージをレイアウトに組み込んでflashが存在するときのみ
flashを表示するように指定する。

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

#####演習
1.文字列の式展開でシンボルを入れると:が除かれたものが返ってくる

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

2.考えろと言われても答えが出ている気がするが解説。
:successキーと:dangerキーはシンボルだが
シンボルを文字列の式展開に代入すると：を取り除いたものが出力される。

```irb
>> flash = { success: "It worked!", danger: "It failed." }
=> {:success=>"It worked!", :danger=>"It failed."}
>> flash.each do |key, value|
?>  puts "#{key}"
>>  puts "#{value}"
>> end
success
It worked!
danger
It failed.
=> {:success=>"It worked!", :danger=>"It failed."}
```

####実際のユーザー登録
データベースの内容がごちゃごちゃになっている可能性があるのでとりあえずリセットしてみる。
```rails db:migrate:reset```
リセットした後、フォームでユーザーを新規作成すると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617753/105342b5-6c00-ffa8-c370-b1ce3161b0cc.png)

flashのウェルカムメッセージが緑色(alert-successクラス)で表示され、ユーザーが作成される。
ページを再読み込みさせるとこのウェルカムメッセージは消える。

#####演習
1.

```irb
>> User.find_by(email:"take.webengineer@gmail.com")
   (0.4ms)  SELECT sqlite_version(*)
  User Load (1.2ms)  SELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT ?  [["email", "take.webengineer@gmail.com"], ["LIMIT", 1]]
=> #<User id: 1, name: "take", email: "take.webengineer@gmail.com", created_at: "2020-06-14 02:57:10", updated_at: "2020-06-14 02:57:10", password_digest: [FILTERED]>
>> 
```
2.[試した結果](
https://camo.qiitausercontent.com/69c0d5bfd0917054af81621a2b6390b63e234ab5/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3631373735332f31303533343262352d366330302d666661382d633337302d6231636533313631623063632e706e67)

####成功時のテスト
失敗した時のテストは書いたので次は成功した時のテストを書いていく。

```rb
  test "valid signup information" do
    get signup_path
    assert_difference 'User.count', 1 do
      post users_path, params:{user:{name:"sample",
                                     email:"sample@rails.com",
                                     password:"foobar",
                                     password_confirmation:"foobar"}}
      end
      follow_redirect!
      assert_template 'users/show'
  end
```

assert_differenceでは第1引数が第2引数分、ブロック内の処理を行う前と行った後で変化することをテストする。
つまりcreateページに有効なユーザー作成情報を送信してユーザーが実際作成されることをテストする。
```follow_redirect!```はリダイレクト先に移動するメソッド。
このメソッドによってこの段階では作成したユーザーのshowページにいるので
```assert_template```で'users/show'テンプレートが表示されているかを確認している。

また最後の行でこの```assert_template```を実行することでshowページを全体的にテストしている。
つまりshowページでエラーが起きたりうまく表示されないときもエラーとしてはきだしてくれるので
この一行で重要な機能をしっかり確認してくれる。

#####演習
1.テキストに関するテストは文章が間違っていたり、テキストそのものを変更しただけで簡単に壊れるので
今回はflashに何らかの文が入っていることをテストする。
```assert_not flash.empty?```

2.```<%= content_tag(:div,message,class:"alert alert-#{message_type}") %>```
この行では第1引数で要素(div要素)を指定、第2引数で要素の中身(テキストコンテンツ)を指定、
第3引数でclassを指定する。こうすることでerbだけで書けるのでわかりやすく簡潔になる。

3.リダイレクトする先がない(指定されていない)と怒られる。

```
RuntimeError:         RuntimeError: not a redirect! 204 No Content
            test/integration/users_signup_test.rb:26:in `block in <class:UsersSignupTest>'
```

4.有効なユーザー情報を送ったときにはユーザーが一人増えるというテストに対して
createアクションではfalseに書き換えたため、ユーザーを作成する行が実行されないためテストでも
```"User.count" didn't change by 1.```→User.countが変わってないよと怒られる。

```
 FAIL["test_valid_signup_information", #<Minitest::Reporters::Suite:0x0000559122566bd0 @name="UsersSignupTest">, 1.1665384099906078]
 test_valid_signup_information#UsersSignupTest (1.17s)
        "User.count" didn't change by 1.
        Expected: 1
          Actual: 0
        test/integration/users_signup_test.rb:20:in `block in <class:UsersSignupTest>'
```

###プロのデプロイ
この章の実装で実際にユーザーを作成し、データベースに保存できるようになった。
ユーザー登録を安全に行うために設定を追加していく。
まずはいつも通りGitのコミット、プッシュを行っておく。

####本番環境でのSSL
本番環境で実際にユーザーを作るとネットワークを入力したデータが流れていくが、暗号化されていないと
Passwordやメールアドレスなど漏洩しては困る情報などが簡単に捕捉されてしまう。
これを防ぐために本番環境ではSSLを使って暗号化することによって
以降のウェブサイトのセキュリティを強化する。

ブラウザにSSL使用を強制することでhttpsで安全に通信が行える。

```  config.force_ssl = true```
production.rbのコメントアウトされているこの行を有効にするだけで完了。

あとはサーバーのSSLをセットアップするだけ
独自ドメインの場合はSSL証明書を購入してセットアップする必要があるが
HerokuのSSLに便乗(herokuapp.com)すれば簡単にSSLを使うことができる

####本番環境用のWebサーバー
本番環境用のWebサーバーはデフォルトではWEBrickになっているがトラフィックの増加に弱いので
多くのトラフィックにも強いPumaサーバーに変える。

Rails5以降はデフォルトでPumaが使えるようになっているので
Pumaを走らせるための設定ファイルを作成するだけでいい。

```yml:database.yml
# SQLite. Versions 3.8.0 and up are supported.
#   gem install sqlite3
#
#   Ensure the SQLite 3 gem is defined in your Gemfile
#   gem 'sqlite3'
#
default: &default
  adapter: sqlite3
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  timeout: 5000

development:
  <<: *default
  database: db/development.sqlite3

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  <<: *default
  database: db/test.sqlite3

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'] %>
```

Herokuの公式ドキュメントに色々今回の情報も載っているので参考にリンクを置いておく
[Heroku公式ドキュメント(Rails)](https://devcenter.heroku.com/articles/getting-started-with-rails6)

#####演習
1.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617753/73bf04c6-b131-d6bb-9977-b59ce9c56a2e.png)
鍵がついている(https)　→　SSLで通信している。

2.表示される。(development環境と同じ)




[前の章へ](https://qiita.com/take_webengineer/items/497fc90d7c6f9bc9a0ff)

[次の章へ](https://qiita.com/take_webengineer/items/fce014c8aeee9a0d7201)