deviseを試してみた
Railsでユーザ認証といったら、devise
が一番有名なのですが、いまいち理解が足りなかったので、実装しながらどんな感じにデータが入るのか等を見ていきたいと思います。
インストール
$ mkdir sample-devise $ cd sample-devise && rails new . -d mysql -B -T
Gemfile
以下をGemfileに追加(materialzecssはちょっと使ってみたかったのでいれています)
gem 'materialize-rails', '~> 0.97.5.2' gem 'devise', '~> 4.3'
$ bundle install --path=vendor/bundle
devise設定
devise install
deviseを利用するには、devise:installコマンドを一番最初に実行する必要があります。 作成されるのは、deviseの初期設定ファイルと、devise英語メッセージのようです。
$ rails g 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. You can copy Devise views (for customization) to your app by running: rails g devise:views ===============================================================================
出力された内容にしたがって、deviseの設定をしていく必要があります。
- デフォルトURLの設定
- root_urlの設定
- flashメッセージの設定
- deviseのviewを生成
デフォルトURLの設定
デフォルトURLは出力の内容通りに修正しました。
- config/environments/development.rb
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
モデルの作成
deviseで利用するUser
モデルを生成します。
$ rails g devise User invoke active_record create db/migrate/20170611032037_devise_create_users.rb create app/models/user.rb insert app/models/user.rb route devise_for :users
テーブルの作成
$ rails db:create $ rails db:migrate
作成されたテーブルの内容は以下のとおりです。
$ rails dbconsole mysql> SHOW CREATE TABLE users \G; *************************** 1. row *************************** Table: users Create Table: CREATE TABLE `users` ( `id` int(11) NOT NULL AUTO_INCREMENT, `email` varchar(255) NOT NULL DEFAULT '', `encrypted_password` varchar(255) NOT NULL DEFAULT '', `reset_password_token` varchar(255) DEFAULT NULL, `reset_password_sent_at` datetime DEFAULT NULL, `remember_created_at` datetime DEFAULT NULL, `sign_in_count` int(11) NOT NULL DEFAULT '0', `current_sign_in_at` datetime DEFAULT NULL, `last_sign_in_at` datetime DEFAULT NULL, `current_sign_in_ip` varchar(255) DEFAULT NULL, `last_sign_in_ip` varchar(255) DEFAULT NULL, `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `index_users_on_email` (`email`), UNIQUE KEY `index_users_on_reset_password_token` (`reset_password_token`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec)
最終ログイン時間や、ログインカウント、IP等を記録してくれる設計になっている模様
コントローラの作成
ユーザ認証を掛けるコントローラを生成します。
$ rails g scaffold_controller User create app/controllers/users_controller.rb invoke erb exist app/views/users create app/views/users/index.html.erb create app/views/users/edit.html.erb create app/views/users/show.html.erb create app/views/users/new.html.erb create app/views/users/_form.html.erb invoke helper create app/helpers/users_helper.rb invoke jbuilder create app/views/users/index.json.jbuilder create app/views/users/show.json.jbuilder create app/views/users/_user.json.jbuilder
- 認証制限を追加
認証を掛けたいcontrollerにauthenticate_モデル名!
を追加します。
app/controllers/users_controller.rb
before_action :authenticate_user!
ビューの作成
devise用のviewを作成します。
$ rails generate devise:views users Expected boolean default value for '--markerb'; got :erb (string) 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/email_changed.html.erb create app/views/users/mailer/password_change.html.erb create app/views/users/mailer/reset_password_instructions.html.erb create app/views/users/mailer/unlock_instructions.html.erb
Routing変更
Rails.application.routes.draw do resources :users root 'users#index' devise_for :users, controllers: { sessions: 'users/sessions' }, path: 'auth', path_names: { sign_in: 'login', sign_out: 'logout', password: 'secret', confirmation: 'verification', unlock: 'unblock', registration: 'register', sign_up: 'cmon_let_me_in' } devise_scope :user do get 'sign_in', to: 'devise/session#new' end end
ログアウト処理
Cookieにdevise_sessionが保存されていて、それを削除するのがsession#destroy
メソッドのようです。
rails routes ... destroy_user_session DELETE /auth/logout(.:format) users/sessions#destroy
DELETEで該当URIをcallする
- app/assets/javascripts/users.js
$(function(){ 'use strict'; $('#logout').click(function(){ $.ajax({ url: "/auth/logout.json", method: "DELETE", contentType: "application/json" }).done(function(data) { console.debug(data); location.href = "/"; }).fail(function(data) { console.error(data); }); }); });
あとはHTMLに該当ボタンを設置する
user_session
メソッドでuser sessionを判定する
<ul id='dropdown1' class='dropdown-content'> <% if user_session %> <li><a href="#" id="logout">Logout</a></li> <% else %> <li><a href="/auth/register/cmon_let_me_in" id="sign-up">Sign up</a></li> <li><a href="/auth/login" id="login">Login</a></li> <% end %> </ul>
確認
$ rails s
localhost:3000へアクセスすると、認証していない場合、以下のような認証画面に遷移します。
認証に成功すると、User一覧画面に遷移することが出来るようになります。
今回実装したソースは以下に上げています。
触りは大体こんなもので、実運用に用いるには、もう少し深い部分の理解も必要になってくるかなと思います。