railsチュートリアル第九章 ログイン状態を保持

###ログイン状態を保持
ユーザーの暗号化済みIDと記憶トークンをブラウザの永続cookiesに保存して、永続セッションを作成する準備ができました。
これを```実際に行うにはcookiesメソッド```を使います。

####authenticated?をUserモデルに追加する
app/models/user.rb

```rb
class User < ApplicationRecord
.
.
.
  # 渡されたトークンがダイジェストと一致したらtrueを返す
  def authenticated?(remember_token)
    BCrypt::Password.new(remember_digest).is_password?(remember_token)
    # remember_tokenとremamber_digestを比較するもの
    # bycryptで暗号化
    # .is_password?で＝＝の働きをする
    
  end
end
```
トークンとダイジェストの違いがわからん。
####ログインしてユーザーを保持する
app/controllers/sessions_controller.rb

```rb
class SessionsController < ApplicationController
.
.
.
  def create
    user = User.find_by(email: params[:session][:email].downcase)
    # 送信されたメアドを使ってデータベースから取り出す。
    #emailを小文字にする
    if user &.authenticate(params[:session][:password])
    # user  取得したユーザーが有効かどうか？
    # その後にデータベース上にパスワードがあるか？
    # ユーザーログイン後にユーザー情報のページにリダイレクトする
    # &.は省略型
      log_in user
      # ユーザーのブラウザ内の一時cookiesに暗号化済みのユーザーIDが自動で作成
      remember user
      # ダイジェストをデータベースに記憶させる
      redirect_to user
      # 名前付きルート/userのビューを表示する
    else
      flash.now[:danger] = 'Invalid email/password combination'
      # flash.nowでリクエストが発生後メッセージを消滅する
      # エラーメッセージを作成する
        render 'new'
        # newアクションのビューを表示
    end
  end
.
.
.
end
```
####ユーザーを記憶する
app/helpers/sessions_helper.rb

```rb
module SessionsHelper

  # 渡されたユーザーでログインする
  def log_in(user)
    session[:user_id] = user.id
    #sessionメソッドで作成した一時cookiesは自動的に暗号化される
    # ユーザーのブラウザ内の一時cookiesに暗号化済みのユーザーIDが自動で作成
  end
  
   # ユーザーのセッションを永続的にする
  def remember(user)
    user.remember
    # userをデータベースに保存
    cookies.permanent.signed[:user_id] = user.id
    # signed.permanent ユーザーidと記憶トークンを結びつける
    # 攻撃者に奪い取られる可能性があるため
    cookies.permanent[:remember_token] = user.remember_token
  end
.
.
.
end
```

####永続的セッションのcurrent_userを更新する
app/helpers/sessions_helper.rb

```rb
class User < ApplicationRecord
.
.
.
  # 記憶トークンcookieに対応するユーザーを返す
  def current_user
    if (user_id = session[:user_id])
    # ログイン中のidを代入する
    # 永続セッション（ログイン中）にするため
      @current_user ||= User.find_by(id: user_id)
      # カレントユーザーまたは検索結果があったものを代入する
    elsif (user_id = cookies.signed[:user_id])
    # そうでなければ 書名付きクッキーを代入
      user = User.find_by(id: user_id)
      # idでユーザーを探す
      if user && user.authenticated?(cookies[:remember_token])
    　# ユーザーが有効であり、記憶トークンも認証されたら
        log_in user
        # ログインする
        @current_user = user
        # カレントユーザーに代入するかな
        
      end
    end
  end
.
.
.
end
```
テスト

```
ubuntu:~/environment/sample_app (advanced-login) $ rails t
Running via Spring preloader in process 8950
Started with run options --seed 17566

ERROR["test_login_with_valid_information_followed_by_logout", #<Minitest::Reporters::Suite:0x000055a0ef5c93c0 @name="UsersLoginTest">, 1.6133994830006486]
 test_login_with_valid_information_followed_by_logout#UsersLoginTest (1.61s)
ActionView::Template::Error:         ActionView::Template::Error: undefined local variable or method `　' for #<#<Class:0x000055a0eef11190>:0x000055a0ef288cb0>
            app/helpers/sessions_helper.rb:32:in `current_user'
            app/helpers/sessions_helper.rb:43:in `logged_in?'
            app/views/layouts/_header.html.erb:8
            app/views/layouts/application.html.erb:9
            test/integration/users_login_test.rb:43:in `block in <class:UsersLoginTest>'

  24/24: [============================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.99939s
24 tests, 58 assertions, 0 failures, 1 errors, 0 skips
```
```ActionView::Template::Error: undefined local variable or method ```

###演習
1.
ブラウザのcookieを調べ、ログイン後のブラウザではremember_tokenと暗号化されたuser_idがあることを確認してみましょう。

確認
2.
コンソールを開き、リスト 9.6のauthenticated?メソッドがうまく動くかどうか確かめてみましょう。

```
>> user = User.first
   (1.6ms)  SELECT sqlite_version(*)
  User Load (0.8ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> #<User id: 1, name: "a", email: "abc@def.com", created_at: "2021-10-05 04:11:41", updated_at: "2021-10-09 07:53:18", password_digest: [FILTERED], remember_digest: "$..">

>> user.authenticated?
Traceback (most recent call last):
        2: from (irb):2
        1: from app/models/user.rb:48:in `authenticated?'
ArgumentError (wrong number of arguments (given 0, expected 1))
#引数を一つ欲しいらしい。

>> user.authenticated?("")
=> false
>> user.authenticated?("aaaaaa")
=> false
````