devise 入門講座 (1)

はじめに

こんにちは。TAOと申します。
アカウント機能を容易に実装することができる gem である devise の基本的な使用方法を数回に分けて説明していこうと思います。

この講座を受ける際の注意点
この講座は rails チュートリアルを修了したばかりの人を対象に制作しています。また、最終的には devise に実装されている全モジュールの使い方を学ぶことになりますが、この講座では使用するアカウントテーブルのカラムの管理の練習を兼ねて、カラムはその都度作成していきます。

動作対象
・Ruby 2.5
・Rails 5.1
・SQLite3

今回実装する機能
・アカウント作成機能
・ログイン及びログアウト機能
・アカウント編集機能


devise とは?

devise はログイン・ログアウト機能やアカウント作成機能などを簡単に実装できる gem です。機能がモジュール化されているので、管理しやすいのが特徴です。
今回は2018/3/18にリリースされた4.4.3を使っていきます。


devise のインストール

まずは雛形を作成しましょう。私はいつもディレクトリを真っ先に作成して、そのディレクトリに移動して、 Gemfile を作成するという手順を取っています。
今回は devise_learning というアプリを開発していきます。

# 任意のディレクトリに移動して、devise_learning ディレクトリを作成する
$ mkdir devise_learning

# devise_learning ディレクトリに移動する
$ cd devise_learning

# bundle をインストールする
$ bundle init

Gemfile に今回使用する gem を貼り付けます。

frozen_string_literal: true

source "https://rubygems.org"

git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }

gem 'rails', '~> 5.1.5'
gem 'turbolinks', '5.2.0'
gem 'puma', '~> 3.7'

# database
gem 'sqlite3', '~> 1.3.6'

# devise
gem 'devise', '4.4.3'
# gem 'bcrypt', git: 'https://github.com/codahale/bcrypt-ruby.git', require: 'bcrypt'

group :development, :test do
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
end

group :development do
  gem 'web-console', '>= 3.3.0'
  gem 'listen', '3.1.5'
end

# windows 環境の方は以下のコメントを外してください
# gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

devise はパスワードを暗号化する際に bcrypt という gem を使用しています。ruby のバージョンが 2.3 系の場合、あるいは Windows 環境で本アプリを作成する場合は、デフォルトでインストールされる bcrypt は動作しない場合があります。動作しない場合はこのコメントを外してください。

# gem 'bcrypt', git: 'https://github.com/codahale/bcrypt-ruby.git', require: 'bcrypt'

完了したら bundle install をしましょう。

$ bundle install

ここでアプリケーションの雛形を作成します。既に gem はインストールしたので、-B を付属して bundle install をスキップします。

$ rails new ./ -B

Gemfile の対応について尋ねられると思いますが、もちろん n と答えてください。
アプリケーションの雛形が完成したら、とりあえずアプリを起動してみましょう。

$ rails server

「Yay! You’re on Rails!」と表示されていれば OK です。


devise のインストール

早速、devise を雛形にインストールしましょう。rails g devise:install を実行すると devise の導入手順が出力されるので、これを元に進めていきます。

$ 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 つのファイルが作成されましたが、これらのファイルの使い方は後ほど解説します。
まずは 1 番目の説明を読んでみましょう。

devise の導入手順の和訳 (1)
環境ファイルにデフォルトの URL オプションが定義されていることを確認してください。
config/environments/development.rb の開発環境に適した default_url_options の例を次に示します

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

プロダクション環境では、host: はアプリケーションの実際のホストに設定する必要があります。

config/environment/development.rb に defalut_url_options を設定しましょう。default_url_options については Railsチュートリアルの11.2.2でも取り扱われています。私はローカル環境で開発しているので、devise の導入手順の通りに記述します。

Rails.application.configure do
  .
  .
  .
  config.action_mailer.raise_delivery_errors = false
  config.action_mailer.perform_caching = false
  config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
  .
  .
  .
end

メール認証機能は後で実装するので、これ以上の設定は行いません。
終わったら 2 番目の説明を読んでみましょう。

devise の導入手順の和訳 (2)
config/routes.rb何らかの root_url を定義していることを確認してください。
例えば

root to: "home#index"

config/routes.rb に root_url を定義しましょう。
まずは controller を定義します。今回は devise の導入手順に示されている例のとおり、ホーム画面用の home コントローラと index ページを用意します。

$ rails g controller home index

次に config/routes.rb に root_url を設定します。自動で作成されるルーティングを次のように書き換えてください。

Rails.application.routes.draw do
  root to: 'home#index'
end

以上で root_url の定義は完了です。
終わったら 3 番目の説明を読んでみましょう。

devise の導入手順の和訳 (3)
app/views/layouts/application.html.erb にフラッシュメッセージがあることを確認してください。
例えば

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

任意のフラッシュメッセージを定義していきましょう。といっても、今回は app/views/layouts/application.html.erb に、導入手順にかかれているコードをそのまま貼り付けてしまいます。

<!DOCTYPE html>
<html>
  <head>
    <title>DeviseLearning</title>
    <%= csrf_meta_tags %>
    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>
  <body>
    

<%= yield %> </body> </html>

bootstrap を使用したスタイルの調整は次回行いますので、以上で任意のフラッシュメッセージの定義は完了です。
終わったら 4 番目の説明を読んでみましょう。

devise の導入手順の和訳 (4)
以下のコマンドを実行することによって、Deviseビュー(カスタマイズ用)をアプリにコピーすることができます。

$ rails g devise:views

Deviseビュー(カスタマイズ用)をアプリにインストールしてみましょう。 導入手順に記されているコマンドを実行すると大量の Devise ビューが作成されます。

$ bundle exec rails g devise:views
      invoke  Devise::Generators::SharedViewsGenerator
      create    app/views/devise/shared
      create    app/views/devise/shared/_links.html.erb
      invoke  form_for
      create    app/views/devise/confirmations
      create    app/views/devise/confirmations/new.html.erb
      create    app/views/devise/passwords
      create    app/views/devise/passwords/edit.html.erb
      create    app/views/devise/passwords/new.html.erb
      create    app/views/devise/registrations
      create    app/views/devise/registrations/edit.html.erb
      create    app/views/devise/registrations/new.html.erb
      create    app/views/devise/sessions
      create    app/views/devise/sessions/new.html.erb
      create    app/views/devise/unlocks
      create    app/views/devise/unlocks/new.html.erb
      invoke  erb
      create    app/views/devise/mailer
      create    app/views/devise/mailer/confirmation_instructions.html.erb
      create    app/views/devise/mailer/email_changed.html.erb
      create    app/views/devise/mailer/password_change.html.erb
      create    app/views/devise/mailer/reset_password_instructions.html.erb
      create    app/views/devise/mailer/unlock_instructions.html.erb

作成されたファイルで、ログインやアカウント作成時などで使用される初期ビューを変更することができます。変更は次回行います。

以上で devise の初期設定は完了です。これでアカウント機能をもつテーブルを作成する手順が整いました。


devise を用いてアカウント機能を実装

devise を用いてアカウント機能をもつ user モデルを作成していきます。 devise でアカウントを持つモデルを作成する場合は次のコマンドを実行します。

$ rails g devise user
      invoke  active_record
      create    db/migrate/xxxxxxxxxxxxxx_devise_create_users.rb
      create    app/models/user.rb
      invoke    test_unit
      create      test/models/user_test.rb
      create      test/fixtures/users.yml
      insert    app/models/user.rb
       route  devise_for :users

まずは、route devise_for :users からみていきます。
config/routes.rb が次の通りになっていることを確認してください。

Rails.application.routes.draw do
  devise_for :users
  root to: 'home#index'
end

devise_for :users というルートが設定されていることが確認できます。どんなルートが作成されているのか確認してみましょう。

$ bundle exec rails routes
                  Prefix Verb   URI Pattern                    Controller#Action
        new_user_session GET    /users/sign_in(.:format)       devise/sessions#new
            user_session POST   /users/sign_in(.:format)       devise/sessions#create
    destroy_user_session DELETE /users/sign_out(.:format)      devise/sessions#destroy
       new_user_password GET    /users/password/new(.:format)  devise/passwords#new
      edit_user_password GET    /users/password/edit(.:format) devise/passwords#edit
           user_password PATCH  /users/password(.:format)      devise/passwords#update
                         PUT    /users/password(.:format)      devise/passwords#update
                         POST   /users/password(.:format)      devise/passwords#create
cancel_user_registration GET    /users/cancel(.:format)        devise/registrations#cancel
   new_user_registration GET    /users/sign_up(.:format)       devise/registrations#new
  edit_user_registration GET    /users/edit(.:format)          devise/registrations#edit
       user_registration PATCH  /users(.:format)               devise/registrations#update
                         PUT    /users(.:format)               devise/registrations#update
                         DELETE /users(.:format)               devise/registrations#destroy
                         POST   /users(.:format)               devise/registrations#create
                    root GET    /                              home#index

devise_for :users は使用されているモジュールに応じて、devise の機能に必要なルートを設定します。使用するモジュールは app/models/user.rb で設定します。

というわけで create app/models/user.rb をみてみましょう。devise の機能はこのファイルで管理します。

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

devise に実装されている各モジュールの機能をここに掲載します。

database_authenticatableサイン時にパスワードを暗号化してDBに登録
registerableユーザーが自身のアカウントの編集と削除を可能にする
recoverableパスワードのリセットを可能にする
rememberableremember me 機能を有効化する
trackableサインインの回数やIPアドレスなどを記録
validatableメールとパスワードのバリデーションを行う
confirmableメール認証機能を有効化
lockable規定回数ログインに失敗したらアカウントをロックする
timeoutable一定時間でセッションを破棄する
omniauthableTwitter や Facebook など、外部サービスのアカウントで認証を可能にする

最終的には devise の全モジュールを使用することになるのですが、今回は現時点で使用しないモジュールをコメントアウトします。

class User < ApplicationRecord
  # Not use devise modules are:
  # :recoverable, :rememberable, :trackable,
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable, :validatable
end

使用するモジュールを 3 つに絞りました。この 3 つのモジュールだけで Remember me 機能を除いた Railsチュートリアルの10章 までの機能を実装することができます。
ここでもう一度ルートを確認してみてください。先ほど存在していたルートの一部がなくなっているはずです。

$ rails routes
                  Prefix Verb   URI Pattern               Controller#Action
        new_user_session GET    /users/sign_in(.:format)  devise/sessions#new
            user_session POST   /users/sign_in(.:format)  devise/sessions#create
    destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
cancel_user_registration GET    /users/cancel(.:format)   devise/registrations#cancel
   new_user_registration GET    /users/sign_up(.:format)  devise/registrations#new
  edit_user_registration GET    /users/edit(.:format)     devise/registrations#edit
       user_registration PATCH  /users(.:format)          devise/registrations#update
                         PUT    /users(.:format)          devise/registrations#update
                         DELETE /users(.:format)          devise/registrations#destroy
                         POST   /users(.:format)          devise/registrations#create
                    root GET    /                         home#index

次に進む前に、ログインやログアウトなどに必要なリンクを作成してしまいましょう。rails routes のログからリンクを作成します。
app/wiews/layouts/_session.html.erb を新たに作成して次のように記述してください。

<% if user_signed_in? %>
  <p><%= link_to "アカウント編集", edit_user_registration_path %>
  <p><%= link_to "ログアウト", destroy_user_session_path, method: "delete" %></p>
<% else %>
  <p><%= link_to "ログイン", new_user_session_path %></p>
  <p><%= link_to "アカウント作成", new_user_registration_path %></p>
<% end %>

user_signed_in? はセッションを登録しているかどうかを真理値で返してくれる devise が提供するメソッドです。user の箇所は作成したテーブル名で変化するので注意してください。
app/views/layouts/application.html.erbにこのパーシャルを追記しましょう。

<!DOCTYPE html>
<html>
  <head>
    <title>DeviseLearning</title>
    <%= csrf_meta_tags %>
    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>
  <body>
    

<%= render 'layouts/session' %> <%= yield %> </body> </html>

次は create db/migrate/xxxxxxxxxxxxxx_devise_create_users.rb を見ていきましょう。(xxxxxxxxxxxxxxには作成日時が入ります。) 。ここにアカウント機能で使用されるテーブルが用意されています。

class DeviseCreateUsers < ActiveRecord::Migration[5.1]
  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

こちらも devise の全モジュールを使用するにあたって、ここに記載されている全カラムを作成することになるのですが、先ほど app/models/user.rb で設定した 3 つのモジュールに必要なカラムだけを作成します。よって、現時点で使用しないカラムをコメントアウトします。

class DeviseCreateUsers < ActiveRecord::Migration[5.1]
  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

この作業が完了したらデータベースを作成して、マイグレートしましょう。

$ rails db:migrate

db/schema.rb をみると、アカウント機能を実現するのに必要な最低限のカラムが用意されていることがわかります

以上で基本的なアカウント機能は全て実装できました

「え?これだけ?」
はい、本当にこれだけです。これだけでアカウント登録・削除、ログイン・ログアウト機能の実装が完了です。
サーバを起動してみて、実際に挙動を確認してみてください。


さいごに

今回は基本的なアカウント機能を devise を使って実装しました。
次回もこのアプリを使って実装していきますので受講される方は残しておいてください。
次回は devise に bootstrap を導入してスタイルを整えて、フラッシュメッセージが英語になっているので、これを日本語にして、最後に users モデルに名前(username)を登録する機能を追加していきます。


参照

https://railstutorial.jp/chapters/account_activation?version=5.1#sec-email_previews

https://railstutorial.jp/chapters/updating_and_deleting_users?version=5.1#cha-updating_showing_and_deleting_users


参考

https://ticklecode.com/devise/

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google フォト

Google アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中