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

Rails4: deviseを使ってみる

More than 3 years have passed since last update.

はじめに

deviceは認証系で有名という話を聞き、これはキャッチアップしなければ!ということで実際に動かしてみようと思います。
https://github.com/plataformatec/devise
ここでは、まず動かすということで、設定はほぼデフォルトの状態です。

Railsアプリのひな形まで作成

  • 各モジュールのバージョンは下記のとおりです。インストールされていないのであれば適宜入れます。
$ ruby -v
ruby 2.2.4p230 (2015-12-16 revision 53155) [x86_64-linux]

$ rails -v
Rails 4.2.5

$ bundle -v
Bundler version 1.11.2
  • アプリの枠を作ります。
$ rails new myapp

deviseのインストール

  • Gemfileにdeviseを追加します。
Gemfile
gem 'devise'
  • bundle installを実行します。
$ bundle install

$ bundle show | grep devise
  * devise (3.5.3)

deviseの設定

0. deviseのインストール

$ rails g devise:install
Running via Spring preloader in process 8433
      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

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

上記のメッセージを順に対応していきます。

1. デフォルトURLの設定

config/environments/development.rb
Rails.application.configure do
  ...

  # devise の設定
  config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
end

2. root_urlの設定

config/routes.rb
Rails.application.routes.draw do
  root to: "home#index"
end
  • このタイミングでhome#indexファイルも作成します。
$ rails g controller Home index
Running via Spring preloader in process 31047
      create  app/controllers/home_controller.rb
       route  get 'home/index'
      invoke  erb
      create    app/views/home
      create    app/views/home/index.html.erb
      invoke  test_unit
      create    test/controllers/home_controller_test.rb
      invoke  helper
      create    app/helpers/home_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/home.coffee
      invoke    scss
      create      app/assets/stylesheets/home.scss

3. エラーや情報メッセージの表示場所設定

app/views/layouts/application.html.erb
<body>

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

<%= yield %>

</body>

4. HerokuでRails3.2を利用する場合の設定

  • Rails4なのでスキップします。

5. deviseのViewをカスタマイズするための設定

  • 今回はシンプルで行くのでスキップします。

deviseのユーザモデル

Userモデルの作成

  • モデルを生成して、ファイルの中身を見てみます。
$ rails g devise User
Running via Spring preloader in process 29880
      invoke  active_record
      create    db/migrate/20160105095646_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
  • ユーザモデルでコメントアウトされている:confirmable や :lockable は、migrateファイルのコメントアウトと一致します。つまりコメントを外すとmigrateファイルのコメント部分もはずさないとなりません。
app/models/user.rb
  1 class User < ActiveRecord::Base
  2   # Include default devise modules. Others available are:
  3   # :confirmable, :lockable, :timeoutable and :omniauthable
  4   devise :database_authenticatable, :registerable,
  5          :recoverable, :rememberable, :trackable, :validatable
  6 end
  • DBのカラム情報です。
db/migrate/20160105095646_devise_create_users.rb
  1 class DeviseCreateUsers < ActiveRecord::Migration
  2   def change
  3     create_table(:users) do |t|
  4       ## Database authenticatable
  5       t.string :email,              null: false, default: ""
  6       t.string :encrypted_password, null: false, default: ""
  7 
  8       ## Recoverable
  9       t.string   :reset_password_token
 10       t.datetime :reset_password_sent_at
 11 
 12       ## Rememberable
 13       t.datetime :remember_created_at
 14 
 15       ## Trackable
 16       t.integer  :sign_in_count, default: 0, null: false
 17       t.datetime :current_sign_in_at
 18       t.datetime :last_sign_in_at
 19       t.string   :current_sign_in_ip
 20       t.string   :last_sign_in_ip
 21 
 22       ## Confirmable
 23       # t.string   :confirmation_token
 24       # t.datetime :confirmed_at
 25       # t.datetime :confirmation_sent_at
 26       # t.string   :unconfirmed_email # Only if using reconfirmable
 27 
 28       ## Lockable
 29       # t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
 30       # t.string   :unlock_token # Only if unlock strategy is :email or :both
 31       # t.datetime :locked_at
 32 
 33 
 34       t.timestamps null: false
 35     end
 36 
 37     add_index :users, :email,                unique: true
 38     add_index :users, :reset_password_token, unique: true
 39     # add_index :users, :confirmation_token,   unique: true
 40     # add_index :users, :unlock_token,         unique: true
 41   end
 42 end

migrateする

  • DBを作っていなければ作成し、config/database.ymlを変更の上、migrateコマンドを実行します。
$ rake db:migrate
== 20160105095646 DeviseCreateUsers: migrating ================================
-- create_table(:users)
   -> 0.0059s
-- add_index(:users, :email, {:unique=>true})
   -> 0.0161s
-- add_index(:users, :reset_password_token, {:unique=>true})
   -> 0.0144s
== 20160105095646 DeviseCreateUsers: migrated (0.0366s) =======================
  • mysqlを利用したので下記が生成されることが確認できます。
mysql> desc users;
+------------------------+--------------+------+-----+---------+----------------+
| Field                  | Type         | Null | Key | Default | Extra          |
+------------------------+--------------+------+-----+---------+----------------+
| id                     | int(11)      | NO   | PRI | NULL    | auto_increment |
| email                  | varchar(255) | NO   | UNI |         |                |
| encrypted_password     | varchar(255) | NO   |     |         |                |
| reset_password_token   | varchar(255) | YES  | UNI | NULL    |                |
| reset_password_sent_at | datetime     | YES  |     | NULL    |                |
| remember_created_at    | datetime     | YES  |     | NULL    |                |
| sign_in_count          | int(11)      | NO   |     | 0       |                |
| current_sign_in_at     | datetime     | YES  |     | NULL    |                |
| last_sign_in_at        | datetime     | YES  |     | NULL    |                |
| current_sign_in_ip     | varchar(255) | YES  |     | NULL    |                |
| last_sign_in_ip        | varchar(255) | YES  |     | NULL    |                |
| created_at             | datetime     | NO   |     | NULL    |                |
| updated_at             | datetime     | NO   |     | NULL    |                |
+------------------------+--------------+------+-----+---------+----------------+
13 rows in set (0.00 sec)

routeの確認

  • Userモデル作成時にrouteも自動で生成されているので確認します。
$ rake routes
                  Prefix Verb   URI Pattern                    Controller#Action
              home_index GET    /home/index(.:format)          home#index
        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
           user_password POST   /users/password(.:format)      devise/passwords#create
       new_user_password GET    /users/password/new(.:format)  devise/passwords#new
      edit_user_password GET    /users/password/edit(.:format) devise/passwords#edit
                         PATCH  /users/password(.:format)      devise/passwords#update
                         PUT    /users/password(.:format)      devise/passwords#update
cancel_user_registration GET    /users/cancel(.:format)        devise/registrations#cancel
       user_registration POST   /users(.:format)               devise/registrations#create
   new_user_registration GET    /users/sign_up(.:format)       devise/registrations#new
  edit_user_registration GET    /users/edit(.:format)          devise/registrations#edit
                         PATCH  /users(.:format)               devise/registrations#update
                         PUT    /users(.:format)               devise/registrations#update
                         DELETE /users(.:format)               devise/registrations#destroy
                    root GET    /                              home#index

Viewの変更

ヘルパーメソッドを使ってViewにリンクを追加します。

deviseのヘルパーメソッド

  • user_signed_in?: ログイン中か確認
  • current_user:  ログイン中のユーザ(オブジェクト)
  • user_session: 現在のスコープのユーザセッション

もし、UserではなくMemberでモデルを作った場合は、user部がmemberに置き換えられるそうです。

Viewにリンクの追加

app/views/layouts/application.html.erb
<body>
  <% if user_signed_in? %>
    ログイン中: <strong><%= current_user.email %></strong>
    <%= link_to 'プロフィール変更', edit_user_registration_path %> |
    <%= link_to "ログアウト", destroy_user_session_path, method: :delete %>
  <% else %>
    <%= link_to "サインアップ", new_user_registration_path %> |
    <%= link_to "ログイン", new_user_session_path %>
  <% end %>

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

<%= yield %>

</body>

動かしてみる

起動

画面遷移

  • 初期画面
    016.png

  • サインアップ画面 (登録に成功すると、DBにレコードが挿入される)
    013.png

  • プロフィール変更
    014.png

  • ログアウト
    015.png

  • エラーメッセージの表示
    012.png

ハマったところ

  • ローカルにrailsを入れず、bundleのほうを使ったら、エラーが出ました。  bundleインストール済みの状態でもありネットで検索しても原因不明…。
$ bundle exec rails g devise:install
.rvm/rubies/ruby-2.2.4/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require': cannot load such file -- bundler/setup (LoadError)
  • bundle installでpath指定したらフリーズした。原因不明。このためpath未指定で対応。 途中で切断すると下記のようなメッセージが表示されました。
bundle/ruby/2.2.0/gems/spring-1.6.1/lib/spring/client/run.rb:99:in `gets': Interrupt
from bundle/ruby/2.2.0/gems/spring-1.6.1/lib/spring/client/run.rb:99:in `verify_server_version'
  • rvmを使っていたせいなのかは不明…。

参考サイト

http://ruby-rails.hatenadiary.com/entry/20140801/1406907000

tifa2chan
主にアプリ開発をしています。
future
ITを武器とした課題解決型のコンサルティングサービスを提供します
http://future-architect.github.io/
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