はじめに
こんにちは、onoです。
今回はユーザ登録処理を簡単に実装できるGemであるdeviseの使い方を紹介します。
前提条件
ruby 2.4.1
rails 5.1.1
devise 4.3.0
deviseについて
deviseとは
deviseは認証機能を提供するGemです。
https://github.com/plataformatec/devise
deviseでできること
- ユーザ登録(パスワードを暗号化してDBに保存)
- 登録するメールアドレスのバリデーション
- ユーザ登録時にメールを送り、そのメールのリンクにより登録を完了する
- ユーザを識別するトークンをCookieに保存、取得、削除する
- ログイン回数やIPアドレスを記録する
- パスワードを忘れた場合、パスワード再発行のメールを送る
- パスワードを間違えた場合にアカウントをロックする
- タイムアウト処理
- TwitterやFacebookなど認証をサポート(別途Gemが必要)
登録処理の実装
まず、新しいプロジェクトを作成してください。
Gemのインストール
Gemfileにdeviseを追加してbundle installします。
1 2 3 4 5 | source 'https://rubygems.org' # 省略 gem 'devise' |
deviseのインストール
ターミナル上で下記のコマンドを実行します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | $ 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 =============================================================================== |
デフォルトURLを指定する
config/environments/development.rbに下記の設定を追加します。
1 2 3 4 5 6 | Rails.application.configure do # 省略 config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } end |
root_urlを指定する
最初に表示されるページを作成し、root_urlに指定します。
まず、ターミナル上で下記のコマンドを実行します。
1 2 3 4 5 6 7 8 9 10 11 12 13 | $ rails g controller TopPages index create app/controllers/top_pages_controller.rb route get 'top_pages/index' invoke erb create app/views/top_pages create app/views/top_pages/index.html.erb invoke helper create app/helpers/top_pages_helper.rb invoke assets invoke coffee create app/assets/javascripts/top_pages.coffee invoke scss create app/assets/stylesheets/top_pages.scss |
次にconfig/routes.rbを下記の通りに修正します。
1 2 3 | Rails.application.routes.draw do root 'top_pages#index' end |
通知メッセージを表示させる
ログイン時などに通知メッセージを表示させるようにします。
また、後々動作確認をする時に便利なので、ログアウトできるようにします。
app/views/layouts/application.html.erbを下記の通りに修正します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <!DOCTYPE html> <html> <!--省略--> <body> <p class="notice"><%= notice %></p> <p class="alert"><%= alert %></p> <% if user_signed_in? %> <p><%= link_to "ログアウト", destroy_user_session_path, method: :delete %></p> <% end %> <!--省略--> </body> </html> |
devise関連のViewを生成する
新規作成フォームなどをカスタマイズするために、devise関連のviewを生成します。
ターミナル上で下記のコマンドを実行します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | $ rails g devise:views Expected boolean default value for '--markerb'; got :erb (string) 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 |
ユーザモデルを作成する
まず、マイグレーションファイルを作成します。
ターミナル上で下記のコマンドを実行します。
1 2 3 4 5 6 | $ rails g devise user invoke active_record create db/migrate/20170617030700_devise_create_users.rb create app/models/user.rb insert app/models/user.rb route devise_for :users |
出来上がったマイグレーションファイルは下記の通りです。
ユーザ名を保存するカラムを追加します。
また、後々メールでの登録処理やアカウントのロックに必要なので、ConfirmableとLockableのコメントアウトを外しておきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | class DeviseCreateUsers < ActiveRecord::Migration[5.1] def change create_table :users do |t| # 追加 t.string :name, null: false, default: '' ## 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, :name, unique: true 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 |
マイグレーションファイルを修正したらDBを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | $ rake db:create Created database 'devise_development' Created database 'devise_test' $ rake db:migrate == 20170617030700 DeviseCreateUsers: migrating ================================ -- create_table(:users) -> 0.0153s -- add_index(:users, :name, {:unique=>true}) -> 0.0131s -- add_index(:users, :email, {:unique=>true}) -> 0.0131s -- add_index(:users, :reset_password_token, {:unique=>true}) -> 0.0167s == 20170617030700 DeviseCreateUsers: migrated (0.0592s) ======================= |
出来上がったモデルは下記の通りです。
1 2 3 4 5 6 | class User < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable end |
ApplicationControllerを修正する
app/controllers/application_controller.rbを下記の設定を追加します。
1 2 3 4 | class ApplicationController < ActionController::Base protect_from_forgery with: :exception before_action :authenticate_user! end |
ここまででユーザ登録処理は完成です。
登録時にユーザ名を登録する
デフォルトではメールアドレスとパスワードしか登録できません。
ユーザ名も一緒に登録できるようにします。
ApplicationControllerを修正する
app/controllers/application_controller.rbに下記の設定を追加します。
1 2 3 4 5 6 7 8 9 10 11 | class ApplicationController < ActionController::Base protect_from_forgery with: :exception before_action :authenticate_user! before_action :configure_permitted_parameters, if: :devise_controller? protected def configure_permitted_parameters devise_parameter_sanitizer.permit(:sign_up, keys: [:name]) devise_parameter_sanitizer.permit(:account_update, keys: [:name]) end end |
登録フォームを修正する
app/views/devise/registrations/new.html.erbに下記の設定を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <h2>Sign up</h2> <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %> <%= devise_error_messages! %> <div class="field"> <%= f.label :name %><br /> <%= f.text_field :name, autofocus: true %> </div> <!--省略--> <% end %> <%= render "devise/shared/links" %> |
アカウント登録の確認メールを送る
確認メールを送る方法は下記の2種類の方法があります。
- 自分のGmailアカウントから送る
- 自前でメールサーバを立てる
ここでは、自分のGmailアカウントから送る方法を説明します。
ユーザモデルを修正する
先ほど生成したユーザモデルを下記の通り修正します。
1 2 3 4 5 6 7 | class User < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable # :confirmableを追加する end |
initializerを設定する
config/initializers/devise.rbに下記の設定を追加します。
1 2 3 4 5 6 7 8 9 | 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 = '自分のGmailアドレス' |
Gmailの設定を行う
config/environments/development.rbに下記の設定を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | Rails.application.configure do # trueにする config.action_mailer.raise_delivery_errors = true # 省略 config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } # 設定を追加 config.action_mailer.smtp_settings = { :enable_starttls_auto => true, :address => "smtp.gmail.com", :port => 587, :domain => 'smtp.gmail.com', :user_name => "自分のGmailアドレス", :password => "自分のGmailのパスワード", :authentication => 'login', } end |
Gmailアカウントの設定を行う
デフォルトの状態では、自分のGmailアカウントからメールを送ることができせん。
そのためGmailの「アカウント情報」画面から「ログインとセキュリティ」画面にアクセスし、ページの下部にある「安全性の低いアプリの許可」を有効にします。
(アプリ パスワードを発行するやり方もあります)
アカウントをロックする
パスワードを一定回数間違えた時にアカウントをロックするようにします。
initializerを設定する
config/initializers/devise.rbを下記の通り修正します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | Devise.setup do |config| # 省略 # Defines which strategy will be used to unlock an account. # :email = Sends an unlock link to the user email # :time = Re-enables login after a certain amount of time (see :unlock_in below) # :both = Enables both strategies # :none = No unlock strategy. You should handle unlocking by yourself. config.unlock_strategy = :both # ロック状態を解除する方法 # :email 登録したメールアドレス宛に、ロックを解除するリンクを送る # :time config.unlock_inで指定した時間が経過したら解除する # :both 上記の二つを併用する # :none 自動的にロックを解除しない(ユーザモデルのunlock_access!メソッドで解除できる) # Number of authentication tries before locking an account if lock_strategy # is failed attempts. config.maximum_attempts = 10 # パスワードをこの回数間違えるとアカウントがロックされる # Time interval to unlock the account if :time is enabled as unlock_strategy. config.unlock_in = 1.hour |
セッションをタイムアウトさせる
一定時間アクセスがなかった場合にセッションをタイムアウトさせます。
initializerを設定する
config/initializers/devise.rbを下記の通り修正します。
1 2 3 4 5 6 7 8 | Devise.setup do |config| # 省略 # ==> Configuration for :timeoutable # The time you want to timeout the user session without activity. After this # time the user will be asked for credentials again. Default is 30 minutes. config.timeout_in = 30.minutes |
さいごに
deviseを使ってユーザ登録フォームを実装する方法を紹介しました。