LoginSignup
4
2

rails_adminを使用した管理画面の作成

Posted at

環境

Ruby: 3.2.2
Rails: 7.0.6
db: postgresql
css: tailwind css
※ユーザー機能はDeviseを使用

rails_adminとは

Railsアプリケーションの管理画面を自動で作成してくれるgemのこと。
管理画面内でデータのCRUDができるようになる。

cancancanとは

権限管理ができるgemのことで、特定のユーザーがアクセスできるリソースを制限することができる。
例)管理者(admin)ユーザーしか管理画面を使用できないようにする。

導入

Gemfile
gem 'rails_admin', '~> 3.0'
gem 'cancancan'
$ bundle

rails_adminのインストール

$ bin/rails g rails_admin:install
	?  Where do you want to mount rails_admin? Press <enter> for [admin] > #この表示はURLを指定するもので、デフォルトのURLは/adminとなっているため、特に変更の必要がなければ「Enter」
			route  mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
      create  config/initializers/rails_admin.rb
           -  Using [sprockets] for asset delivery method
     gemfile  sassc-rails

このコマンドで管理画面が作成される。

Gemfileに’sassc-rails’が追記されているが、これは管理画面がsassで実装されているため、sassをcssにコンパイルするために必要。

bundle installをしてsassc-railsをインストールしておく。

Abilityクラスの作成(cancancan)

$ bin/rails g cancan:acility
		create  app/models/ability.rb

このコマンドで、Abilityクラスが作成される。

Abilityクラスでは、認可ルールの定義、ユーザー権限の判定、条件の定義を記述する。

例)管理者権限を守るユーザーは管理画面にログインできて、全ての操作をできる。

rails_admin.rbの設定

gem「Devise」を利用してユーザーの認証を実装しているかつ、「cancancan」を利用して特定のユーザーのみのアクセス制限を実装する場合は、以下のコメントアウトされている部分のコメントを外す。

config/initializers/rails_admin.rb
RailsAdmin.config do |config|
  config.asset_source = :sprockets

  ### Popular gems integration

  ## == Devise ==
  config.authenticate_with do
    warden.authenticate! scope: :user
  end
  config.current_user_method(&:current_user)

  ## == CancanCan ==
  config.authorize_with :cancancan
end
  • 「config.authenticate_with do … end」は、管理画面にアクセスする前に認証を行うための設定。具体的には、Deviseの「warden.authenticate!」メソッドを使用して、:userスコープのユーザーを認証している。:userスコープは、Deviseにおいてデフォルトで使用されているスコープ。
  • 「config.current_user_method(&:current_user)」は、Rails_adminでcurrent_userを使用するためのメソッド。
  • 「config.authorize_with :cancancan」は、Rails_adminでのアクセス制限にcancancanを使用するための設定。Abilityクラスで定義されたアクセス権限が適用される。

Abilityクラスの設定

app/models/ability.rb
class Ability
	include CanCan:Ability
	def initialize(user)
		if user && user.admin?
			can :access, :rails_admin
			can :manage, :all
		end
	end
end
  • 「if user && user.admin?」で、ログインしてるユーザーかつ管理者の場合、処理を実行する。
  • 「can :access, :rails_admin」で管理画面にアクセスできる。
  • 「can :manage, :all」で管理画面での全ての機能を使用できる。

管理画面の日本語化

gem ‘rails-i18n’をインストールし、公式ドキュメントの翻訳ファイルをコピーする。

config/locales/views/rails_admin.ja.yml
# 日本語化テンプレ
ja:
  activerecord:
    # 全てのモデル記載
    models:
      user: ユーザー
      post: 投稿
      comment: コメント
      like: いいね
      contact: お問い合わせ
    attributes:
      # 各モデルのカラム名を記載
      user:
        name: 名前
        email: メールアドレス
        password: パスワード
      post:
        content: 説明
        image: 画像
      comment:
        comment: コメント内容
      contact:
        name: 名前
        email: メールアドレス
        content: お問い合わせ内容
    errors:
      messages:
        record_invalid: 'バリデーションに失敗しました: %{errors}'
        restrict_dependent_destroy:
          has_one: "%{record}が存在しているので削除できません"
          has_many: "%{record}が存在しているので削除できません"
  date:
    abbr_day_names:
    - 
    - 
    - 
    - 
    - 
    - 
    - 
    abbr_month_names:
    -
    - 1
    - 2
    - 3
    - 4
    - 5
    - 6
    - 7
    - 8
    - 9
    - 10
    - 11
    - 12
    day_names:
    - 日曜日
    - 月曜日
    - 火曜日
    - 水曜日
    - 木曜日
    - 金曜日
    - 土曜日
    formats:
      default: "%Y/%m/%d"
      long: "%Y年%m月%d日(%a)"
      short: "%m/%d"
    month_names:
    -
    - 1
    - 2
    - 3
    - 4
    - 5
    - 6
    - 7
    - 8
    - 9
    - 10
    - 11
    - 12
    order:
    - :year
    - :month
    - :day
  datetime:
    distance_in_words:
      about_x_hours:
        one: 1時間
        other: %{count}時間
      about_x_months:
        one: 1ヶ月
        other: %{count}ヶ月
      about_x_years:
        one: 1
        other: %{count}
      almost_x_years:
        one: 1年弱
        other: "%{count}年弱"
      half_a_minute: 30秒前後
      less_than_x_seconds:
        one: 1秒以内
        other: "%{count}秒未満"
      less_than_x_minutes:
        one: 1分以内
        other: "%{count}分未満"
      over_x_years:
        one: 1年以上
        other: "%{count}年以上"
      x_seconds:
        one: 1
        other: "%{count}秒"
      x_minutes:
        one: 1
        other: "%{count}分"
      x_days:
        one: 1
        other: "%{count}日"
      x_months:
        one: 1ヶ月
        other: "%{count}ヶ月"
      x_years:
        one: 1
        other: "%{count}年"
    prompts:
      second: 
      minute: 
      hour: 
      day: 
      month: 
      year: 
  errors:
    format: "%{attribute}%{message}"
    messages:
      accepted: を受諾してください
      blank: を入力してください
      confirmation: %{attribute}の入力が一致しません
      empty: を入力してください
      equal_to: %{count}にしてください
      even: は偶数にしてください
      exclusion: は予約されています
      greater_than: %{count}より大きい値にしてください
      greater_than_or_equal_to: %{count}以上の値にしてください
      inclusion: は一覧にありません
      invalid: は不正な値です
      less_than: %{count}より小さい値にしてください
      less_than_or_equal_to: %{count}以下の値にしてください
      model_invalid: 'バリデーションに失敗しました: %{errors}'
      not_a_number: は数値で入力してください
      not_an_integer: は整数で入力してください
      odd: は奇数にしてください
      other_than: %{count}以外の値にしてください
      present: は入力しないでください
      required: を入力してください
      taken: はすでに存在します
      too_long: %{count}文字以内で入力してください
      too_short: %{count}文字以上で入力してください
      wrong_length: %{count}文字で入力してください
    template:
      body: 次の項目を確認してください
      header:
        one: "%{model}にエラーが発生しました"
        other: "%{model}に%{count}個のエラーが発生しました"
  helpers:
    select:
      prompt: 選択してください
    submit:
      create: 登録する
      submit: 保存する
      update: 更新する
  number:
    currency:
      format:
        delimiter: ","
        format: "%n%u"
        precision: 0
        separator: "."
        significant: false
        strip_insignificant_zeros: false
        unit: 
    format:
      delimiter: ","
      precision: 3
      separator: "."
      significant: false
      strip_insignificant_zeros: false
    human:
      decimal_units:
        format: "%n %u"
        units:
          billion: 十億
          million: 百万
          quadrillion: 千兆
          thousand: 
          trillion: 
          unit: ''
      format:
        delimiter: ''
        precision: 3
        significant: true
        strip_insignificant_zeros: true
      storage_units:
        format: "%n%u"
        units:
          byte: バイト
          eb: EB
          gb: GB
          kb: KB
          mb: MB
          pb: PB
          tb: TB
    percentage:
      format:
        delimiter: ''
        format: "%n%"
    precision:
      format:
        delimiter: ''
  support:
    array:
      last_word_connector: "、"
      two_words_connector: "、"
      words_connector: "、"
  time:
    am: 午前
    formats:
      default: "%Y年%m月%d日(%a) %H時%M分%S秒 %z"
      long: "%Y/%m/%d %H:%M"
      short: "%m/%d %H:%M"
    pm: 午後
  # rails_admin日本語化
  admin:
    js:
      true: True
      false: False
      is_present: 存在する
      is_blank: 空白
      date: 日付 ...
      between_and_: ... から ...
      today: 今日
      yesterday: 昨日
      this_week: 今週
      last_week: 先週
      number: 数字 ...
      contains: 含む
      is_exactly: 完全に一致
      starts_with: で始まる
      ends_with: で終わる
      too_many_objects: "対象が多すぎます、上の検索ボックスを使用してください"
      no_objects: "対象が見つかりません"
    loading: "読み込み中..."
    toggle_navigation: ナビゲーション切り替え
    home:
      name: "ホーム"
    pagination:
      previous: "&laquo; 前"
      next: "次 &raquo;"
      truncate: "…"
    misc:
      search: "検索"
      filter: "検索"
      refresh: "更新"
      show_all: "すべて表示"
      add_filter: "絞り込む..."
      bulk_menu_title: "選択項目を..."
      remove: "削除"
      add_new: "新規作成"
      chosen: "選択された%{name}"
      chose_all: "すべて選択"
      clear_all: "選択解除"
      up: "上"
      down: "下"
      navigation: "ナビゲーション"
      root_navigation: "アクション"
      navigation_static_label: "リンク"
      log_out: "ログアウト"
      time_ago: "%{time}前"
      ago: "前"
      more: "さらに %{count} 個以上の %{models_name}"
    flash:
      successful: "%{name}の%{action}に成功しました"
      error: "%{name}の%{action}に失敗しました"
      noaction: "操作を取り消しました"
      model_not_found: "モデル'%{model}'はありません"
      object_not_found: "'ID:%{id}'の%{model}はありません"
    table_headers:
      model_name: "モデル名"
      last_used: "最終アクセス日"
      records: "レコード数"
      username: "ユーザ"
      changes: "変更"
      created_at: "日時"
      item: "アイテム"
      message: "メッセージ"
    actions:
      dashboard:
        title: "サイト管理"
        menu: "ダッシュボード"
        breadcrumb: "ダッシュボード"
      index:
        title: "%{model_label_plural}の一覧"
        menu: "一覧"
        breadcrumb: "%{model_label_plural}"
      show:
        title: "%{model_label} '%{object_label}'の詳細"
        menu: "詳細"
        breadcrumb: "%{object_label}"
      show_in_app:
        menu: "表示"
      new:
        title: "新規%{model_label}"
        menu: "新規作成"
        breadcrumb: "新規"
        link: "新規%{model_label}追加"
        done: "作成"
      edit:
        title: "%{model_label} '%{object_label}'を編集"
        menu: "編集"
        breadcrumb: "編集"
        link: "この%{model_label}を編集"
        done: "更新"
      delete:
        title: "%{model_label} '%{object_label}'を削除"
        menu: "削除"
        breadcrumb: "削除"
        link: "'%{object_label}'削除"
        done: "削除"
      bulk_delete:
        title: "%{model_label_plural}を一括削除"
        menu: "一括削除"
        breadcrumb: "一括削除"
        bulk_link: "選択した%{model_label_plural}を削除"
      export:
        title: "%{model_label}をエクスポート"
        menu: "エクスポート"
        breadcrumb: "エクスポート"
        link: "%{model_label_plural}をエクスポート"
        bulk_link: "選択した%{model_label_plural}をエクスポート"
        done: "エクスポート"
      history_index:
        title: "%{model_label_plural}の更新履歴"
        menu: "履歴"
        breadcrumb: "履歴"
      history_show:
        title: "%{model_label} '%{object_label}'の履歴"
        menu: "履歴"
        breadcrumb: "履歴"
    form:
      cancel: "キャンセル"
      basic_info: "基本情報"
      required: "必須"
      optional: "オプション"
      one_char: "文字"
      char_length_up_to: "最大文字数:"
      char_length_of: "文字数:"
      save: "保存"
      save_and_add_another: "保存して次へ"
      save_and_edit: "保存して編集"
      all_of_the_following_related_items_will_be_deleted: "を削除してよろしいですか? 以下の項目が削除され、もしくは関係を失います:"
      are_you_sure_you_want_to_delete_the_object: "%{model_name}の項目"
      confirmation: "実行する"
      bulk_delete: "以下の項目が削除され、それによって関連する項目が削除され、もしくは関係を失います:"
      new_model: "%{name} (新規)"
    export:
      confirmation: "%{name}としてエクスポート"
      select: "エクスポートするフィールドを選択してください"
      select_all_fields: "全フィールドを選択"
      fields_from: "%{name}のフィールド"
      fields_from_associated: "関連する%{name}のフィールド"
      display: "カラム:%{name} 型:%{type}"
      options_for: "%{name}の出力オプション"
      empty_value_for_associated_objects: "<empty>"
      click_to_reverse_selection: 'クリックで選択を反転します'
      csv:
        header_for_root_methods: "%{name}" # 'model' is available
        header_for_association_methods: "%{name} [%{association}]"
        encoding_to: "文字コード"
        encoding_to_help: "空白の場合は%{name}になります"
        skip_header: "ヘッダなし"
        skip_header_help: "チェックすると出力にヘッダ行を含めません"
        default_col_sep: ","
        col_sep: "区切り文字"
        col_sep_help: "空白の場合は'%{value}'区切りです" # value is default_col_sep

roleカラムの追加

Usersテーブルにroleカラムを追加して、管理者と一般ユーザーを区別できるようにする。

以下のコマンドでマイグレーションファイルを作成

$ bin/rails g migration AddRoleToUser
20230806123456_add_role_to_user.rb
class AddRoleToUser < ActiveRecord::Migration[7.0]
  def change
    add_column :users, :role, :integer, default: 0, null: false
  end
end
$ bin/rails db:migrate
app/models/user.rb
class User < ApplicationRecord
  enum role: { general: 0, admin: 1 }
end

enum-helpのインストール

enumで実装したカラムの日本語化もしておく。

gem 'enum-help'
$ bundle

翻訳ファイルに追記

config/locales/activerecord/ja.yml
ja:
  enums:
    user:
      role:
        general: '一般'
        admin: '管理者'

日本語化ができているか確認する。

$ rails c
irb(main):001:0> user = User.create(name: 'a', email: 'a@example.com', role: 'admin')
=> [#<User_id: 1, name: "a", email: "a@example.com", role: "admin">]

irb(main):002:0> user.role
=> "admin"

irb(main):003:0> user.role_i18n
=> "管理者"

管理画面の確認

image.png

  • すでに作成しているモデルについては、CRUDができるようになっている。
  • 日本語化対応がされている。

最後に

働きながら個人を開発をしている関係で、管理画面に時間を取りたくなかったので、かなり時間を削減することができたと思います。
手軽に管理画面を実装したい場合は、'rails_admin'をオススメします!
今回は以上です!

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2