deviseというgemを使用する機会があったので、簡単に使い方をまとめます。 devise とは、railsのgemの1つでログイン認証を行えるようにするgemです。
開発環境
gemファイルに、以下の記述を追加します。
gem '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 ===============================================================================
rails g devise:viewsコマンドを実行して、devise関連のviewを作成します。
実行結果
$ docker-compose exec app bundle exec rails g devise:views invoke Devise::Generators::SharedViewsGenerator create app/views/devise/shared create app/views/devise/shared/_links.html.erb invoke form_for create app/views/devise/confirmations create app/views/devise/confirmations/new.html.erb create app/views/devise/passwords create app/views/devise/passwords/edit.html.erb create app/views/devise/passwords/new.html.erb create app/views/devise/registrations create app/views/devise/registrations/edit.html.erb create app/views/devise/registrations/new.html.erb create app/views/devise/sessions create app/views/devise/sessions/new.html.erb create app/views/devise/unlocks create app/views/devise/unlocks/new.html.erb invoke erb create app/views/devise/mailer create app/views/devise/mailer/confirmation_instructions.html.erb create app/views/devise/mailer/email_changed.html.erb create app/views/devise/mailer/password_change.html.erb create app/views/devise/mailer/reset_password_instructions.html.erb create app/views/devise/mailer/unlock_instructions.html.erb
rails g devise Accountコマンドを実行してdeviseで管理するモデルを作成します。 ※Accountの部分はモデル名なので、任意です。
実行結果
$ docker-compose exec app bundle exec rails g devise Account invoke active_record create db/migrate/20190126030805_devise_create_accounts.rb create app/models/account.rb invoke rspec create spec/models/account_spec.rb invoke factory_bot create spec/factories/accounts.rb insert app/models/account.rb route devise_for :accounts
この時点で、routeにデフォルトのパスが追加されるので、 /accounts/sign_upへアクセスすれば、アカウントを作成できます。
とりあえず、導入部はここまで。
ここからは、簡単なカスタマイズについて触れていきます
Sign up画面にname項目を追加します。 ※migrateファイルでAccountへのカラム追加は事前に行っています。
<h2>Sign up</h2> <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %> <%= devise_error_messages! %> <div class="field"> <%= f.label :name %><br /> <%= f.text_field :name, autofocus: true, autocomplete: "name" %> </div> <div class="field"> <%= f.label :email %><br /> <%= f.email_field :email, autofocus: true, autocomplete: "email" %> </div> <div class="field"> <%= f.label :password %> <% if @minimum_password_length %> <em>(<%= @minimum_password_length %> characters minimum)</em> <% end %><br /> <%= f.password_field :password, autocomplete: "new-password" %> </div> <div class="field"> <%= f.label :password_confirmation %><br /> <%= f.password_field :password_confirmation, autocomplete: "new-password" %> </div> <div class="actions"> <%= f.submit "Sign up" %> </div> <% end %> <%= render "devise/shared/links" %>
application_controller.rbにconfigure_permitted_parametersを追加します。
この記述により、viewの追加パラメータをcontroller側で許可するようにします。
class ApplicationController < ActionController::Base before_action :configure_permitted_parameters, if: :devise_controller? protected def configure_permitted_parameters devise_parameter_sanitizer.permit(:sign_up, keys: [:name]) end end
上記設定で、Sign upにname項目が追加され、登録できるようになりました。
上記の例は、Sign Up画面に対して行った場合ですが、
別途、Accountの管理機能を設けるなどdeviseの画面以外で登録したい場合のことも記載しておきます。
※パスがかぶるため、一部設定をSkipします。 Rails.application.routes.draw do devise_for :accounts, skip: [:registrations] resources :accounts, only: [:index, :new, :create] end
# frozen_string_literal: true class AccountsController < ApplicationController def index @accounts = Account.all end def new @account = Account.new end def create @account = Account.new(account_params) @account.save redirect_to accounts_path end private def account_params params.require(:account).permit(:name, :email, :price, :password, :password_confirmation) end end
h1 New account = form_for @account do |f| .box-body .form-group = f.label :name = f.text_field :name .form-group = f.label :email = f.text_field :email .form-group = f.label :password = f.password_field :password, autocomplete: "new-password" .form-group = f.label :password_confirmation = f.password_field :password_confirmation, autocomplete: "new-password" .actions = f.submit
これで、新規に作成したAccount管理画面から登録もできます。 ※indexに関しては、省略しています。
application_controller.rb にafter_sign_in_path_forを定義します
def after_sign_in_path_for(resource) root_path end
例として、root_pathにリダイレクトするようにしています。
application_controller.rb にafter_sign_out_path_forを定義します
def after_sign_out_path_for(resource) root_path end
例として、root_pathにリダイレクトするようにしています。
deviseはデフォルトでメールアドレスでログインする仕様になっていますが、
それ以外の項目でログインしたい場合は以下のように記載する必要があります。
ここでは、name項目でログインする場合を記載します
def configure_permitted_parameters devise_parameter_sanitizer.permit(:sign_in, keys: [:name]) end
devise :authentication_keys => [ :name ]
この設定で、nameでログインできるようになったので、
view側のログイン項目をemailからnameに変更することで
nameでログインが可能になります。
上記に加えて、メールアドレス、もしくは、名前でログインする場合は、 下記のように記載します。
## find_for_database_authentication(warden_conditions)をオーバライドします。 devise :authentication_keys => [ :login_info ] attr_accessor :login_info def self.find_for_database_authentication(warden_conditions) conditions = warden_conditions.dup if login_info = conditions.delete(:login_info) where(conditions.to_h).where(["lower(name) = :value OR lower(email) = :value", { :value => login_info.downcase }]).first elsif conditions.has_key?(:name) || conditions.has_key?(:email) where(conditions.to_h).first end end
login_infoはviewで入力されるメールアドレス、名前どちらかが入力される項目になります。