【Rails，ゲストログイン】削除される度に，同一ゲストユーザーを生成する


## はじめに
ゲストユーザーが削除された際に，「ゲストログイン」ボタン押下で，削除前と同一のゲストユーザーを再生成する方法をまとめました．
Rails初心者の記事です．
不足，間違い等ありましたらご指摘いただけますと幸いです．

## 環境
Ruby 3.0.4
Rails 6.1.7

## ゲストログイン機能の仕様
ゲストログインボタンを押下すると，ゲストユーザーのユーザー情報に合致するユーザーが存在するか照合する．
存在すれば，当該ユーザーでログインする．
存在しなければ，指定したデータを持つゲストユーザーを生成しログインする．

## 実装
### sessionsコントローラでguest_loginアクションを実装
ゲストユーザーの照合，生成を実装します．
また，ゲストユーザーをログインユーザーとして扱うため，セッションに`user.id`を格納します．
ログイン判定は，後述のApplicationControllerで実装しています．
```ruby:app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
  # ログイン前のため，ログイン判定をスキップ．login_requiredは，後述のApplicationControllerで定義．
  skip_before_action :login_required
...
  def guest_login
		# ゲストユーザー情報に合致するレコードをuserに格納．
    user = User.find_by(id: 25, user_name: "guest1", email: "guest1@guest.com", guest: true)

	# ゲストユーザーがDBに存在する場合，
    if user.present?
      # セッションにユーザーidを格納．これを用いて後述のApplicationControllerでログインユーザーかどうか識別．
      session[:user_id] = user.id
      flash[:success] = "「#{user.user_name}」でログインしました．"
      redirect_to root_path

	# ゲストユーザーがDBに存在しない（ゲストユーザーが削除された）場合，
    else
	  # パスワードをランダムに生成し，指定したゲストユーザー情報と併せて，userに格納．
	  # 後述のように，ログインに対してsessionモデルでバリデーションしているめ，パスワードの生成が必須．
      password = SecureRandom.urlsafe_base64
      user = User.new(id: 25, user_name: "guest1", email: "guest1@guest.com", guest: true, password: password, password_confirmation: password)
      if user.save
        session[:user_id] = user.id
        flash[:success] = "「#{user.user_name}」を作成しログインしました．"
        redirect_to root_path
      else
        flash[:danger] = "ゲストユーザーを作成できませんでした．"
        redirect_to login_path
      end
    end
  end
...
end
```
#### ゲストユーザーがDBに存在する場合(`if user.present?`)，
`find_by`メソッドで当該ゲストユーザーのレコードを取得しログインします．
#### ゲストユーザーがDBに存在しない（ゲストユーザーが削除された）場合(`else`)，
`new`メソッドで，削除前と同一（パスワード以外）のゲストユーザーを生成，保存しログインします．
sessionモデル（以下`app/models/session.rb`参照）のログインでバリデーションしているため，パスワードも生成します．
パスワードを`SecureRandom.urlsafe_base64`でランダム生成しているのは，パスワードをコード上に残さないためです．

### sessionモデル
ログイン時にバリデーション(詳細は[こちら](https://qiita.com/takecn/items/48f6a4e11cc695bfb50d)を参照)する仕様としています．
そのため，ゲストユーザーを再生成する際は，上述のようにパスワードの設定が必要になります．
```ruby:app/models/session.rb
class Session
  include ActiveModel::Model

  attr_accessor :user_name, :email, :password, :password_confirmation

  validates :user_name, presence: true
  validates :email, presence: true
  validates :password, presence: true
end
```

### ルーティング
ゲストログイン用のルーティングを設定します．sessionsコントローラの`guest_login`アクションを呼び出します．
```ruby:app/config/routes.rb
Rails.application.routes.draw do
...
  post "/guest_login", to: "sessions#guest_login"
...
end
```

### View
ゲストログインボタンを実装します．
```erb:app/views/sessions/new.html.erb
...
<%= link_to 'ゲストログインする', guest_login_path, method: :post %>
...
```

### ApplicationController
セッションに`user.id`が格納されなければログインできない仕様を以下で設定します．
セッションへの`user.id`の格納は，上記sessionsコントローラで実装しています．
```ruby:app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  helper_method :current_user
  before_action :login_required

  private

  def current_user
    @current_user ||= User.find_by(id: session[:user_id]) if session[:user_id]
  end

  def login_required
    redirect_to login_path unless current_user
  end
end
```
## まとめ
ゲストログイン用のアクションで，ゲストユーザーのユーザー情報を指定し，照合，生成することで「削除される度に，同一ゲストユーザーを生成する」ことができます．

## さいごに
当記事は，万が一，ゲストログインが削除された場合に備えるためのものです．
ゲストログインが勝手に削除されない仕様にするのは必要だと思います．
以上です．
至らない点あればご指摘いただければと思います．

## 参考記事
[簡単ログイン・ゲストログイン機能の実装方法（ポートフォリオ用）](https://qiita.com/take18k_tech/items/35f9b5883f5be4c6e104)