LoginSignup
13
2

Rails7.1環境で認証機能Rails deviseの導入方法

Last updated at Posted at 2023-12-04

この記事はウェブクルー Advent Calendar 2023 5日目の記事です。
昨日は@wc-horino さんの「Scala, PlayFramework, Mockitoを使った自動テスト導入」でした。

Rails-deviseとは

Deviseは、Ruby on Railsフレームワークの人気のある認証ライブラリです。ユーザーのサインアップ、サインイン、パスワードのリセットなど、強力なセキュリティ機能および認証機能を簡単に実装できるようなGemライブラリーです。

開発環境情報

# rubyバージョン
$ rbenv versions
* 3.2.2

# railsバージョン、Turbo Frame有効済み
$ rails -v
Rails 7.1.2

参考資料

公式ドキュメント

Github

Rails-deviseのインストールと初期設定

Rails-deviseのインストール

Gemfile
gem "devise"
terminal
bundle install
rails g devise:install

deviceをインストールしたら、deviseのconfigファイル(/config/initializers/devise.rb)が作成されました。
今回は特に編集しなくて大丈夫です。

deviseのUserモデルの作成

terminal
rails g devise User

userモデルとroutesの記述が自動に追加されました。

/app/models/user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
end

devise_for :usersこの一行の追加により、以下のようなルーティングが自動的に設定されます:
サインアップ (/users/sign_up)
ログイン (/users/sign_in)
サインアウト (/users/sign_out)
パスワードリセット (/users/password/new, /users/password/edit など)

/config/routes.rb
Rails.application.routes.draw do
  devise_for :users
  get "home/index"
  root "home#index"

  get "up" => "rails/health#show", as: :rails_health_check

  # Defines the root path route ("/")
  # root "posts#index"
end

マイグレーションファイルでカスタマイズカラムを追加

terminal
rails g migration AddColumnToUser

/db/migrate/*****_add_column_to_user.rbファイルが生成されました。
このマイグレーションファイルでfull_name、username、phone_numberのカラムをusersテーブルに追加します。

/db/migrate/*****_add_column_to_user.rb
class AddColumnToUser < ActiveRecord::Migration[7.1]
  def change
    add_column :users, :full_name, :string
    add_column :users, :username, :string
    add_column :users, :phone_number, :string
  end
end

マイグレーションファイルを実行します。

rails db:migrate

schemaファイルを確認してみると、
full_name、username、phone_numberが無事にusersテーブルに追加されました。

/db/schema.rb
ctiveRecord::Schema[7.1].define(version: 2023_12_04_131204) do
  create_table "users", force: :cascade do |t|
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
   +t.string "full_name"
   +t.string "username"
   +t.string "phone_number"
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
  end
end

コントローラーにdeviseのメソッドなどを登録

参考: https://github.com/heartcombo/devise#strong-parameters

/app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
    # /users/sign_up
    devise_parameter_sanitizer.permit(:sign_up, keys: [:username, :phone_number, :full_name])
  end
end

ruby7.0以降はTurbo frame機能がデフォルトになっているため、Turboと組み込む必要があります。

/app/controllers/turbo_devise_controller.rb
class TurboDeviseController < ApplicationController
  class Responder < ActionController::Responder
    def to_turbo_stream
      controller.render(options.merge(formats: :html))
    rescue ActionView::MissingTemplate => error
      if get?
        raise error
      elsif has_errors? && default_action
        render rendering_options.merge(formats: :html, status: :unprocessable_entity)
      else
        redirect_to navigation_location
      end
    end
  end

  self.responder = Responder
  respond_to :html, :turbo_stream
end

deviseのviewsの作成

deviseのデフォルトのビューをカスタマイズするためのファイルがアプリケーション内に生成されます。
/app/views/deviseのフォルダーが生成されて、
今回は/sessions/new.html.erb/registrations/new.html.erbだけを編集します。

terminal
rails generate devise:views

ログインページのマークアップ
スクリーンショット 2023-12-05 0.41.10.png

/app/views/devise/sessions/new.html.erb
<div class="container home-sections d-flex flex-row justify-content-center
  align-items-center"
>
  <div class="images-section pt-3 d-none d-lg-block"></div>

  <div class="login-section pt-3">
    <div class="card text-center pt-5" style="width: 23rem;">
      <h1>ログイン画面</h1>
      <div class="card-body">
        <%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
          <div class="mb-3 mt-4">
            <%= f.email_field :email, class: "form-control", placeholder: "電話番号, ユーザ名, Eメール" %>
          </div>

          <div class="mb-3">
            <%= f.password_field :password, class: "form-control", placeholder: "パスワード" %>
          </div>

          <%= f.submit "ログイン", class: "btn btn-primary w-100" %>
        <% end %>

        <% if notice %>
          <p class="notice"><%= notice %></p>
        <% elsif alert %>
          <p class="alert"><%= alert %></p>
        <% end %>

        <a href="#" class="fs-6 d-block my-4 text-decoration-none"> パスワードを忘れた?</a>
      </div>
    </div>

    <div class="card text-center py-2 mt-3" style="width: 23rem;">
      <div class="card-text">
        アカウントを持っていない?
        <%= link_to "サインアップ", new_user_registration_path, class: "fs-6 my-4 text-decoration-none text-info" %>
      </div>
    </div>
  </div>
</div>

登録ページのマークアップ
スクリーンショット 2023-12-05 0.41.21.png

/app/views/devise/registrations/new.html.erb
<div class="container home-sections d-flex flex-row justify-content-center
  align-items-center"
>
  <div class="login-section pt-3">
    <div class="card text-center pt-5 mx-auto" style="width: 23rem;">
      <h1>サインアップ画面</h1>

      <div class="card-body">
        <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
          <div class="mb-3 mt-4">
            <%= f.email_field :email, class: "form-control", placeholder: "電話番号、Eメール" %>
          </div>

          <div class="mb-3 mt-4">
            <%= f.text_field :full_name, class: "form-control", placeholder: "お名前" %>
          </div>

          <div class="mb-3 mt-4">
            <%= f.text_field :username, class: "form-control", placeholder: "ユーザ名" %>
          </div>

          <div class="mb-3">
            <%= f.password_field :password, class: "form-control", placeholder: "パスワード" %>
          </div>

          <div class="mb-3">
            <%= f.password_field :password_confirmation, class: "form-control", placeholder: "パスワード確認" %>
          </div>

          <%= f.submit "サインアップ", class: "btn btn-primary w-100" %>
        <% end %>

        <% if notice %>
          <p class="notice"><%= notice %></p>
        <% elsif alert %>
          <p class="alert"><%= alert %></p>
        <% end %>
      </div>
    </div>

    <div class="card text-center py-2 mt-3 mx-auto" style="width: 23rem;">
      <div class="card-text">
        既にアカウントを持っている?
        <%= link_to "サインイン", new_user_session_path, class: "fs-6 my-4 text-decoration-none text-info" %>
      </div>
    </div>
  </div>
</div>

ログインしていない時
スクリーンショット 2023-12-05 0.41.36.png

ログインした後
スクリーンショット 2023-12-05 0.41.57.png

開発環境で確認

サンプルをご参考ください。

終わりに

deviseはRuby on Railsアプリケーションにおいて、ユーザー認証とセッション管理の実装を驚くほど簡単で同時に豊富な機能を提供しています。開発者はセキュリティに焦点を当てることなくてアプリケーションのコア機能に専念できます。ぜひ試して見てください。

明日は@wchikarusato さんの「obsidianを使って1週間を振り返る方法」になります。
お楽しみにしてください。

13
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
13
2