Edited at

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