複数権限でのdeviseの実装(管理者機能の作成)

管理者機能の作成

今回は、Gemのdeviseを使用して複数権限の管理者権限の作成を実施していく。(Member(会員)とAdmin(管理者))

前提条件

作業環境

エディエタ:AWS

ブラウザ:Google Chrome

Ruby : 3.1.2

Rails : 6.1.7.4

deviseはインストール済み

作業は下記を参照(deviseのインストールまで)

deviseの導入 - takifugu’s blog

作業手順

  1. モデルの作成

  2. コントローラの作成

  3. ビューの作成

  4. ルーティングの記述

  5. 不要な記述の削除

モデルの作成

会員用の情報・管理者用の情報を保存するための会員・管理者テーブルを作成するために下記のコマンドを実行。

$ rails g devise Member  #会員モデルの作成

$ rails g devise Admin  #管理者モデルの作成

上記を実行すると下記のようにファイルが作成される。

$ rails g devise Member
Running via Spring preloader in process 12143
      invoke  active_record
      create    db/migrate/20230905012027_devise_create_members.rb
      create    app/models/member.rb
      invoke    test_unit
      create      test/models/member_test.rb
      create      test/fixtures/members.yml
      insert    app/models/member.rb
       route  devise_for :members

$ rails g devise Admin
Running via Spring preloader in process 12249
      invoke  active_record
      create    db/migrate/20230905012038_devise_create_admins.rb
      create    app/models/admin.rb
      invoke    test_unit
      create      test/models/admin_test.rb
      create      test/fixtures/admins.yml
      insert    app/models/admin.rb
       route  devise_for :admins

作成されたマイグレーションファイルに必要なカラムを追加しマイグレーションする。

$ rails db:migrate
コントローラの作成

deviseのデフォルト設定のまま使用する場合は作成する必要はないが、

deviseのデフォルト設定を変更・追加が必要な場合、この手順でコントローラを作成する。

下記のコマンドを実行する。

$ rails g devise:controllers public  #会員用

$ rails g devise:controllers admin  #管理者用

上記を実行すると下記のようにファイルが作成される。

$ rails g devise:controllers public
Running via Spring preloader in process 29804
      create  app/controllers/public/confirmations_controller.rb
      create  app/controllers/public/passwords_controller.rb
      create  app/controllers/public/registrations_controller.rb
      create  app/controllers/public/sessions_controller.rb
      create  app/controllers/public/unlocks_controller.rb
      create  app/controllers/public/omniauth_callbacks_controller.rb

$ rails g devise:controllers admin
Running via Spring preloader in process 29914
      create  app/controllers/admin/confirmations_controller.rb
      create  app/controllers/admin/passwords_controller.rb
      create  app/controllers/admin/registrations_controller.rb
      create  app/controllers/admin/sessions_controller.rb
      create  app/controllers/admin/unlocks_controller.rb
      create  app/controllers/admin/omniauth_callbacks_controller.rb

上記を実行すると下記のように注意文が出てくることがありますが、後でルーティングを設定する際に変更するため、

この段階では気にしなくて良いです。(※1)

(※1)コントローラの作成時に下記のような注意文が出る。

Some setup you must do manually if you haven't yet:

  Ensure you have overridden routes for generated controllers in your routes.rb.
  For example:

    Rails.application.routes.draw do
      devise_for :users, controllers: {
        sessions: 'users/sessions'
      }
    end

上記を直訳すると、

まだセットアップしていない場合は、手動でセットアップする必要があります: routes.rbで生成されたコントローラのルートをオーバーライドしていることを確認してください。 例えば下記のようなコードにしてください。

となります。この段階では、このようにオーバーライドした形になっていないため、後で記述を変更します。

ビューの作成

次に、会員・管理者用の VIew ファイルを作成します。下記のコマンドを実行する。

$ rails g devise:views publics  #会員用

$ rails g devise:views admins  #管理者用

上記を実行するとファイルが作成される。作成ファイルが多いため、記述は省略する。

ここで作成されたファイル名(publicsとadmins)をコントローラ名と同じに変更する。 (コントローラをpublics、adminsで作成しても良いが、名称を同じにしないと、uninitialized constantエラーが発生するため、注意)

publics → public admins → admin

この記述に伴い、ビューのフォルダ内記述を変更する。(publics→public、admins→adminに変更)

例: views/public/registrations/new.html.erb

[変更前]  <%= render "publics/shared/links" %>

[変更後]  <%= render "public/shared/links" %>
ルーティングの記述

次にルーティングを記述していく。

現在は下記のようなルーティングとなっている。

config/routes.rb

Rails.application.routes.draw do
  devise_for :admins
  devise_for :members

end

先ほども記述したようにこの状態では、作成したコントローラの記述を変更したとしてもその処理を実行することができない。

また、今回はURLも変更するため、この状態では変更することがでない。

そのため、下記の記述に変更していきます。

config/routes.rb

Rails.application.routes.draw do
  # 会員用
  devise_for :members, controllers: {
    registrations: "public/registrations",
    passwords: 'public/passwords',
    sessions: 'public/sessions'
  }

  # 管理者用
  devise_for :admin, skip: [:registrations, :passwords] ,controllers: {
    sessions: "admin/sessions"
  }
end

上記のように記述します。

今回の場合、管理者側では、ログイン機能のみを作成するため、

skipオプションを使用して不要なルーティングを削除しています。

ルーティングの確認。

$ rails routes

上記のように管理者側では、ログイン機能のみのルーティングが作成されます。

不要な記述の削除

ルーティング作成時に管理者側では、ログイン機能のみを実装しましたが、

この状態では、デフォルトのビューに必要ない機能の記述があるため、リンク先がないなどのエラーが発生します。

そのため、管理者側のログイン機能以外の記述を削除していきます。

app/views/admin/shared/_links.html.erb

<%- if controller_name != 'sessions' %>
  <%= link_to "Log in", new_session_path(resource_name) %>
<% end %>

--------------------------------ここから削除--------------------------------
<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
  <%= link_to "Sign up", new_registration_path(resource_name) %>
<% end %>

<%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
  <%= link_to "Forgot your password?", new_password_path(resource_name) %>
<% end %>

<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
  <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %>
<% end %>

<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
  <%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %>
<% end %>

<%- if devise_mapping.omniauthable? %>
  <%- resource_class.omniauth_providers.each do |provider| %>
    <%= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider), method: :post %>
  <% end %>
<% end %>
--------------------------------ここまで削除--------------------------------

上記で記述を削除完了し、サーバーにアクセスすると、ログイン画面が表示される。

以上。