Help us understand the problem. What is going on with this article?

Rails 4.2 で ユーザー管理・認証 (devise)

More than 5 years have passed since last update.

devise とは

Rails でログイン認証管理を行う際のメジャーな Gem 。
以下の10個のモジュールからなる。

  • Database Authenticatable:
    • DB に保存するパスワードの暗号化。ほぼ必須のモジュール。
    • POST リクエストや Basic 認証で使われる。
  • Omniauthable:
    • OmniAuth サポートのためのモジュール。
    • Twitter などの外部サービスのアカウントでユーザー登録させたい場合に追加する。
  • Confirmable:
    • アカウント作成の際のメール認証モジュール。
    • メール中のリンクをクリックしないとログインできないようにできる。
  • Recoverable:
    • パスワードリセットが可能になる。
  • Registerable:
    • サインアップ処理が可能になる。
  • Rememberable:
    • クッキーに保存されたトークンの生成・削除を行う。
  • Trackable:
    • ログイン時のデータ (サインイン回数・時刻・IPアドレス) をDBに保存する。
  • Timeoutable:
    • 一定時間でセッション情報を削除する。
  • Validatable:
    • メールアドレスとパスワードのバリデーションを行う(設定ファイルで変更可能)。
  • Lockable:
    • 規定回数以上ログインに失敗したらアカウントをロックする。

インストール

開発環境の準備

今回は Rails (4.2.0) と devise (3.4.1) 環境でテストする。
DBはSQLite3をそのまま利用する。
これらが動作する環境を準備しておく。

Rails アプリケーション作成

以下のコマンドを実行していく。

$ mkdir -p ~/projects/devise_rails_admin_app
$ cd ~/projects/devise_rails_admin_app
$ bundle init

作成されたGemfileを以下のように書き換える。

Gemfile
source 'https://rubygems.org'

gem 'rails', '4.2.0'

以下のコマンドを実行。

$ bundle install --path vendor/bundle
$ bundle exec rails new .
...
Overwrite /home/vagrant/projects/capistrano_sample/Gemfile? (enter "h" for help) [Ynaqdh] Y
...

Gemfile を下記のように書き換える。

Gemfile
source 'https://rubygems.org'

gem 'rails', '4.2.0'
gem 'sqlite3'
gem 'sass-rails', '~> 5.0'
gem 'uglifier', '>= 1.3.0'
gem 'coffee-rails', '~> 4.1.0'
gem 'therubyracer', platforms: :ruby
gem 'jquery-rails'
gem 'turbolinks'
gem 'jbuilder', '~> 2.0'
gem 'sdoc', '~> 0.4.0', group: :doc
gem 'bcrypt', '~> 3.1.7'
gem 'devise'
gem 'rails_admin'

group :development, :test do
  gem 'byebug'
  gem 'web-console', '~> 2.0'
  gem 'spring'
end

下記コマンドを実行。

$ bundle install --path vendor/bundle

devise のインストール

下記コマンドを実行。

$ bundle exec rails generate 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. 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

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

このような出力が出る。

environments の設定

config.action_mailer.default_url_options の設定
config/environments/ 以下のファイル(development.rbproduction.rb など) に下記の行を追加
(host や port は各環境に合わせる)。

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

root ページの作成

下記コマンドで root ページ用の Controller を作成する。

$ bundle exec rails generate controller home index

ログイン・サインアップ画面へのリンク追加

views/home/index.html.erb にログイン画面とサインアップ画面へのリンク追加。

views/home/index.html.erb
<h1>Home#index</h1>
<% if user_signed_in? %>
  Logged in as <strong><%= current_user.email %></strong>.
  <%= link_to "Settings", 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 %>
<p>Find me in app/views/home/index.html.erb</p>

root_url の設定

config/routes.rb に root_url を記述する。

routes.rb
Rails.application.routes.draw do
  get 'home/index'
  root 'home#index'
end

ログイン情報の画面への出力

app/views/layouts/application.html.erb の設定
<%= yield =%> の行のすぐ上の部分に下記記述を追加。

<% if notice %>
  <p class="alert alert-success"><%= notice %></p>
<% end %>
<% if alert %>
  <p class="alert alert-danger"><%= alert %></p>
<% end %>

ログイン時のみ内容を確認できるように設定

app/controllers/application_controller.rbbefore_action を追加。

app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_action :authenticate_user!
  protect_from_forgery with: :exception
end

今回は生成したモデルが user なので、authenticate_user! となる。
他のモデル名の場合、userの部分を書き換える。

User Model の生成

下記コマンドで devise を利用して User Model を生成する。

$ bundle exec rails generate devise user
$ bundle exec rake db:migrate

動作確認

下記コマンドでアプリケーションサーバ起動。

$ bundle exec rails server -b 0.0.0.0

ブラウザからアクセスすると下記のような画面が見えるはず。
d1acfa5d4de432c9d70911ac545fe64c.png

サインアップ画面はこんな感じ。
c367f156b979c651cdb3cce043a65b9e.png

ログイン後の home/index.html
10cbd56aa249dc8a016b243ba18207e1-2.png

devise のカスタマイズ・情報取得

メール周り

このままだとパスワードリセット等の機能が正常に働かないためメーラー用の設定をする。
config/environments/development.rb に次のような設定を行う。
例として Gmail を利用する場合の記述を記載している。

config/environments/development.rb
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
  :address => 'smtp.gmail.com',
  :port => 587,
  :authentication => :plain,
  :user_name => 'メールアドレス',
  :password => 'パスワード'
}

ユーザーがサインインしているかどうかの判定

hoge_controller.rb
# 戻り値が true ならサインイン済み。
user_signed_in?
# サインインしている全ユーザー取得
current_user
# ユーザーのセッション情報
user_session

devise の View をカスタマイズする

下記のコマンドで app/view/devise 以下に devise の View が作成される。

$ rails generate devise:views

対応関係は下記のようになっている。

  • ログイン: app/views/devise/sessions/new.html.erb
  • ユーザー登録: app/views/devise/registrations/new.html.erb
  • ユーザ情報変更: app/views/devise/registrations/edit.html.erb
  • パスワード変更: app/views/devise/passwords/edit.html.erb
  • メール認証: app/views/devise/confirmations/new.html.erb
  • パスワードリセット: app/views/devise/passwords/new.html.erb
  • アカウントアンロック: app/views/devise/unlocks/new.html.erb

devise で作成したモデルにカラム追加

bundel exec rails generate migration … で追加すれば良い。

$ bundle exec rails generate migration add_name_to_users name:string

index や unique 制約が必要な場合は db/migrate/[yyyymmddHHMMSS]_add_name_to_users.rb
にこのタイミングで追加してやる。

$ bundle exec rake db:migrate

仮に認証キーを email から name に変更する場合は
config/initializers/devise.rbconfig.authentication_keys を変更すれば良い。

unique 制約等を追加した場合は Users Model に validate を追記する。

サインアップ時に追加したカラムも入力させたい場合は
app/views/devise/registrations/new.html.erb
にフィールドを追加する。

プロフィール画面に表示を追加したい場合は
app/views/devise/registrations/edit.html.erb
に追加する。

参考資料

devise README
Railsの一番人気のログイン認証gemのDeviseの導入方法
Railsの一番人気のログイン認証gemのDeviseのカスタマイズ方法
Rails4 にて Devise でユーザー登録・ログイン認証・認可の機能を追加

Salinger
the-room4d
データを分析してます。
https://the-room.company/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした