deviseを使ってRailsアプリに簡単なログイン認証を実装してみる
- やること
- deviseを使う準備
- viewファイルの作成
- Userモデルを作成する
- 現時点でのルーティングを確認
- コントローラーを作成
- DBをのぞいてみる
- リポジトリ
- 次はFacebook認証を実装する
- 参考
やること
- devise gemを使ってRailsアプリに簡単なログイン認証を実装してみる
開発環境
deviseを使う準備
rails newでRailsアプリの雛形を作成する。
データベースを指定していないので、デフォルトではsqlite3が使われる。
rails new omniauth-test
(今後、omniauthというgemを使ったSNS認証機能も実装する予定のため、ここではomniauth-testという名前にしている)
アプリが作成されたら移動。
cd omniauth-test
deviseをインストールするため、Gemfileの一番下に以下を追記。
gem 'devise'
bundle installする。(bundleと書いてもbunlde installが実行される)
bundle
deviseをGemfileに記述してインストールしたものの、まだこれでは使えない。 以下のコマンドで、deviseの基本機能をRailsアプリにインストールする。
bin/rails g devise:install
するとこんな画面が現れる。
Running via Spring preloader in process 99124
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
===============================================================================
上からみていくと、まずdeviseの設定ファイルとロケールファイルが作成されている。
create config/initializers/devise.rb create config/locales/devise.en.yml
それ以下には、「初期設定はこうしてよね」と書いてるので、とりあえず言われるがままにやる。
config/environments/development.rb
# 以下を追記
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
config/routes.rb
# 追記 root to: 'home#index'
※後でコントローラーとメソッドを実装します。
app/views/layouts/application.html.erb
<body> # 追記 <p class="notice"><%= notice %></p> <p class="alert"><%= alert %></p> <%= yield %> </body>
前準備が終わったので、一旦gitでコミットしておく。
git add . git commit -m "deviseを使う前準備完了"
viewファイルの作成
deviseが提供するコマンドで、ユーザー登録に関するviewファイルたちが生成される。ユーザー登録画面や、「パスワードを忘れましたか?」的な画面など、いろんなWEBアプリでよく見かけるやつ。
bin/rails g devise:views
実は、このコマンドを実行しなくても、deviseでログイン認証画面は表示される。 しかし、実際は登録画面をカスタマイズする場合がほとんどなので、上記コマンドを実行し、いろいろいじる。
Userモデルを作成する
ログインしてきたユーザーを保存するため、deviseの機能を持ったUserモデルを作成する。
bin/rails g devise User
通常のモデルを作成する場合は、rails g model Userなどとするが、deviseの機能を受け継ぎたいので、deviseコマンドを入れている。
実行後、こんな画面が表示される。
invoke active_record
create db/migrate/20200222031348_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
作成されたapp/models/user.rbを見てみると、deviseの機能(モジュール)が記述されているのがわかる。これは、deviseのコマンドでUserモデルを作成したため。
class User < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable end
デフォルトで有効になっているのは、次のモジュールたち。
| モジュール | 機能 |
|---|---|
| database_authenticatable | ユーザー情報を保存するのにDBを使う |
| registerable | ユーザーを登録、編集、削除できる |
| recoverable | パスワードをリセットできる |
| rememberable | Cookieにログイン情報を保存する |
| validatable | メールアドレスとパスワードをバリデーションする |
コメントアウトされているこちらの部分は、デフォルトでは無効になっている。
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
| モジュール | 機能 |
|---|---|
| confirmable | 登録されたemailに送信する |
| lockable | ログインを数回したらロックする |
| timeoutable | 一定期間でタイムアウトさせる |
| trackable | ログイン時の情報を保存 |
| omniauthable | OmniAuth gemと連携する |
たとえば、Facebook認証を実装したい場合、omniauthable を有効にする必要がある。
テーブルに保存される内容をチェック
マイグレーションファイルを見て、どんなカラムが作成されるか見てみる。
# 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
emailアドレスや、暗号化されたパスワードが保存されている。
## Database authenticatable t.string :email, null: false, default: "" t.string :encrypted_password, null: false, default: ""
マイグレーションを実行
マイグレーションを実行する。
bin/rails db:migrate
データベースがsqlite3の場合、rails newをした時点でデータベースは作成されているので、マイグレーションだけでいい。
データベースとしてPostgresqlやMysqlなどを使用しているなら、db:createでデータベースを作成する。
bin/rails db:create
現時点でのルーティングを確認
routes.rbを見てみる。
Rails.application.routes.draw do devise_for :users root to: "home#index" end
devise_forはこれまたdeviseが勝手に書いてくれてるもの。具体的にはbin/rails g devise Userをしたときに追記されている。
ここでは、ユーザー登録や編集に関係するページへのルーティングを自動で定義してくれている。
bin/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
Devise::SesstionsControllerという専用のコントローラーは作成していないが、devise/sessions#newなどと記述されている。
これは、deviseが定義しているもの。
一旦コミットする
Userモデルを作ったので、ここで一旦コミットしておく。
git add . git commit -m "モデル作成"
コントローラーを作成
いよいよ、ページを表示させるためコントローラーとビューファイルを作成する。
bin/rails g controller home index
homeコントローラーを作成し、indexアクションを定義している。 これは、ルーティングで設定したとおりにコントローラーとアクションを作っているだけ。
# routes.rb root to: "home#index"
「ルートパス(localhost:3000)にアクセスしたら、homeコントローラーのindexアクションが実行される」という意味。
作成されたapp/controllers/home_controller.rbを次のように修正する。
class HomeController < ApplicationController #追記 before_action :authenticate_user!, only: :index def index end end
authenticate_user!はdeviseが提供するメソッド。ログインしていない場合にアクセスしたら、ログイン画面にリダイレクトされる。「ログインしてからまた来てねー」みたいな感じ。
app/views/home/index.html.erbに追記
<h1>Home#index</h1> <p>Find me in app/views/home/index.html.erb</p> #追記 <%= current_user.email %>
current_userは、deivseを入れると使えるようになるメソッド。
current_user.emailとすることで、ログインしているユーザーの、DBに保存された情報が参照できる。
参照するときには、カラム名を記述すればいい。current_user.nameなど。
ビュー側だけではなく、コントローラーなどでも使用できる。
ちなみに、作成したモデル名がMemberモデルだったら、current_memberとなる。
ここでは、ログインできたことがわかりやすくなるように、ログイン後は自分のemailを表示させるようにしている。
app/views/layouts/application.html.erbを修正
共通のレイアウトに追記。
<body>
# ここから
<header>
<nav>
<% if user_signed_in? %>
<%= link_to "logout", destroy_user_session_path, method: :delete %>
<% else %>
<%= link_to "sign up", new_user_registration_path %>
<%= link_to "login", new_user_session_path %>
<% end %>
</nav>
</header>
# ここまで
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
<%= yield %>
</body>
if user_signed_in?はdeviseが提供しているメソッドで、「あなた、ログインしてんの?」とif文で判断している。
ログインしていればtrueを返すため、if~elseまでのコードを実行する。
つまり、ログインしていると、logoutへのリンクが表示される。
ログインしていなければ、signupとloginへのリンクが表示される。
サーバーを起動して画面を確認
サーバーを起動すると
bin/rails s
こんな画面が表示される。

sign_up画面へいき、「example@example.com」で登録すると、

ビューファイルで記述したcurrent_user.emailが表示されているのがわかる。
ちなみに、登録したパスワードはdeviseが自動で暗号化してくれるので安心。
簡易的だが、これでdeviseを使ったログイン認証が実装できた。
DBをのぞいてみる
サインアップ時に入力したデータが、ちゃんとUsersテーブルに保存されているかチェックしてみる。 コンソールを開く。
rails c
以下コマンドを入力。
User.first
User.firstで、Userモデルの先頭のユーザーを参照できる。
=> #<User id: 1, email: "example@example.com", created_at: "2020-02-22 03:54:34", updated_at: "2020-02-22 03:54:34"> irb(main):002:0>
登録に使ったメールアドレス、example@example.comがしっかり保存されている。
リポジトリ
今回書いたコードはこちらです。
https://github.com/kotakanazawa/omniauth-test
次はFacebook認証を実装する
続き