アプリを作る　ユーザー登録

##ユーザーを登録する
###ユーザーを表示させる

####デバッグ情報を追加する
app/views/layouts/application.html.erb

```
<!DOCTYPE html>
<html>
.
.
.
 <body>
    <%= render 'layouts/header' %>
    <div class="container">
      <%= yield %>
      <!--home.html.erbの内容を代入させる-->
      <%= render 'layouts/footer' %>
      <%= debug(params) if Rails.env.development? %>
      <!--デバック情報を表示させる
      　　if Rails.env.development? 開発環境だけに表示させる-->
    </div>
  </body>
  
</html>
```
####デバックの情報のCSSの表示
app/assets/stylesheets/custom.scss

```css
@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;
}
```

####userのurlのルーティングを作成
config/routes.rb

```rb
Rails.application.routes.draw do
  root 'static_pages#home'
  get  '/signup',  to: 'users#new'
  # signupのurlを入力してuser/newのアクションが動き、htmlが表示される。
  resources :users
  # ユーザー情報を表示するURL（/users/1）を追加するためだけのものではありません
  # ユーザーのURLを生成するための多数の名前付きルートと共に、
  #   アクションが利用できるようになるのです
end
```

####ユーザー情報を表示するための仮のビュー
app/views/users/show.html.erb

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

####新規作成のためにUserコントローラにcreateをアクション
app/controllers/users_controller.rb

```rb
class UsersController < ApplicationController
  def show
    @user = User.find(params[:id])
    # @user インスタンス変数
    # params[:id]の部分はユーザーidの1に置き換わります。
  end
  def new
  end
end
```

これでプレビューを表示させたところid=1がないと表示された。
railsconsoleでインスタンスを作成

```rb
ubuntu:~/environment/my_app (sign-up) $ rails console
Running via Spring preloader in process 7150
Loading development environment (Rails 6.0.3)
2.6.3 :001 > user = User.create(name: "a", email: "abc@def.com", password: "aaaaaa", password_confirmation: "aaaaaa")
   (1.7ms)  SELECT sqlite_version(*)
   (0.1ms)  begin transaction
  User Exists? (0.8ms)  SELECT 1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER(?) LIMIT ?  [["email", "abc@def.com"], ["LIMIT", 1]]
  User Create (10.4ms)  INSERT INTO "users" ("name", "email", "created_at", "updated_at", "password_digest") VALUES (?, ?, ?, ?, ?)  [["name", "a"], ["email", "abc@def.com"], ["created_at", "2021-11-19 15:38:13.272909"], ["updated_at", "2021-11-19 15:38:13.272909"], ["password_digest", "$2a$12$6Sb5WKzynKizowVEO12B0O0EXo09Se9zI32Q11asV.hV4jRTF0JZC"]]
   (6.8ms)  commit transaction
 => #<User id: 1, name: "a", email: "abc@def.com", created_at: "2021-11-19 15:38:13", updated_at: "2021-11-19 15:38:13", password_digest: [FILTERED]> 
```

そしたらshowアクションが動いた。

####デバッグを使い、状況を把握する

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

[3, 12] in /home/ubuntu/environment/my_app/app/controllers/users_controller.rb
    3:   def show
    4:     @user = User.find(params[:id])
    5:     # @user インスタンス変数
    6:     # params[:id]の部分はユーザーidの1に置き換わります
    7:     # Rubyを使ってユーザー名とメールアドレスを表示するにはインスタンス変数であることを前提とする
=>  8:  　  debugger
    9:   end
   10:  
   11:   def new
   12:   end
```
####ユーザーの画像を追加する（アイコンのような物）

```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}"
    # grabatar_urlに代入する
    image_tag(gravatar_url, alt: user.name, class: "gravatar")
    # ユーザーのメアドを元にグラバターの画像を表示させる
  end
end
```

####ユーザー個人の画面
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>
````
####ユーザー登録画面
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_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>
```

####ストロングパラメータをつける
app/controllers/users_controller.rb

```rb
.
.
.
 def create
    @user = User.new(user_params) # 実装は終わっていないことに注意!
    if @user.save
      # 保存の成功をここで扱う。
    else
      render 'new'
    end
  end
  
  private
  
    def user_params
    # ストロングパラメータ
    # 使用制限をつける　user属性を使うときに
      params.require(:user).permit(:name, :email, :password, 
                                     :password_confirmation)
    end
end
```

####エラーメッセージを出すようにする
app/views/users/new.html.erb

```html
<% provide(:title, 'Sign up') %>
<h1>サインイン</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' %>
      <!--class: 'form-control'を入れるとBoostrapがうまく取り扱ってくれる-->

      <%= 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>
```

####そのエラーメッセージの中身
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") %>.
      <!--エラーの数と"error”文字列が表示される-->
    </div>
    <ul>
    <% @user.errors.full_messages.each do |msg| %>
      <li><%= msg %></li>
    <% end %>
    </ul>
  </div>
<% end %>
```

###エラーメッセージのスタイルを決める
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;
  }
}
```

####統合テストで有効でない登録は無効にされることを確認


```rb
require 'test_helper'

class UsersSignupTest < ActionDispatch::IntegrationTest
  test "invalid signup information" do
    get signup_path
    # 名前付きルートでsignup_pathに取得
    assert_no_difference 'User.count' do
    # 有効でないのでデータベースには追加されないことを確認
      post users_path, params: { user: { name:  "",
                                         email: "user@invalid",
                                         password:              "foo",
                                         password_confirmation: "bar" } }
       
      # users#show 
      # 登録ページに情報を登録
    end
    assert_template 'users/new'
    # また登録ページに戻る
  end
end
```

####サインアップ成功時createメソッドの動き
app/controllers/users_controller.rb

```rb
.
.
.
def create
    @user = User.new(user_params) # 実装は終わっていないことに注意!
    if @user.save
      # 保存の成功をここで扱う。
      flash[:success] = "ようこそ自作アプリへ成功しました！"
      redirect_to @user
      # 表示させるユーザーページを
    else
      render 'new'
    end
.
.
.
```

####サインアップの成功時の画面表示
app/views/layouts/application.html.erb

```html
.
.
.
<body>
  <%= render 'layouts/header' %>
  <div class="container">
    <% flash.each do |message_type, message| %>
      <div class="alert alert-<%= message_type %>"><%= message %></div>
    <% end %>
    <%= yield %>
    <!--home.html.erbの内容を代入させる-->
    <%= render 'layouts/footer' %>
    <%= debug(params) if Rails.env.development? %>
    <!--デバック情報を表示させる
   　　if Rails.env.development? 開発環境だけに表示させる-->
  </div>
</body>
```

####成功時の統合テスト

```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!
    # POSTリクエストを送信した結果を見て、指定されたリダイレクト先に移動するメソッド
    assert_template 'users/show'
    # ユーザーページが表示されているか？
  end
end
```