Ruby Ruby on Rails Web開発 プログラミング

Rails 8.1 + Devise ログイン実装まとめ(login_id + password 版)

開発環境

  • Rails 8.1.2
  • Ruby 3.3.7
  • PostgreSQL
  • Devise 5

この記事を書いてる人

082p
082p

ご訪問、ありがとうございます!

システムエンジニア兼動画クリエーターとして活動しています。
主にRubyを得意とし、Ruby on Railsを中心にWebアプリケーション開発を行っています。
業務ではSQLやJavaScriptに触れることも多く、バックエンドからデータベースまで幅広く対応しています。
このブログでは、Ruby on RailsやPython(Django)などのWebアプリケーション開発やデータベース関連の技術記事を中心に、時々C#やWPFなどの開発内容についても発信しています。

認証方式のカスタマイズ

  • デフォルトの email + password ではなく login_id + password でログイン
  • SaaS構造に合わせて、ユーザーは会社(Company)と拠点(Workspace)に所属
Company(契約会社)
 └ Workspace(支店)
     └ User(ログインユーザー)

users テーブル設計(例)

create_table :users do |t|
  t.string :login_id, null: false
  t.string :encrypted_password, null: false, default: ""
  t.integer :role, default: 1, null: false
  t.references :company, foreign_key: true
  t.references :workspace, foreign_key: true
  t.datetime :remember_created_at
  t.timestamps null: false
end

add_index :users, :login_id, unique: true



role: 権限管理用(例:super_admin = 9, regular = 1)

Devise 設定

# config/initializers/devise.rb
config.authentication_keys = [:login_id]
config.case_insensitive_keys = [:login_id]
config.strip_whitespace_keys = [:login_id]

User モデル(メール無し、login_id + password)

class User < ApplicationRecord
  devise :database_authenticatable,
         :registerable,
         :rememberable  # :validatable は外す

  validates :login_id, presence: true, uniqueness: true
  validates :password, presence: true, length: { minimum: 6 }, confirmation: true, if: :password_required?

  def password_required?
    new_record? || !password.nil? || !password_confirmation.nil?
  end

  def super_admin?
    role == "super_admin"
  end
end
  • :validatable は使用せず、自前でパスワードバリデーション
  • super_admin? メソッドで権限チェック

ApplicationController 設定

class ApplicationController < ActionController::Base
  before_action :authenticate_user!  # ログイン必須

  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_in, keys: [:login_id])
  end
end
  • ログイン必須ページは全て authenticate_user!
  • Devise に login_id を追加

管理者専用ユーザー管理コントローラー

# app/controllers/admin/users_controller.rb
class Admin::UsersController < Admin::ApplicationController
  before_action :require_super_admin

  # 新規ユーザー作成フォーム
  def new
    @user = User.new
  end

  # ユーザー作成処理
  def create
    @user = User.new(user_params)
    if @user.save
      redirect_to admin_new_user_path, notice: "ユーザーを作成しました"
    else
      render :new, status: :unprocessable_entity
    end
  end

  private

  # 管理者かどうかチェック
  def require_super_admin
    unless current_user&.super_admin?
      redirect_to root_path, alert: "アクセス権がありません"
    end
  end

  # 許可パラメータ
  def user_params
    params.require(:user).permit(:login_id, :password, :password_confirmation, :role, :workspace_id, :company_id)
  end
end
  • super_admin しか新規ユーザー作成できない
  • render :new, status: :unprocessable_entity でバリデーションエラーも表示

ビュー(TailwindCSS)

<!-- app/views/admin/users/new.html.erb -->
<div class="max-w-md mx-auto mt-10 p-6 bg-white rounded shadow">
  <h1 class="text-2xl font-bold mb-6">新規ユーザー作成(スーパーユーザー専用)</h1>

  <% if @user.errors.any? %>
    <div class="mb-4 p-4 bg-red-100 text-red-700 rounded">
      <h2 class="font-bold mb-2">入力エラーがあります:</h2>
      <ul class="list-disc list-inside">
        <% @user.errors.full_messages.each do |msg| %>
          <li><%= msg %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <%= form_with model: @user, url: admin_users_path, local: true do |f| %>
    <%= f.label :login_id %>
    <%= f.text_field :login_id %>

    <%= f.label :password %>
    <%= f.password_field :password %>

    <%= f.label :password_confirmation %>
    <%= f.password_field :password_confirmation %>

    <%= f.label :role %>
    <%= f.select :role, User.roles.keys.map { |r| [r.humanize, r] } %>

    <%= f.label :workspace_id, "所属拠点" %>
    <%= f.collection_select :workspace_id, Workspace.all, :id, :name %>

    <%= f.label :company_id, "会社" %>
    <%= f.collection_select :company_id, Company.all, :id, :name %>

    <%= f.submit "作成", class: "bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700" %>
  <% end %>
</div>
  • パスワード短い / 確認不一致 / login_id 重複もすべて赤文字で表示
  • TailwindCSS でスタイリング

ルーティング

namespace :admin do
  get "users/new", to: "users#new", as: :new_user
  post "users", to: "users#create", as: :users
end

devise_for :users
  • Devise でログイン機能を提供
  • 管理者は独自に新規ユーザー作成ページを使用

ポイントまとめ

  • Devise + login_id + password の SaaS 向けカスタマイズ
  • super_admin だけが管理者ユーザーを作成可能
  • パスワードバリデーションは :validatable を使わず自前実装
  • エラー表示は TailwindCSS で一目でわかる

-Ruby, Ruby on Rails, Web開発, プログラミング