💬
DelegatedTypesで複数のユーザー権限を管理する
DelegatedTypesを使って、管理者と顧客の2つのユーザー情報を管理する。
DelegatedTypesで管理者と顧客で異なるユーザー属性情報を個別のテーブル情報を作成することで管理する。
例えばテーブルはUser、Administrator、Customerの3テーブルとなる。
Userテーブル
id | email_address | userable_type | user_id |
---|---|---|---|
1 | admin-1@example.com | Administrator | 1 |
2 | customer-1@example.com | Customer | 2 |
Administratorテーブル
id | deperatment | employee_code |
---|---|---|
1 | sales | 19 |
Customerテーブル
id | birth | address |
---|---|---|
1 | 2024-12-31 | Tokyo |
DelegatedTypesをユーザーモデルに適用する
railsアプリーケーションを作成する。
gem exec rails new app --devcontainer
bin/rails g authentication
作成されたユーザーテーブルをスーパークラスとしてDelegatedTypesを属性情報を指定する。
bin/rails generate migration AddUserableToUser userable_type:string userable_id:integer
DelegatedTypesで使うAdministratorとCustomerを作成する
bin/rails g model Administrator department:string employee_code:string
bin/rails g model Customer birth:date address:string
UserクラスでDelegatedTypesを宣言する
class User < ApplicationRecord
has_secure_password
has_many :sessions, dependent: :destroy
normalizes :email_address, with: ->(e) { e.strip.downcase }
delegated_type :userable, types: %w[ Administrator Customer ], dependent: :destroy
end
委譲クラスとして、Administrator
とCustomer
が含まれる。
rails consoleからユーザーを作成する
# Customerの作成
User.create!(email_address: "customer-1@example.com", password: "password!", userable: Customer.new(birth: "2024-12-31", address: "Tokyo"))
# Adminの作成
User.create!(email_address: "admin-1@example.com", password: "password!", userable: Administrator.new(department: "sales", employee_code: "19"))
# DelegateTypeによりユーザー判定可能
User.find_by(email_address: "customer-1@example.com").customer?
=> true
User.find_by(email_address: "admin-1@example.com").administrator?
=> true
ユーザーログイン
CustomerとAdministrator用のcontrollerを作成する。
bin/rails g controller admin/home index
bin/rails g controller customer/home index
ユーザーがCustomerかAdministratorかにより画面制御を行う。
class Customer::HomeController < ApplicationController
before_action :require_customer_access
def index
end
private
def require_customer_access
raise ActionController::RoutingError, "Not Found" unless Current.user.customer?
end
end
class Admin::HomeController < ApplicationController
before_action :require_admin_access
def index
end
private
def require_admin_access
raise ActionController::RoutingError, "Not Found" unless Current.user.administrator?
end
end
また、ログイン時に遷移先の切り替えが必要。
module Authentication
def after_authentication_url
session.delete(:return_to_after_authenticating)
if Current.user.administrator?
admin_root_url
elsif Current.user.customer?
customer_root_url
else
root_url
end
end
end
参考
「3. Multiple tables with an association」よりは「4. Active Record delegated_type」のほうが、DelegatedTypesがIFを提供してくれるためより実装がシンプル。
Discussion