rails 発展その2 ログイン機能

# ログイン機能の作成
```ruby:gemfile
    gem 'devise'
      #上記を記述
```

```bash:ターミナル
   $ pwd
  # 現在のカレントディレクトリの確認

   $ bundle install

   $ rails g devise:install
   # deviseの設定ファイルを作成

　　$ rails g devise user
   # deviseコマンドでモデルを作成
```
   
　　rails g devise コマンド
　　　deviseで、ログイン機能をつける概念のモデルを作成する際に利用するコマンドです。
　　　モデルに加えて、ログイン機能のために必要なカラムが追加されるマイグレーションファイル
　　　などが生成されます。

```bash:ターミナル
　　$ rake db:migrate
  　 # 作成されたマイグレーションファイルを実行
　
　　$ rails g devise:views
# モデルに対応するビューが作成されます。
```
　　　

作成されるビューの一覧です。
 
| ファイルパス | 機能 |
|:--|:--|
| sessions/new.html.erb | ログイン画面 |
| registrations/new.html.erb | ユーザ登録画面 |
| registrations/edit.html.erb | プロフィール情報変更画面 |
| passwords/new.html.erb | メール送信画面(パスワード変更用) |
| passwords/edit.html.erb | パスワード変更画面 |
| confirmations/new.html.erb | メールによる認証を行う画面 |
| unlocks/new.html.erb | アカウントのアンロック画面 |

```bash:ターミナル
　　$ rails g devise:controllers users
    # コントローラを編集する場合、上記のコマンドを実行します。
```


ルーティングの設定もします。
registrations_controller.rb
sessions_controller.rb
使用の時は以下のようにします。

```ruby:config/routes
   devise_for :users, controllers: {
   registrations: 'users/registrations',
   sessions:      'users/sessions',
}
```

# 自動生されるコード、ルーティング

```ruby:config/routes
  devise_for :users
=begin
  上記のコードが自動追加されます
　devise_forはログインまわりに必要なルーティングを一気に生成してくれるdeviseのヘルパーメソッドです。
　例えばdevise_for :usersの記述により、以下のように「ログイン・新規登録」で必要なルーティングが生成
　されます。
　また、後ほど登場するcurrent_userやuser_signed_in?などのヘルパーメソッドも利用できるように
　なります。
=end
```

```ターミナル:ターミナル
  ルーティング周りはuserモデルの場合このような形になります。

　new_user_session GET    /users/sign_in(.:format)       devise/sessions#new
            user_session POST   /users/sign_in(.:format)       devise/sessions#create
    destroy_user_session DELETE /users/sign_out(.:format)      devise/sessions#destroy
           user_password POST   /users/password(.:format)      devise/passwords#create
       new_user_password GET    /users/password/new(.:format)  devise/passwords#new
      edit_user_password GET    /users/password/edit(.:format) devise/passwords#edit
                         PATCH  /users/password(.:format)      devise/passwords#update
                         PUT    /users/password(.:format)      devise/passwords#update
cancel_user_registration GET    /users/cancel(.:format)        devise/registrations#cancel
       user_registration POST   /users(.:format)               devise/registrations#create
   new_user_registration GET    /users/sign_up(.:format)       devise/registrations#new
  edit_user_registration GET    /users/edit(.:format)          devise/registrations#edit
                         PATCH  /users(.:format)               devise/registrations#update
                         PUT    /users(.:format)               devise/registrations#update
                         DELETE /users(.:format)          

```

# ユーザーモデルのモジュール
```ruby:app/models/user.rb
   class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
  end
```

deviseに記述されてるのはモジュールと呼ばれるもので、それぞれ以下のような機能があります。

・database_authenticatable　 DBに保存されるパスワードが正しいかの検証と暗号化
・registerable　 サインアップ処理
・recoverable 　パスワードのリセット
・rememberable 　クッキーにログイン情報を保持
・trackable 　サインイン回数・時刻・IPアドレスを保存
・validatable 　メールアドレスとパスワードのバリデーション
・confirmable 　メール送信による登録確認
・lockable 　一定回数ログインに失敗した際のアカウントロック
・timeoutable 　一定時間でセッションを削除する
・omniauthable　 OmniAuthサポート

必要によって追記と削除をします。

# devise用のストロングパラメーター設定
通常はコントローラーないでストロングパラメーターを設定しますが
devise gemではgemそのものに設定がされてるので
他の方法が必要です。

##   configure_permitted_parametersメソッド(before_actionに記述)
   deviseでは初期状態でサインアップ時にメールアドレスとパスワードのみを受け取るように
   ストロングパラメーターが設定してあるので、パラメーターの追加したい場合はこのメソッドを使用する。

```ruby:controller
    before_action :configure_permitted_parameters, if: :devise_controller?

    def configure_permitted_parameters
      devise_parameter_sanitizer.permit(:ストロングパラメーターを追加したいアクション名, keys: [:追加するキー])
    end

#　例
   before_action :configure_permitted_parameters, if: :devise_controller?

    def configure_permitted_parameters
      devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname])
    end
```

##   devise_parameter_sanitizerメソッド(具体内容を記述)
　　devise_parameter_sanitizerメソッドを使うとdeviseで設定されているstrong_parametersに対してパラメーターを追加することができます

```ruby
   devise_parameter_sanitizer.permit(追加したいメソッドの種類, keys: [:追加したいパラメーター1, :パラメーター2,..])

# 例
  devise_parameter_sanitizer.permit(:account_update, keys: [:name, :age])
```

簡単な追加パラメーター図はこちら

| 引数の値 | 処理 |
|:--|:--|
| :sign_up | 新規登録時 |
| :sign_in | ログイン時 |
| :account_update | レコードの更新時 |

***ここで注意点があります。***
   ・devise_parameter_sanitizerメソッドを直接before_actionに記述してはいけません。
   ・devise_parameter_sanitizerメソッドはdeviseで追加されたメソッドなので
    Deviseのコントローラ以外で呼び出すことができません。

　　具体的な使用方法はこちら

```ruby
    before_action :メソッド名, if: :コントローラ名?
    # ifオプションを指定して使用コントローラーを指定

   # 例

   class ApplicationController < ActionController::Base

    before_action :configure_permitted_parameters, if: :devise_controller?
    # これでdeviseコントローラーのみに指定

    def configure_permitted_parameters
      devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname, :avatar])
    end
    #　メソッドを記述 

  end
```

# deviseのヘルパーメソッド一覧

| メソッド | 用途 |
|:--|:--|
| before_action :authenticate_user! | コントローラーの設定で、ログイン済ユーザーだけにアクセスを許可する |
| user_signed_in? | ユーザーがサインイン済かどうか |
| current_user | サインインしているユーザー情報を取得する |
| user_session | ユーザーのセッション情報にアクセス |

モデル名にUser以外を使用している場合、それぞれのメソッドの『user』部分を書き換える
モデル名がkojinの場合

current_kojin
となる

応用例はこちら

```ruby:controller
def create
      Iken.create(name: iken_params[:name], image: iken_params[:image], text: tweet_params[:text], user_id: current_user.id)
    end

# ikenテーブルにnameとimageとメソッドで指定したユーザーidを保存する。

```

# after_sign_out_path_forメソッド
   deviseでサインアウトしたあとのリダイレクト先を指定するメソッドとして
   after_sign_out_path_forがあります。
   このメソッドでは返り値にサインアウト後のリダイレクト先URLを指定します。

```ruby
    def after_sign_out_path_for(resource)
     '???'            # サインアウト後のリダイレクト先URL
    # 例
     '/users/sign_in' # サインアウト後のリダイレクト先URL
    end
```

# authenticate_user!メソッド
    authenticate_user!はdeviseで使えるメソッドです。
　　　ユーザーがログインしていない場合はログインページにリダイレクトさせます。
　　　before_actionを合わせて使用します。
　　　before_actionのexceptやonly,exceptオプションを組み合わせると特定のアクションを指定することもできます。

```ruby:controller
   class TopController < ReviewController
       before_action :authenticate_user!, except: :index
       # これでindex以外でログインしてなければログインページに遷移します。
   end
```