devise (4.9.2) を使ってみる
https://gyazo.com/ba83d40a6ec0f6652f7428fa644ad5ac
以前、 Qiita で devise を使ってみるという記事を書きました。
時を経て、こちらの Gem を利用することになったので、改めて記事を書きたいと思います。
準備
code:bash
$ rails new rails_devise
$ cd rails_devise
$ bundle install --path=vendor/bundle
新規プロジェクトの作成と、初期のGemをインストールしました。
deviseのインストール
deviseをGemfileに追加します。
code:Gemfile
gem 'devise'
そしてインストールします。
code:bash
$ bundle install
さて、ここからdeviseを実装していきます。
code:bash
$ rails generate devise:install
create config/initializers/devise.rb
create config/locales/devise.en.yml
===============================================================================
Depending on your application's configuration some manual setup may be required:
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.
* Required for all applications. *
2. Ensure you have defined root_url to *something* in your config/routes.rb.
For example:
root to: "home#index"
* Not required for API-only Applications *
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>
* Not required for API-only Applications *
4. You can copy Devise views (for customization) to your app by running:
rails g devise:views
* Not required *
===============================================================================
インストールすると、何やら注意文が出てきました。
これらの文言に従い、対応していきます。
デフォルトURLの指定]
今回はローカル環境で試すだけなので、localhost:3000を指定するため、以下の行を追加します。
code:config/environments/development.rb
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
root_urlの指定
http://localhost:3000にアクセスしたとき呼ばれるページの指定をします。
特別なことはなく、 root to でルートパスを指定すれば良いです。
Flashメッセージの設定
Flashメッセージが表示される場所を追記します。
以下の行をそのまま追記すれば良いようです。
code:app/views/layouts/application.html.erb
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
Viewの作成
devise のビューをカスタマイズしたい場合は、以下のコマンドでファイルを app/views 以下に生成します。
code:bash
$ rails g devise:views
モデルの作成
devise用のモデルを作成し、マイグレーションを走らせます。
(モデル名は任意です。)
code:bash
$ rails g devise Admin
$ rails db:migrate
こちらで、モデルとマイグレーションファイルが生成されます。
合わせて、マイグレーションも実行しておきます。
マイグレーションファイルは以下のようになっております。
デフォルトでコメントアウトされている部分もオープンにできますが、今回はライトに作りたいため、デフォルトのままでいきます。
モデルには、以下のようにデフォルトで設定されているモジュールと、任意で設定できるモジュールがあります。
code:admin.rb
class Admin < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
end
今回はデフォルトなので、初めから使用できる下記のモジュールを使用します。
table:devise
モジュール名 役割
Database Authenticatable ユーザーがサインインする時に認証するためにパスワードをデータベースに暗号化し保存します。この認証は POST リクエストまたはBasic認証を通して行われます。
Registerable 登録プロセスを通してサインアップを処理します。また、アカウントを編集・削除できるようにします。
Recorverble パスワードをリセットし、リセットの指示を送ります。
Rememberable ユーザーを記憶するために、保存されたクッキーから、トークンを生成・消去を扱います。
Trackable サインインのカウント・タイムスタンプ・IPアドレスを計測します。
Validatable Eメールとパスワードによる確認を提供します。これは、オプションでカスタマイズできるので、あなた専用の確認を定義できます。
ここまでで、とりあえずrails sでローカルサーバーを起動させ確認してみると、特に何もありません。
ヘルパーの実装
ユーザーがログインしていなければリダイレクトさせるのは、下記をapplication_controller.rbに追記します。
code:app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_action :authenticate_admin!
再度、ページにアクセスしてみると、ログインページにリダイレクトされます。
このビューは、views/devise/sessions/new.html.rbになります。(rails routesで確認できます。)
とりあえず新規登録をしてみると、下図のようにログインまでしてくれます。
もし特定のアクション(例えば show のみログイン必須にする場合は、以下のように修正します。
code:rb
before_action :authenticate_admin_user!, only: :show ログイン後のリダイレクト先を変更する
after_sign_in_path_forやafter_sign_out_path_forで上書きしてしまうようです。
必ず呼ばれるapplication_controller.rbに記述します。
code:app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_action :authenticate_admin_user!, only: :show def after_sign_in_path_for(resource)
pages_show_path
end
ログインとログアウトのリンクを設置する
ログインするのもログアウトするのもリンクがあると楽なので、簡単に設置してしまいます。
code:app/views/layouts/application.html.erb
<%= link_to 'Login', new_admin_user_session_path, method: :get %>
<%= link_to 'Logout', destroy_admin_user_session_path, method: :delete %>
ログインしている場合としていない場合でリンクを出し分ける
他にも便利なヘルパーがあり、user_signed_in?でログインしているかどうかの結果を返してくれます。
(ただし、今回はモデル名をAdmin_Userにしたため、下記のサンプルの中ではadmin_user_signed_in?となっています。)
これで、ログインとログアウトのリンクを出し分けたいと思います。
code:app/views/layouts/application.html.erb
<% if admin_user_signed_in? %>
<%= link_to 'Logout', destroy_admin_user_session_path, method: :delete %>
<% else %>
<%= link_to 'Login', new_admin_user_session_path, method: :get %>
<% end %>
ログインしているユーザーの情報を取得
こちらはcurrent_userでオブジェクトを取得できます。
(ただし、今回はモデル名をAdmin_Userにしたため、下記のサンプルの中ではcurrent_admin_userとなっています。)
また、user_sessionで現在のセッション情報を取得できるようですが、初期状態は空っぽです。
code:app/views/pages/show.html.erb
<h1>Hi!!<%= current_admin_user.email %>!!</h1>
<p><%= debug(admin_user_session) %></p>
複数の認証機能を実装する
管理ユーザーと一般ユーザーでログイン処理を分けたいケースがあるかと思います。
その場合は、コントローラーやビューをネームスペース分けて作成することができます。
まずは、 devise の設定ファイルにて、以下の項目を true に変更します。
code:config/initializer/devise.rb
config.scoped_views = true
その後、コントローラーとビューを作成するために、以下のコマンドを実行します。
code:bash
$ rails g devise:controllers admins
$ rails g devise:views admins
これで、ネームスペースを切った状態のファイルが生成されます。
ただ、ここで routes.rb に追加された devise_for で生成されたルーティングは、デフォルトのコントローラーを指定してしまいます。
そのため、以下のように意図したコントローラーにマッピングされるようにします。
code:config/routes.rb
devise_for :admins, controllers: {
sessions: 'admins/sessions',
passwords: 'admins/passwords',
registrations: 'admins/registrations'
}
最後に
今回、モデル名をUserではなく、Admin_Userにしたため、基本ヘルパーのuserの部分をadmin_userにする必要がありました。
モデル名をUser以外にしようとしている方は要注意です。
ビューが少し寂しいので、Bootstrapで少し整えたいと思います。