🐥

[Rails]ゲストログイン機能(ルーティングヘルパーメソッド,名前空間)

2025/03/04に公開

ゲストログイン機能の実装にあたり、自分が疑問に感じた点だけをまとめてます。ご注意ください。

モデル

モデルに以下を書く

class User < ApplicationRecord
  GUEST_USER_EMAIL = "guest@example.com"

  def self.guest
    # (1)
    find_or_create_by!(email: GUEST_USER_EMAIL) do |user|
    # (2)
      user.password = SecureRandom.urlsafe_base64
      user.name = "guestuser"
    end
  end
end

(1) find_or_create_by

データの検索と作成を同時に行うメソッド。
find_or_create_by(条件) でデータがなけれなば作成、ある場合はデータを返す。

(2) SecureRandom.urlsafe_base64

SecureRandom.urlsafe_base64はランダムな文字列を作成するメソッド。

https://zenn.dev/she_techblog/articles/1cbb824044f0df
https://railsdoc.com/page/find_or_create_by
https://api.rubyonrails.org/v7.1.3.4/classes/ActiveRecord/Relation.html#method-i-find_or_create_by
https://docs.ruby-lang.org/ja/latest/method/SecureRandom/s/urlsafe_base64.html
https://zenn.dev/take_tech/articles/9d258b4cafab18


今回出たエラー

Started GET "/users/sign_in" for 127.0.0.1 at 2025-03-04 08:35:12 +0900
ActionController::RoutingError (uninitialized constant Public::SessionsController
            candidate = constant.const_get(name)
                                ^^^^^^^^^^
            raise MissingController.new(error.message, error.name)
            ^^^^^):

ログアウト・ログインのリンクをクリックすると上記が出るようになった。
sessionコントローラをusersフォルダに移動させたことが原因だと思う。

今回はもともとsessionコントローラがあったため、usersフォルダに移動させると、ログインや新規登録のリンクが動かなくなる不具合が発生したため、usersフォルダに移動せずpubricフォルダのまま進めました。

ルーティングヘルパーメソッド

今回のエラーを対応するにあたって、ルーティングヘルパーメソッドを理解してないことが分かった。
出てきたものをまとめていきます。


1. devise_for(Devise のルーティング設定)

意味

devise_forDevise が提供するルーティングを自動生成するためのメソッド
これを使うことで、ログイン・ログアウト・新規登録などのルートを一括定義 できる。

# 3行目
devise_for :admin, skip: [:registrations, :password], controllers: {
  sessions: "admin/sessions"
}
# 30行目
devise_for :users, controllers: {
  registrations: 'public/registrations',
}

💡 何をしているか?

  1. devise_for :admin

    • admin ユーザーの 認証ルートを作成(例:/admin/sign_in など)
    • skip: [:registrations, :password]管理者は新規登録やパスワードリセットをできない
    • controllers: { sessions: "admin/sessions" }ログイン処理 (sessions) だけカスタムコントローラーを使用
  2. devise_for :users

    • users 用の 認証ルートを作成
    • controllers: { registrations: 'public/registrations' }
      新規登録 (registrations) だけカスタムコントローラーを使用
    • ログイン (sessions) のカスタマイズはしていない(デフォルトの devise/sessions を使用)

参考文献

Rails Guide(ルーティング)
https://guides.rubyonrails.org/routing.html#resource-routing-the-rails-default

Devise の公式ドキュメント(Routing)
https://github.com/heartcombo/devise#configuring-routes


2. devise_scope(Devise ルートのカスタマイズ)

意味

devise_scope は、devise_for のルートをさらにカスタマイズしたいときに使う メソッド。

# 7行目
devise_scope :user do
  get '/users/sign_out' => 'devise/sessions#destroy'
  post "users/guest_sign_in", to: "public/sessions#guest_sign_in"
end

💡 何をしているか?

  1. get '/users/sign_out' => 'devise/sessions#destroy'

    • /users/sign_out に GET リクエストを送ると、ログアウト処理 (devise/sessions#destroy) が実行される
    • ただし、Devise はデフォルトで DELETE /users/sign_out を使うため、GET に変更するのは 非推奨
  2. post "users/guest_sign_in", to: "public/sessions#guest_sign_in"

    • /users/guest_sign_inPOST すると、ゲストログイン処理 (public/sessions#guest_sign_in) を実行
    • Devise の標準ルートにないカスタムルートを追加

参考文献

Devise の公式ドキュメント(Routing のカスタマイズ)
https://github.com/heartcombo/devise/wiki/How-To:-Customize-routes


3. scope module:(ネームスペースなしでコントローラーを整理)

意味

scope module: "xxx" は、URL は変更せず、コントローラーの名前空間 (module) だけを変更する

# 25行目
scope module: :public do
  root to: "homes#top"
  get 'about', to: 'homes#about', as: 'about'
  get 'search', to: 'tasks#search'
end

💡 何をしているか?

  • scope module: :public により、以下のルートを Public:: 名前空間のコントローラーに紐付け
    • /Public::HomesController#top
    • /aboutPublic::HomesController#about
    • /searchPublic::TasksController#search

この設定がない場合、homes#topApplicationController を継承した HomesController を探してしまう。

参考文献

Rails Guide(ルーティング) - 名前空間とスコープ
https://guides.rubyonrails.org/routing.html#controller-namespaces-and-routing


4. namespace(URL もコントローラーも変更)

意味

namespace "xxx" は、URL に xxx/ を追加し、コントローラーの名前空間も xxx:: に変更 する。

# 12行目
namespace :admin do
  resources :users, only: [:destroy]
  resources :dashboards, only: [:index] do
    collection do
      get :search
    end
  end
  resources :comments, only: [:index, :destroy]
  resources :tasks, only: [:index, :destroy]
end

💡 何をしているか?

  • namespace :admin により、URL に /admin/ が追加
    • /admin/users/:idAdmin::UsersController#destroy
    • /admin/dashboardsAdmin::DashboardsController#index
    • /admin/commentsAdmin::CommentsController#index

📌 これにより、通常の UsersControllerAdmin::UsersController を分けられる

参考文献

Rails Guide(ルーティング) - 名前空間
https://guides.rubyonrails.org/routing.html#controller-namespaces-and-routing


5. resources(CRUD のルートを一括生成)

意味

resources は、CRUD(Create, Read, Update, Delete)のルートを一括定義する

# 34行目
resources :tasks, only: [:new, :create, :index, :show, :edit, :update, :destroy] do
  resource :favorite, only: [:create, :destroy]
  resources :task_comments, only: [:create, :destroy], as: "comments"
end

💡 何をしているか?

  • /tasks/ に対する CRUD のルートを作成
  • resource :favoritetasks/:task_id/favorite という「単一のお気に入り」ルートを作成
  • resources :task_commentstasks/:task_id/comments のルートを作成

参考文献

Rails Guide(ルーティング) - resources の使い方
https://guides.rubyonrails.org/routing.html#resource-routing-the-rails-default


まとめ

設定 役割
devise_for Devise のルートを一括生成
devise_scope Devise のルートをカスタマイズ
scope module: URL を変えずに名前空間を適用
namespace URL に /xxx/ を追加し、コントローラーの名前空間を変更
resources CRUD のルートを一括生成

「名前空間」とは?

名前空間(ネームスペース、namespace)とは、クラスやモジュールを整理して管理するための仕組み
簡単に言うと、「同じ名前のクラスやメソッドがあっても、区別できるようにするもの」


📌 例:名前空間がない場合

たとえば、UsersController っていうコントローラーがあったとする。

class UsersController < ApplicationController
  def index
    @users = User.all
  end
end

でも、もし 管理者(admin)用の UsersController も作りたい となったら
そのまま UsersController って名前で作ると、どっちの UsersController かわからなくなる


📌 例:名前空間を使う場合

そこで、namespace :admin を使って管理者用のコントローラーを作る ことで、区別できるようになる。

namespace :admin do
  resources :users, only: [:index, :destroy]
end

こうすると、Admin::UsersController っていう「管理者専用の UsersController」を作れる。

class Admin::UsersController < ApplicationController
  def index
    @users = User.all
  end
end

namespace の効果

  • URL も変わる
    • /usersUsersController
    • /admin/usersAdmin::UsersController
  • クラス名が変わる
    • UsersController
    • Admin::UsersController
  • どの UsersController を使うか、Rails がちゃんと判断できる

📌 scope module:namespace の違い

方法 URL コントローラー
namespace :admin /admin/users Admin::UsersController
scope module: :admin /users Admin::UsersController

📌 namespaceURL に admin/ を追加 する。
📌 scope module:URL はそのままで、内部的に Admin:: を付ける

scope module: :public do
  get 'about', to: 'homes#about'
end

例えば、上記だと /about がついたURLになるけど、実際には Public::HomesController が使われる。

Discussion