development > Ruby On Rails > deviseでRailsアプリにユーザー認証機能を追加する
Ruby On Rails

deviseでRailsアプリにユーザー認証機能を追加する

Large?1464705267

Webアプリを作っていると、結構な確率でユーザー認証を実装することがあります。RailsではDeviseというgemがデファクトになっていて、だいたいの機能はこのgemを導入することで実現できてしまいます。

今回は、まず最初にセットアップの方法をご紹介。

インストールする

まずはGemfileに

gem 'devise'

と追記し、bundle installしましょう。次に、

$ bundle exec rails g devise:install

でdeviseをインストールします。すると、以下の様な表示が出ると思います。

      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. If you are deploying on Heroku with Rails 3.2 only, you may want to set:
       config.assets.initialize_on_precompile = false
     On config/application.rb forcing your application to not access the DB
     or load models when precompiling your assets.
  5. You can copy Devise views (for customization) to your app by running:
       rails g devise:views
===============================================================================

まず一番上に表示されている

      create  config/initializers/devise.rb
      create  config/locales/devise.en.yml

は、その表示のとおりですが、deviseのイニシャライザーと英語版のロケールファイルが生成されたことを表しています。それ以下の表示は、セットアップの手順を示しているものです。これに沿ってセットアップを進めていきましょう。

config.action_mailer.default_url_optionsをセットする

まずconfig/environments/development.rbを開き、

# Don't care if the mailer can't send.
  config.action_mailer.raise_delivery_errors = false
  config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }  #これを追記

指示の通りconfig.action_mailer.default_url_options = { host: 'localhost', port: 3000 }を追記します。

root to: "home#index"をルーティングに加える

コントローラーを以下のコマンドで生成します。

$ bundle exec rails g controller home index

そして、config/routes.rbを開いて

Rails.application.routes.draw do
  root to: "home#index"  # 追記した
  get 'home/index'  # rails g controllerで作られた
  (省略)
end

とします。

アラートを表示できるようにする

アラートを挿入するため、app/views/layouts/application.html.erbを

<!DOCTYPE html>
<html>
<head>
  <title>DeviseDemo</title>
  <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true %>
  <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
  <%= csrf_meta_tags %>
</head>
<body>
  <% if notice %>
    <p class="notice"><%= notice %></p>
  <% elsif alert %>
    <p class="alert"><%= alert %></p>
  <% end %>
<%= yield %>
</body>
</html>

とします。<%= yield %>の上にアラートが挿入されています。

残りのメッセージは?

インストール時のメッセージには

  4. If you are deploying on Heroku with Rails 3.2 only, you may want to set:
       config.assets.initialize_on_precompile = false
     On config/application.rb forcing your application to not access the DB
     or load models when precompiling your assets.

と、

5. You can copy Devise views (for customization) to your app by running:
       rails g devise:views

の2つがまだ残っています。4.については、今回はRails4で作業しているのでスキップです。5.は、実行時のオプションがあるので後ほど詳しく説明しようと思います。

deviseで管理するmodelを作成

ではいよいよ、ユーザー認証用のモデルを作成します。今回はUserというモデルを作ってみたいと思います。deviseはジェネレーターを用意してくれているので、

$ bundle exec rails g devise User

を実行するだけでOKです。実行すると、

      invoke  active_record
      create    db/migrate/20150903121655_devise_create_users.rb
      create    app/models/user.rb
      insert    app/models/user.rb
       route  devise_for :users

と表示されると思います。この表示から、マイグレーションファイルとuserモデルとルーティングが追加されたことがわかります。

マイグレーション

生成されたマイグレーションファイル見てみると、

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

ファイル内に## Database authenticatableであったり## Recoverableの様なブロックがいくつもあると思います。これらがdeviseがユーザー認証に関して持っている機能です。全部で

  • Database Authenticatable
  • Omniauthable
  • Confirmable
  • Recoverable
  • Registerable
  • Rememberable
  • Trackable
  • Timeoutable
  • Validatable
  • Lockable

の10個のモジュールがあります。このうち、confirmable、 lockable、 timeoutable、omniauthableの4つは初期は無効化されています。各機能を有効化・無効化するには、app/models/user.rbにデフォルトで設定されている

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

を、

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

のように編集することで調整可能です。それでは、bundle exec rake db:migrateを実行しましょう。

viewファイルを生成する

さきほどdeivseをインストールした際のメッセージに、

5. You can copy Devise views (for customization) to your app by running:
       rails g devise:views

というものがあったと思います。このrails g devise:viewsを実行するとviewファイルを生成することが出来るのですが、このまま実行すると、

      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/reset_password_instructions.html.erb
      create    app/views/devise/mailer/unlock_instructions.html.erb

この様にapp/views/devise/配下にviewファイルが生成されます。これをモデルやコントローラーと同じようにapp/views/usersにviewファイルを生成するためには、

$ bundle exec rails g devise:views users

を実行します。すると、

      invoke  Devise::Generators::SharedViewsGenerator
      create    app/views/users/shared
      create    app/views/users/shared/_links.html.erb
      invoke  form_for
      create    app/views/users/confirmations
      create    app/views/users/confirmations/new.html.erb
      create    app/views/users/passwords
      create    app/views/users/passwords/edit.html.erb
      create    app/views/users/passwords/new.html.erb
      create    app/views/users/registrations
      create    app/views/users/registrations/edit.html.erb
      create    app/views/users/registrations/new.html.erb
      create    app/views/users/sessions
      create    app/views/users/sessions/new.html.erb
      create    app/views/users/unlocks
      create    app/views/users/unlocks/new.html.erb
      invoke  erb
      create    app/views/users/mailer
      create    app/views/users/mailer/confirmation_instructions.html.erb
      create    app/views/users/mailer/reset_password_instructions.html.erb
      create    app/views/users/mailer/unlock_instructions.html.erb

このようにapp/views/users配下にviewファイルが生成されました。

これは、命名が分かりやすくなるだけでなく、例えばUserとAdminでそれぞれ認証するような複数のモデルをdeviseで管理する際に重要になってきます。

この場合、bundle exec rails g devise:views usersとbundle exec rails g devise:views adminsとすると2セットのviewファイルが生成されるので、それぞれを別の見た目に編集することも出来ます。

その際には、config/initializers/devise.rbにある

# ==> Scopes configuration
# Turn scoped views on. Before rendering "sessions/new", it will first check for
# "users/sessions/new". It's turned off by default because it's slower if you
# are using only default views.
# config.scoped_views = false

# ==> Scopes configuration
# Turn scoped views on. Before rendering "sessions/new", it will first check for
# "users/sessions/new". It's turned off by default because it's slower if you
# are using only default views.
config.scoped_views = true

に変更してあげましょう。

Sign Up/Sign In/Sign Outリンクを追加する

ここまでの作業でユーザー認証に関する実装はほぼ完了しました。最後にサインアップ、サインイン、サインアウトのリンクを追加しましょう。app/views/layouts/application.html.erbの<body>タグのすぐ下に、

<body>
  <% if user_signed_in? %>
    Logged in as <strong><%= current_user.email %></strong>.
    <%= link_to 'Edit profile', edit_user_registration_path, :class => 'navbar-link' %> |
    <%= link_to "Logout", destroy_user_session_path, method: :delete, :class => 'navbar-link'  %>
  <% else %>
    <%= link_to "Sign up", new_user_registration_path, :class => 'navbar-link'  %> |
    <%= link_to "Login", new_user_session_path, :class => 'navbar-link'  %>
  <% end %>
  <% if notice %>
    <p class="notice"><%= notice %></p>
  <% elsif alert %>
    <p class="alert"><%= alert %></p>
  <% end %>
  <%= yield %>
</body>

リンクを追加します。

実装を確認

最後に、bundle exec rails sでサーバーを起動して画面を確認してみましょう。メールアドレスとパスワードを入力することで、ユーザーの認証ができるようになっていると思います。

devise導入により使えるようになるヘルパー

deviseを導入すると、

  • before_action :authenticate_user!
  • user_signed_in?
  • current_user
  • user_session

のヘルパーが使えるようになります。

before_action :authenticate_user!
これはコントローラーに設定することで、認証済みのユーザーだけがアクセス出来るようにするものです。

class ArticlesController < ApplicationController
  before_action :authenticate_user!

  def index
  end

  def show
  end
end

の様にすると認証済みのユーザーしかこのコントローラーにはアクセスできなくなります。また、

class ArticlesController < ApplicationController
  before_action :authenticate_user!, only: :index

  def index
  end

  def show
  end
end

とすると、indexアクションのみユーザー認証を掛けることが出来ます。

user_signed_in?
これは、ユーザーがサインイン済みか検証するためのものです。例えばif user_signed_in?の様に書けば、条件分岐に使うことが出来ます。

current_user
これは、サインイン中のユーザーを取得するものです。このまま

= current_user.email
# ユーザーのメールアドレス(email)を返す

の様に使うことができます。

user_session
これは言葉通り、ユーザーのセッション情報を取得するものです。上記3つと比較するとあまり利用頻度は高くないかもしれません。

まとめ

以上がdeviseのセットアップ方法でした。今回はdevise導入により利用できる機能のごく一部しかご紹介できていませんが、deviseを使うことで非常に簡単に豊富なユーザー認証機能を利用することが出来るようになります。

deviseの便利な使い方などは次回以降にご紹介していくので、よろしければそちらもご覧ください。

Small?1464705267

この記事が気に入ったらいいね!して
9bar の最新記事を受け取りましょう

Thumb?1464705267

9bar の最新記事をお届けします!

新着記事