【rails】deviseで実現するユーザ認証機能

  • このエントリーをはてなブックマークに追加

「deviseでユーザ認証機能って実際どんな感じで実装するの?」

 

そんな方のために実装の流れをインストールから丁寧に解説していきます。

 

また、ユーザ認証といってもOAuth認証やメール認証などあるため、今回は的を絞って以下の機能だけ実装します。

トップページとマイページがあり、マイページにはログインしないとアクセスできない。

 

環境

  • ruby 2.4.1
  • rails 5.0.7
  • devise 4.4.3
  • rspec -rails 3.7.2

 

使用するファイル

  • view: app/views/like/

index.html.erb

mypage.html.erb

 

  • controller: app/controllers/

application_controller.rb

like_controller.rb

 

  • model: app/models/

user.rb

 

  • rspec: spec/controllers/

likecontrollerspec.rb

 

GitHub | 今回作成したコード

 

deviseの準備

1. deviseのインストール

1. Gemfileにdeviseを追記

Gemfile

 

source 'https://rubygems.org'
〜
gem 'devise', '4.4.3'
〜

 

2. bundleを使ってgemをインストール

 

$ bundle install --path vendor/bundle

 

3. railsでdeviseのインストール

インストールコマンドを実行するとセットアップの方法が表示されます。詳細については「2. deviseの設定」で解説していきます。

$ bundle exec rails g devise:install
      create  config/initializers/devise.rb
      create  config/locales/devise.en.yml
==============================================================
Some setup you must do manually if you haven't yet:

  1. Ensure you have defined default url options in your environments files. Here
     is an example of default_url_options appropriate for a development environment
     in config/environments/development.rb:

       config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

     In production, :host should be set to the actual host of your application.

  2. Ensure you have defined root_url to *something* in your config/routes.rb.
     For example:

       root to: "home#index"

  3. Ensure you have flash messages in app/views/layouts/application.html.erb.
     For example:

       <p class="notice"><%= notice %></p>
       <p class="alert"><%= alert %></p>

  4. You can copy Devise views (for customization) to your app by running:

       rails g devise:views

==============================================================

 

 

2. deviseの設定

「1. deviseのインストール」の3番目の作業で表示されたものを1つずつ解説していきます。

 

1. Ensure you have defined default url options 〜

簡単に言うと「ActionMailer(メールのcontrollerみたいなもの。)内で使用するhost情報設定しなさい。」ということ。

 

(ActionMailerの簡単な説明)

railsでいつも使っているcontrollerのメールバージョンみたいな認識で今回は大丈夫です。

 

設定するファイルと内容は以下になります。

 

config.action_mailer.default_url_options = {host: 'localhost', port: 8888}

host、port
今回は開発環境ということもあり、localhostと8888を指定しています。本番環境などではsample.comの443などのように設定して下さい。

(注意)
使用している環境(RAILS_ENVの値)によってファイルが異なります。
config/environments/
development.rb
production.rb
test.rb

2. Ensure you have defined root_url to〜

「トップのルート情報を設定しなさい」ということ。railsで何かシステムを作る場合は必ずと言っていいほど設定していると思いますので、そこまで気にする必要はないです。
後程、設定していきます。

3. Ensure you have flash messages in 〜

ログイン状態などをViewで表示するための方法を示しているだけです。
以下のようにViewに組み込むことで表示できるようになります。

<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>

 

4. You can copy Devise views (for customization) to 〜

Deviseで使用されるViewの追加方法を示しています。以下のコマンドを実行するだけなので簡単です。

 

$ bundle exec rails g devise:views
-> app/views/devise配下にいろいろファイルが作成されます。

 

 

3. Userモデルの作成

1. Userモデルを作成するためのマイグレーションファイルを作成

deviseのコマンドで簡単に作成できます。

 

$ bundle exec rails g devise User

以下のマイグレーションファイルが作成されるので、使用する機能のカラム情報をコメントアウト or コメントアウト解除を行って下さい。今回は、Database authenticatable/Recoverable/Rememberableを使用するため、その機能が使用するカラム情報以外はコメントアウトしました。

class DeviseCreateUsers < ActiveRecord::Migration[5.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

 

2. Userテーブルの作成

$ bundle exec rails db:migrate

 

4. 使用するモジュールの設定

使用するモジュールを有効にします。

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

 

 

処理の実装

[作成中]()

Rspecでログイン状態を使用するための設定方法は上記の記事を参照して下さい。

 

1. トップページの作成

1. テストコードの作成

 

require 'rails_helper'
require 'devise'

RSpec.describe LikeController, type: :controller do
  describe '#index' do
    context 'When GET' do
      it 'HTTP status is 200.' do
        get :index
        expect(response).to have_http_status(200)
      end
    end
  end
end

 

テストが失敗することを確認します。

$ bundle exec rspec spec/controllers/like_controller_spec.rb
F..

Failures:

  1) LikeController#index When GET HTTP status is 200.
     Failure/Error: get :index

     ActionController::UrlGenerationError:
       No route matches {:action=>"index", :controller=>"like"}
     # ./spec/controllers/like_controller_spec.rb:8:in `block (4 levels) in <top (required)>'

Finished in 0.08382 seconds (files took 2.56 seconds to load)
3 examples, 1 failure

Failed examples:

rspec ./spec/controllers/like_controller_spec.rb:7 # LikeController#index When GET HTTP status is 200.

$

 

2. ルートの追加

 

Rails.application.routes.draw do
  devise_for :users
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
  root 'like#index'
end

 

devise_for :users

deviseによって自動的に設定される値になります。今回は無視して下さい。

 

root ‘like#index’

今回はlike_controller.rbのindexアクションを設定しました。

 

3. viewの作成

app/views/like/index.html.erbを作成します。

 

4. テストの実行

テストが上手くいくことを確認します。

$ bundle exec rspec spec/controllers/like_controller_spec.rb
...

Finished in 0.08082 seconds (files took 2.39 seconds to load)
1 examples, 0 failures

$

 

 

2. マイページの作成

1. テストの作成

 

equire 'rails_helper'
require 'devise'

RSpec.describe LikeController, type: :controller do
  describe '#index' do
    context 'When GET' do
      it 'HTTP status is 200.' do
        get :index
        expect(response).to have_http_status(200)
      end
    end
  end

  describe '#mypage' do
    context 'When GET with logged in' do
      it 'HTTP status is 200.' do
        login_admin
        get :mypage
        expect(response).to have_http_status(200)
      end
    end

    context 'When GET with not logged in' do
      it 'HTTP status is 302.' do
        get :mypage
        expect(response).to have_http_status(302)
      end
    end
  end
end

 

テストが失敗することを確認します。

$ bundle exec rspec spec/controllers/like_controller_spec.rb
.FF

Failures:

  1) LikeController#mypage When GET with logged in HTTP status is 200.
     Failure/Error: get :mypage

     ActionController::UrlGenerationError:
       No route matches {:action=>"mypage", :controller=>"like"}
     # ./spec/controllers/like_controller_spec.rb:18:in `block (4 levels) in <top (required)>'

  2) LikeController#mypage When GET with not logged in HTTP status is 302.
     Failure/Error: get :mypage

     ActionController::UrlGenerationError:
       No route matches {:action=>"mypage", :controller=>"like"}
     # ./spec/controllers/like_controller_spec.rb:25:in `block (4 levels) in <top (required)>'

Finished in 0.07187 seconds (files took 2.39 seconds to load)
3 examples, 2 failures

Failed examples:

rspec ./spec/controllers/like_controller_spec.rb:16 # LikeController#mypage When GET with logged in HTTP status is 200.
rspec ./spec/controllers/like_controller_spec.rb:24 # LikeController#mypage When GET with not logged in HTTP status is 302.

$

 

2. ルートの追加

 

Rails.application.routes.draw do
  devise_for :users
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
  root 'like#index'
  get '/mypage', to: 'like#mypage'
end

 

3. Viewとアクションの追加

app/views/like/mypage.html.erbの追加。またアクションを以下のように追加します。

class LikeController < ApplicationController
  def index
  end

  def mypage
  end
end

 

4. テストの実行

2) LikeController#mypage When GET with not logged in HTTP status is 302. が上手くいくことを確認します。

$ bundle exec rspec spec/controllers/like_controller_spec.rb
.F.

Failures:

  1) LikeController#mypage When GET with logged in HTTP status is 200.
     Failure/Error: expect(response).to have_http_status(200)
       expected the response to have status code 200 but it was 302
     # ./spec/controllers/like_controller_spec.rb:19:in `block (4 levels) in <top (required)>'

Finished in 0.06249 seconds (files took 2.56 seconds to load)
3 examples, 1 failure

Failed examples:

rspec ./spec/controllers/like_controller_spec.rb:16 # LikeController#mypage When GET with logged in HTTP status is 200.

$

 

5. マイページにログインしないとアクセスできない処理の追加

application_controller.rbに以下の処理を追加します。

 

# ユーザー登録した後に遷移するページの設定
  def after_sign_in_path_for(resource)
    root_path
  end

# ログインを要求する処理
  private
  def sign_in_required
    redirect_to new_user_session_path unless user_signed_in?
  end

 

like_controller.rbに以下の処理を追加します。

# mypageへのアクセス条件にログインを要求する処理
before_action :sign_in_required, only: [:mypage]

 

6. テストの実行

全てのテストが上手くいくことを確認します。

$ bundle exec rspec spec/controllers/like_controller_spec.rb
...

Finished in 0.07799 seconds (files took 1.85 seconds to load)
3 examples, 0 failures

$

 

 

まとめ

参考になったでしょうか?今回はシンプルな機能の解説しかしていませんが、deviseにはまだまだ便利な機能がたくさんあります。随時更新していきますので、よかったらまた見に来て下さいね。

  • このエントリーをはてなブックマークに追加

SNSでもご購読できます。

コメントを残す

*