Ruby on Rails 【ログイン機能実装】

**開発環境**
PC: mac
OS: macOS Mojave 10.14.6
ruby:2.6.3
rails:6.0
***
##概要
rails初心者がユーザー登録からログイン認証までの記録を綴る。

##ユーザー認証機能（ログイン機能）の仕組みとは？
###1.そもそもブラウザーとサーバーの通信とは？
1.ブラウザー（クライアント）からサーバーへリクエストを送信
2.サーバーがリクエストを受け取り、リクエスト内容を処理してブラウザー（クライアント）へ情報を送信
3.ブラウザーが情報を受け取りHTMLで表示する。
**このプロセスはHTTPプロトコルの取り決めに基づいて行われる。**

##2.HTTPプロトコルの技術でユーザー承認をするにあたって必要な事
１.の通信プロトコルだけではユーザ承認はできない。
**何故なのか？**
→2回目以降に通信をした時に、アクセスしたユーザーが誰なのか判別出来ない。
このような状態のことを**ステートレス**という。

このステートレスな状態を解消するのが、session管理をして解決する。
###ではどのようにすればいいのか？
1.1回目のアクセスでログイン承認した場合、サーバー側からブラウザーへsessionIDを渡す。
2.ブラウザー側ではCookieにsessionIDにセットされる。
3.2回目以降にアクセスした場合、サーバー側がCookie情報にセットされているsessionIDを識別して、ログインしているか、していないかを判別していく。
※Cookie（クッキー）とはブラウザーに小さな情報を保存できるブラウザーの機能

##Step1：modelの作成
`rails g model mail:string password_digest:string`でマイグレーションファイルを作る。

`password_digest`（パスワードダイジェスト）メソッドはRailsが用意しているメソッド。
暗号化したパスワードを用意してくれる。
そのため、**オリジナルの名前でカラム名を作成してはNG。**

##Step2:migrateファイルのバリテーションを設定
```migrate.rb
class Createusers < ActiveRecord::Migration[6.0]
  def change
    create_table :users do |t|
      t.string :mail, null: false #null: falseは空白で登録できないようにする
      t.string :password_digest, null: false　#null: falseは空白で登録できないようにする

      t.timestamps
    end
    add_index :users, :mail, unique: true　#名前の登録を重複させないためにユニークに設定する。
  end
end
```
##Step3:session情報を管理するコントローラーの作成
コマンド
`rails g controller sessions create destroy --skip--temprate-engine`
`--skip--temprate-engine`はviewは作成しないのでオプションを設定している。

```sessions_controller.rb
class SessionsController < ApplicationController
  def create
  end

  def destroy
  end

end
```

###homeコントローラの設定
目的はRootとなるページを作成する。
※すでにある場合は省略
コマンド
`rails g controller home index`

```home_controller.rb
class HomeController < ApplicationController
  def index
  end
```

###userコントローラの作成
コマンド
`rails g controller users new create me `
目的：ユーザー登録するためのコントローラー
`new`はユーザー作成フォームを作成するアクション
`create`はユーザー作成フォームに入力されたものを保存するアクション
`me`はログイン中のユーザーのマイページを表示するアクション
※usersコントローラーを作成した場合、使用しないcreate.html.erbも作成されてしまうので削除

```users_controller.rb
class UsersController < ApplicationController
  def new
  end

  def create
  end

  def me
  end
end
```
#rootの設定

####当初はこのように設定されているはず。こちらを変更していく。
```root.rb
Rails.application.routes.draw do
  get 'users/new'
  get 'users/create'
  get 'users/me'
  get 'home/index'
  get 'sessions/create'
  get 'sessions/destroy'
  post 'login', :to 'sessions#create'
  delete 'logout', :to 'sessions#destroy'

  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end
```

変更後は以下のうように設定。

```root.rb
Rails.application.routes.draw do
  get 'mypage', :to 'users#me'
  post 'login', :to 'sessions#create'
  delete 'logout', :to 'sessions#destroy'
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
  root 'home#index'
  resources :users, only: %i[ new create]
end
```

#Step4：UserModelにユーザー承認機能を設定する。

```user.rb
class User < ApplicationRecord
    has_secure_password
    #追加される2つの機能。
    #password属性
    #password_confirmation属性
    #上記二つはパスワードとパスワード再確認フォームに入力された値が同じかどうかを確認するための機能。
    validates :name,
    presence: true,
    uniqueness: true,
    length: { maximum: 16 },
    format: {
        with: /\A[a-z0-9]+\z/,
        message: 'は小文字英数字で入力してください'
    }
    validates: password,
    length: { minimum: 8 }
end
```
`has_secure_password`は2つの機能を付与することができる。
1.password属性
2.password_cofirmation属性
上記二つの昨日はパスワードとパスワード再確認フォームに入力された値が同じかどうかを確認するための機能。

`validates`名前カラムにバリテーションを付与する。
`presence`は空白をバリテートする
`uniqueness: true`は重複をさせないために設定
`length: { maximum: 16}`は最大入力文字数

`format: {with: /\A[a-z0-9]+\z/,
        message: 'は小文字英数字で入力してください'
}`は小文字英数字のみを入力できるようにし、それ以外の入力があった場合はエラーメッセージを表示させる。