【Rails】deviseを使った認証機能の実装【初学者】

はじめに

Railsアプリに認証機能を導入するには「devise」というGemを使う方法が最も簡単です。「devise」は認証に係る機能をほとんどコードを書くことなく実装できる反面、処理がブラックボックス化されており、全容が把握しづらいというデメリットがあります。Railsで初めて認証機能を導入する場合、まずは簡単な認証機能を自分で実装し、認証機能に関する理解を深めておくことをおすすめします。認証機能を自分で実装する方法については以下の記事を参照してください。

本記事では、「devise」を使った認証機能の実装について説明します。

「devise」の基本的な使い方

「devise」のインストール

「devise」をインストールするには、Gemfileに以下を追記し、bundle installを実行します。

Gemfile

gem 'devise'

次に、ターミナルで以下のコマンドを実行します。

$ rails generate devise:install

上記のコマンドを実行すると以下のファイルが作成されます。

ファイル 説明
config/initializers/devise.rb 「devise」の設定ファイル。
config/locales/devise.en.yml 「devise」の言語ファイル(英語)。

また、初めに行っておく必要のある設定などについて指示されるので、指示に従って設定を行います。

デフォルトURLの設定

「devise」では、ユーザー登録を行う際に入力したメールアドレスにメールを送り、本登録を完了させるという機能を追加することができます。その際、メールに記載するURLのドメイン名をあらかじめ設定しておく必要があります。

開発環境の場合、config/environments/ディレクトリ配下のdevelopment.rbファイルに以下を追記します。

development.rb

Rails.application.configure do
  # 以下を追記
  config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
end

本番環境の場合、config/environments/ディレクトリ配下のproduction.rbファイルに上記の開発環境と同じ設定に対し、ご自分のドメイン名とポートを設定します。以下は設定例です。

production.rb

Rails.application.configure do
  # 以下を追記
  config.action_mailer.default_url_options = { host: 'www.example.com', port: 80 }
end

ルートルーティングの設定

「devise」は、ユーザー登録の完了時やパスワードの変更後にデフォルトのリダイレクト先としてルートに遷移するようになっています。デフォルトのリダイレクト先を変更しない場合は、ルートのルーティングを設定しておく必要があります。

$ rails generate controller Statics index

routes.rb

Rails.application.routes.draw do
  # 以下を追記
  root 'statics#index'
end

デフォルトのリダイレクト先を変更するには、後述する「リダイレクト先の変更」セクションを参照してください。

フラッシュメッセージの表示

「devise」は、ログイン/ログアウト成功時などにフラッシュメッセージを設定します。必須ではありませんが、それらのフラッシュメッセージの表示を設定しておきます。以下はレイアウトにフラッシュメッセージを設定する例です。

application.html.erb

<!DOCTYPE html>
<html>
  <head>
    <title>RailsDevise</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <%# 以下を追記 %>
    <p class="notice"><%= notice %></p>
    <p class="alert"><%= alert %></p>
    <%= yield %>
  </body>
</html>

モデルの作成

「devise」で使用するモデルを作成します。モデル名は通常Userにしますが、これ以外のモデル名にすることもできます。

$ rails generate devise User

上記のコマンドを実行すると、モデルの作成、マイグレーションファイルの作成、ルーティングの追加などが行われます。モデルやマイグレーションには様々なオプションが用意されており、コメントアウトを外し有効にすることでオプションの機能を追加することができます。

モデルおよびマイグレーションの必要な機能を有効にしたら、以下のコマンドを実行します。

$ rails db:migrate

これで「devise」の基本的な機能を使用する準備ができました。

ヘルパーメソッド

「devise」にはコントローラーやビューで使用する様々なヘルパーメソッドが用意されています。なお、以下はモデル名をUserとした場合の例です。例えば、モデル名がMemberの場合、ヘルパーメソッドはauthenticate_member!のようになります。

ヘルパーメソッド 説明
authenticate_user! このヘルパーメソッドを設定したアクションが実行されるとき、ユーザーがログインしていなければログイン画面に遷移する。
user_signed_in? ユーザーがログインしているかどうかを判定する。
current_user 現在ログインしているユーザー情報を取得する。
user_session 現在ログインしているユーザーのセッションを取得する。

authenticate_user!の使い方は以下の通りです。

users_controller.rb

class UsersController < ApplicationController
  before_action :authenticate_user!, only: [:show, :edit, :update, :destroy]

  # アクションは省略
end

「devise」のカスタマイズ

「devise」の日本語化

「devise」で作成されたフォームやフラッシュメッセージを日本語化するには、config/ディレクトリ配下のapplication.rbに以下を追記します。

application.rb

module RailsDevise
  class Application < Rails::Application
    # 以下を追記
    config.i18n.default_locale = :ja
  end
end

次に、Gemfileに以下を追記しbundle installを実行します。

Gemfile

# 以下を追記
gem 'devise-i18n'

一部の文言だけ変更したい場合は、config/locale/ディレクトリ配下にdevise.ja.ymlファイルを作成し、変更したい文言とその訳を追記します。利用可能な文言は同ディレクトリ配下にあるdevise.en.ymlを参照してください。

devise.ja.yml

ja:
  devise:
    sessions:
      signed_in: "ログインに成功しました。"
      signed_out: "ログアウトに成功しました。"

ルーティングの変更

デフォルトのルーティングを変更したい場合、devise_forメソッドのオプションを使用します。

routes.rb

Rails.application.routes.draw do
  devise_for :users, path: 'auth', path_names: [sign_in: 'log_in']
end

上記のようにオプションを追加すると、ログイン画面のルーティングは/users/sign_inから/auth/log_inに変更されます。特定のルーティングを/sign_inのようにしたいなど、より詳細な変更が必要な場合、devise_scopeブロック内に通常のルーティングを記述します。

routes.rb

Rails.application.routes.draw do
  # 以下は残す
  devise_for :users

  # 以下を追記
  devise_scope :user do
    get '/sign_in', to: 'users/sessions#new'
  end
end

上記のように設定すると、/users/sign_inの他に/sign_inも使えるようになります。devise_forを削除してしまうと、devise_scopeブロック内のルーティング以外が使えなくなるのでご注意ください。

カスタムビューの作成

ユーザー登録画面やログイン画面を変更したい場合、カスタムビューを作成します。

$ rails generate devise:views users

上記のコマンドを実行すると、app/views/users/ディレクトリ配下に「devise」で使用するすべてのビューが作成されます。特定のビューのみ作成したい場合は-vオプションを使用します。

$ rails generate devise:views users -v sessions registrations

カスタムビューが存在しない場合はデフォルトのビューが使用されます。

カスタムコントローラーの作成

「devise」の処理を変更したい場合、カスタムコントローラーを作成します。

$ rails generate devise:controllers users

上記のコマンドを実行すると、app/controllers/usres/ディレクトリ配下に「devise」で使用するすべてのコントローラーが作成されます。特定のコントローラーのみ作成したい場合は-cオプションを使用します。

$ rails generate devise:controllers users -c sessions registrations

カスタムコントローラーやカスタムアクションが存在しない場合はデフォルトのコントローラーやアクションが使用されます。

作成したカスタムコントローラーを使用するようルーティングを変更します。

routes.rb

Rails.application.routes.draw do
  # 以下を修正
  devise_for :users, controllers: {
    sessions: 'users/sessions',
    registrations: 'users/registrations'
  }
end

ストロングパラメーターの追加

カスタムビューを作成し、ユーザー登録画面などのパラメーター(IDやパスワードなど)を追加する場合、ストロングパラメーターを追加する必要があります。ストロングパラメーターを追加するには、application_controller.rbに以下を追記します。

application_controller.rb

class ApplicationController < ActionController::Base
  # 以下を追記
  before_action :configure_sign_up_parameters, if: :devise_controller?

  protected
    def configure_sign_up_parameters
      devise_parameter_sanitizer.permit(:sign_up, keys: [:user_name])
    end
end

カスタムコントローラーに追加することもできます(カスタムコントローラーを作成している場合)。

registratioins_controller.rb

class Users::RegistrationsController < Devise::RegistrationsController
  # 以下を追記
  before_action :configure_sign_up_parameters, only: [:create]

  protected
    def configure_sign_up_parameters
      devise_parameter_sanitizer.permit(:sign_up, keys: [:user_name])
    end
end

リダイレクト先の変更

ユーザー登録/解除、ログイン/ログアウトが成功したときのデフォルトの遷移先はルートです。これらのリダイレクト先を変更することができます。ユーザー登録/解除とログイン/ログアウトで変更方法が異なるので分けて説明します。

ユーザー登録/解除のリダイレクト先

以下のコマンドを実行して、「devise」のカスタムコントローラーを作成します。

$ rails generate devise:controllers users

app/controllers/users/ディレクトリ配下のregistrations_controller.rbを以下のように修正します。

registrations_controller.rb

class Users::RegistrationsController < Devise::RegistrationsController
  # 以下のコメントアウトを外す

  # The path used after sign up.
  def after_sign_up_path_for(resource)
    # 以下を修正
    user_path
  end

  # The path used after sign up for inactive accounts.
  def after_inactive_sign_up_path_for(resource)
    # 以下を修正
    new_user_registration_path
  end
end

次に、routes.rbを以下のように修正します。

routes.rb

Rails.application.routes.draw do
  # 以下を修正
  devise_for :users, controllers: {
    registrations: 'users/registrations'
  }
end

ログイン/ログアウトのリダイレクト先

application_controller.rbに以下を追記します。

application_controller.rb

class ApplicationController < ActionController::Base
  # 以下を追記

  def after_sign_in_path_for(resource)
    user_path
  end

  def after_sign_out_path_for(resource)
    new_user_session_path
  end
end

after_sign_in_path_forメソッドおよびafter_sign_out_path_forメソッドは「devise」で実装しているメソッドです。これらのメソッドをオーバーライドしています。

確認メール送信設定

ユーザー登録時に入力されたメールアドレスに確認メールを送信し、メールアドレスの認証を行う機能を追加します。なお、以下の手順は送信元メールにGmailを使用する場合の例です。

カラムの追加

確認メールで使用するカラムをテーブルに追加します。

yyyymmddhhmmss_devise_create_users.rb

class DeviseCreateUsers < ActiveRecord::Migration[6.1]
  def change
    create_table :users do |t|
      ... 

      ## Confirmable
      # 以下のコメントアウトを外す
      t.string   :confirmation_token
      t.datetime :confirmed_at
      t.datetime :confirmation_sent_at
      t.string   :unconfirmed_email # Only if using reconfirmable

      ...
    end
  end
end

テーブル作成後にカラムを追加したい場合、カラム追加のマイグレーションを作成します。

$ rails generate migration add_confirmable_to_users

yyyymmddhhmmss_add_confirmable_to_users.rb

class AddConfirmableToUser < ActiveRecord::Migration[6.1]
  def change
    # 以下を追記
    add_column :users, :confirmation_token, :string
    add_column :users, :confirmed_at, :datetime
    add_column :users, :confirmation_sent_at, :datetime
    add_column :users, :unconfirmed_email, :string
  end
end

マイグレーションが用意できたら以下を実行します。

$ rails db:migrate

モデルの変更

確認メールを送信する設定をモデルに追加します。

user.rb

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
         # 以下を追記
         :confirmable
end

メール送信の設定

まず、メール送信設定で使用する機密情報をCredentialsに登録します。

$ EDITOR=vi rails credentials:edit

google:
  mail: YourMailAddress
  password: YourPassword

メールアドレスにGmailを使用する場合、アプリパスワードの設定が必要になります。アプリパスワードの設定については以下の記事の「アプリ パスワードを作成、使用する」セクションを参照してください。

config/initializers/ディレクトリ配下のdevise.rbを以下のように修正します。

devise.rb

Devise.setup do |config|
  # ==> Mailer Configuration
  # Configure the e-mail address which will be shown in Devise::Mailer,
  # note that it will be overwritten if you use your own mailer class
  # with default "from" parameter.
  # 以下を修正
  config.mailer_sender = Rails.application.credentials.google[:mail]
end

config/environments/ディレクトリ配下のdevelopment.rbに以下を追記します。

development.rb

Rails.application.configure do
  # 以下を追記
  config.action_mailer.raise_delivery_errors = true
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {
    :address => "smtp.gmail.com",
    :port => 587,
    :user_name => Rails.application.credentials.google[:mail],
    :password => Rails.application.credentials.google[:password],
    :authentication => :plain,
    :enable_starttls_auto => true
  }
end

以上で確認メール送信設定は完了です。なお、確認メール送信設定を行う以前に登録していたアカウントについては、ログインする際にメールアドレスの確認が必要になっています。その場合は確認メールの再送信を行ってください。

まとめ

認証機能を導入するだけなら「devise」は最も簡単な方法のひとつです。しかし、実際には「devise」のデフォルトセットでは物足りないという場合が多く、いくつかの追加の機能を実装する必要が出てくるかもしれません。その際、一度認証機能を自分で実装しているとその経験がきっと役に立つはずです。

本記事を参考にして、「devise」を使って認証機能を実装していただければと思います。

関連記事

【Rails】Paranoiaを使用した論理削除(ソフトデリート)
# はじめに Paranoiaは、Railsアプリケーションで論理削除(ソフトデリート)を実現するためのGemです。 論理削除は、データベースのレコードを物理的に削除するのではなく、削除フラグを設定することで「削除済み」とみなす方法です。こ [...]
2024年7月20日 21:33
【Rails】activerecord-multi-tenantを使用したマルチテナントアプリケーションの作成
# はじめに マルチテナントアプリケーションでは、複数の顧客(テナント)が同じアプリケーションを利用するため、データの分離が必要です。 activerecord-multi-tenantは、このようなマルチテナント環境をサポートするための便 [...]
2024年7月18日 16:50
【Rails】RubyとRailsにおけるattr_reader, attr_writer, attr_accessorの概念と使用方法
# はじめに RubyとRailsの開発において、`attr_reader`,`attr_writer`,`attr_accessor`は非常に便利なメソッドです。これらは、クラス内でインスタンス変数に対するゲッターおよびセッターメソッドを簡単に [...]
2024年7月17日 18:11
【Rails】RubyとRailsにおけるyieldの概念と使用方法
# はじめに RubyとRailsにおける`yield`は、メソッドやテンプレートの中で動的にコードブロックを実行する能力を提供し、これによってコードの再利用性と拡張性が大幅に向上します。本記事では、RubyとRailsにおける`yield`の概 [...]
2024年7月17日 13:15
【Rails】AASMを使用してオブジェクトの状態遷移を効率的に管理
# はじめに Railsアプリケーションにおいて、オブジェクトの状態管理は重要な課題の一つです。AASM (Acts As State Machine) gemは、複雑な状態遷移を効率的に管理します。本記事では、AASMの基本的な使い方を解説して [...]
2024年7月16日 18:00
【Rails】RSpec + Swagger + rswagでアプリケーションのAPIをテストおよびドキュメント化する方法
# はじめに Railsアプリケーションの開発において、APIのテストとドキュメント化は重要な要素です。 RSpecはテストフレームワークとして広く利用されており、SwaggerはAPIの設計とドキュメント化を支援します。これらを統合するr [...]
2024年7月16日 14:27
【Rails】mailcatcherを使用して開発環境でメール送信をテストする方法
# はじめに mailcatcherは、開発環境でのメール送信をキャプチャするためのツールです。ローカルで送信されたメールをブラウザ上で簡単に確認できるようにします。mailcatcherをRailsアプリケーションで使用する方法について説明しま [...]
2024年7月15日 16:37
【Rails】impressionistを使用してページビューやクリック数を追跡する方法
# はじめに impressionist Gemを使用してRailsアプリケーションでページビューやクリック数を追跡する方法について説明します。 # 実装方法 ## impressionist Gemのインストール まず、impre [...]
2024年7月15日 14:18