Tatehito's Programming Blog

プログラマによる技術寄り日記ブログ

【RubyGems】簡単に認証機能がつくれるgem『devise』を試してみた

はじめに

つぎにつくる予定のWebアプリでは、認証(ログイン)機能を実装しようと思っています。そこで認証機能を実装するためのgemで有名な『devise』の最低限の動作確認をしてみました。

環境は以下の通りです💡

  • Ruby 2.6.3
  • Rails 6.0.0
  • devise 4.7.1 (現時点の最新バージョン)

目次

完成イメージ

この記事の通りに進めると、以下のサンプルアプリが完成します。


f:id:tatehito-st:20191012143845p:plain:w300
未ログイン時は「サインアップ」「ログイン」リンクが表示されます。(ログインじゃなくて「サインイン」にすればよかった......)


f:id:tatehito-st:20191012141241p:plain:w200
ログイン画面。レイアウトはdeviseのデフォルトレイアウトです。


f:id:tatehito-st:20191012151729p:plain:w300
ログインするとユーザーページが表示されます。


f:id:tatehito-st:20191012143859p:plain:w300
トップページに戻ると「ログアウト」リンクのみが表示されています。


f:id:tatehito-st:20191012143845p:plain:w300
ログアウトすると元に戻ります。


実装

1.rails newする

Rails6.0.0でアプリを新規作成します。

rails _6.0.0_ new gem-devise-sample

トップページが表示されることを確認します。

f:id:tatehito-st:20191012120812p:plain

2.devise をインストールする

Gemfileに以下を記述し、bundle install

# Gemfile

gem 'devise'

続けて、以下のコマンドでdeviseの設定ファイルを作成します。

$ rails g devise:install

3.devise対応のUserモデルを生成する

Userモデルをつくります。以下のコマンドでdevise対応のUserモデルを生成。

$ rails g devise User

以下のマイグレーションファイルが生成されるので、rails db:migrateでマイグレーションを実行。 コメントアウトされているカラムがあるが、今回は最低限の動作確認のみのため、そのままにしておきます。

# frozen_string_literal: true

class DeviseCreateUsers < ActiveRecord::Migration[6.0]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      # t.integer  :sign_in_count, default: 0, null: false
      # t.datetime :current_sign_in_at
      # t.datetime :last_sign_in_at
      # t.string   :current_sign_in_ip
      # t.string   :last_sign_in_ip

      ## Confirmable
      # t.string   :confirmation_token
      # t.datetime :confirmed_at
      # t.datetime :confirmation_sent_at
      # t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      # t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at


      t.timestamps null: false
    end

    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
    # add_index :users, :confirmation_token,   unique: true
    # add_index :users, :unlock_token,         unique: true
  end
end

この時点で、http://localhost:3000/users/sign_inを開くと最低限のログインページができています。

f:id:tatehito-st:20191012141241p:plain:w200

しかし、この状態だと認証後のリダイレクト先ページがRailsのデフォルトページ(Yay! You’re on Rails!の画面)になっているので、 リダイレクト先ページをユーザー個人のプロフィールページに変更します。

4.トップページをつくる

Pagesコントローラーをindex、showアクションつきで生成。

$ rails g controller Pages index show

ルーティングを設定をします。rootを先ほど生成したpages#indexに。なお、devise_for :usersはdevise対応のUserモデルを生成した時点で自動で設定されます。

# route.rb

Rails.application.routes.draw do
  root 'pages#index'
  get 'pages/show'
  devise_for :users
end

トップページのビューを編集します。今回は、ログイン状態によって、表示するリンクが切り替わるようにしたいと思います。user_signed_in?でログイン状態を判定し、表示するリンクを切り替えます。

routes.rbに設定されたdevise_for :usersにより、‘new_user_session_path‘や‘destroy_user_session_path‘など、devise用の名前付きルートが使えるようになっているので、その名前付きルートを使ってリンクを記述します。

<!-- index.html.erb -->

<h1>トップページ</h1>
<p>Find me in app/views/pages/index.html.erb</p>
<% if user_signed_in? %>
  <%= link_to 'ログアウト', destroy_user_session_path, method: :delete %>
<% else %>
  <%= link_to 'サインアップ', new_user_registration_path %>
  <%= link_to 'ログイン', new_user_session_path %>
<% end %>

これで、ログイン状態によってリンクが切替わるようになりました。

f:id:tatehito-st:20191012143845p:plain:w300


f:id:tatehito-st:20191012143859p:plain:w300

5.認証後のリダイレクト先をユーザーページにする

Devise::Controllers::Helpersafter_sign_in_path_forメソッドをオーバーライドすることで、認証後のリダイレクト先をカスタマイズできます。

# application.rb

def after_sign_in_path_for(resource)
    "/user/#{current_user.id}"
  end

※current_userで現在ログインしているユーザー情報を取得できる。

ユーザーページのビューを編集します。ログインユーザーのメールアドレスを表示するようにしてみました。

<!-- show.html.erb -->

<h1>ユーザーページ</h1>
<div>
  あなたのメールアドレス:<%= current_user.email %>
</div>
<div>
  <%= link_to '戻る', root_path %>
</div>

さいごに、ユーザーページのルーティングを編集。

# route.rb

Rails.application.routes.draw do
  root 'pages#index'
  get "user/:id", :to => "pages#show" # この1行を編集
  devise_for :users
end

これで完成😤

ログインするとそのユーザーのページが開きます。

f:id:tatehito-st:20191012151729p:plain:w300

おわりに

ソースコードはこちらです💁‍♂️

github.com

サインインやサインアップページのビューや、動作をカスタマイズするにはrails g devise:views usersrails g devise:controllers usersをしてdevise対応のコントローラーやビューを生成する必要があるようです。今回は最低限の動作確認が目的のため、そこまでは手を出しませんでした。

サンプルアプリをつくるくらいなら簡単ですが、deviseは多機能で、使いこなすのは一筋縄ではいかなそう、という印象を受けました。まあ、それでもゼロから認証機能をつくるよりはよっぽど簡単なのですが。