Ruby on Railsのgem「devise」でログイン機能を実装する方法

よこのじ(@yokonoji_work)です。

Ruby on Railsのgem「devise」でログイン機能を実装する方法を紹介します。

gem「devise」の導入は「Ruby on Railsでログイン機能を実装するためのgem「devise」を導入する【Bootstrap化と日本語化 含む】」にて済んでいるものとして、説明していきます。

ログインユーザーのみアクセスできるようにアクセス制限を設定

application_controller.rb に before_action :authenticate_user! を追加することで、ログイン済みのユーザーのみにアクセスを許可することができます。

また、サインアップとアカウント情報更新の際に操作できるパラーメータとして、追加登録したnameを設定しています。なお、デフォルトでpasswordとpassword_confirmationは許可されています(:account_updateの場合はcurrent_passwordも許可される)。

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  before_action :authenticate_user!
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
    devise_parameter_sanitizer.permit(:account_update, keys: [:name])
  end
end

この辺りの処理については、次のQiita記事も参考になります。

viewファイルの編集

アカウント登録(サインアップ)の画面に名前(name)を入力できるようにするために、/app/views/devise/registrations/new.html.erb を次のように変更します。

<%= bootstrap_devise_error_messages! %>
<div class="panel panel-default devise-bs">
  <div class="panel-heading">
    <h1><%= t('.sign_up', :default => "Sign up") %></h1>
  </div>
  <div class="panel-body">
    <%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), html: { role: "form" }) do |f| %>
      <div class="form-group">
        <%= f.label :name %>
        <%= f.text_field :name, autofocus: true, class: "form-control" %>
      </div>
      <div class="form-group">
        <%= f.label :email %>
        <%= f.email_field :email, class: "form-control" %>
      </div>
      <div class="form-group">
        <%= f.label :password %>
        <%= f.password_field :password, class: "form-control" %>
      </div>
      <div class="form-group">
        <%= f.label :password_confirmation %>
        <%= f.password_field :password_confirmation, class: "form-control" %>
      </div>
      <%= f.submit t('.sign_up', :default => "Sign up"), class: "btn btn-primary" %>
    <% end %>
  </div>
</div>
<%= render "devise/shared/links" %>

rails s を実行してアプリケーションを表示させると、/users/sign_in というページに飛んでBootstrapデザインのログイン画面になっていることが確認できるかと思います。

deviseのログイン画面 Bootstrapあり

ちなみに、Bootstrapデザインが当たっていない場合のログイン画面はこのようなものになっています。

deviseのログイン画面

また、アカウント情報の変更画面でも同じように名前(name)を入力できるように、/app/views/devise/registrations/edit.html.erb を次のように変更します。

<%= bootstrap_devise_error_messages! %>
<div class="panel panel-default devise-bs">
  <div class="panel-heading">
    <h1><%= t('.title', :resource => resource_class.model_name.human , :default => "Edit #{resource_name.to_s.humanize}") %></h1>
  </div>
  <div class="panel-body">
    <%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %>
      <div class="form-group">
        <%= f.label :name %>
        <%= f.text_field :name, autofocus: true, class: "form-control" %>
      </div>
      <div class="form-group">
        <%= f.label :email %>
        <%= f.email_field :email, class: "form-control" %>
      </div>
      <div class="form-group">
        <%= f.label :password %> <i>(<%= t('.leave_blank_if_you_don_t_want_to_change_it', :default => "leave blank if you don't want to change it") %>)</i>
        <%= f.password_field :password, :autocomplete => "off", class: "form-control" %>
      </div>
      <div class="form-group">
        <%= f.label :password_confirmation %>
        <%= f.password_field :password_confirmation, class: "form-control"  %>
      </div>
      <div class="form-group">
        <%= f.label :current_password %> <i>(<%= t('.we_need_your_current_password_to_confirm_your_changes', :default => 'we need your current password to confirm your changes') %>)</i>
        <%= f.password_field :current_password, class: "form-control" %>
      </div>
      <%= f.submit t('.update', :default => "Update"), class: "btn btn-primary" %>
    <% end %>
  </div>
</div>

<p><%= t('.unhappy', :default => 'Unhappy') %>? <%= link_to t('.cancel_my_account', :default => "Cancel my account"), registration_path(resource_name), :data => { :confirm => t('.are_you_sure', :default => "Are you sure?") }, :method => :delete %>.</p>

<%= link_to t('.back', :default => 'Back'), :back %>

これで、アカウントの名前を登録、変更することが可能になりました。

ログイン後、ログアウト後の遷移先ページ

ログインした後、デフォルトではルートページに飛んでいきますが、任意のページに変更することも可能です。また、ログアウトした後の遷移ページについても指定が可能です。

# ログイン後の遷移先
def after_sign_in_path_for(resource)
  home_account_path
end
# ログアウト後の遷移先
def after_sign_out_path_for(resource)
  new_user_session_path
end

ただし、ログアウト後の遷移先については、先ほどの before_action :authenticate_user! を設定していればアクセス制限がかかりログインページに飛ぶので、柔軟にログアウト後のページを指定したい場合には before_action :authenticate_user! を使わない方法が良さそうです。

ログイン状態の判定を行って処理を変える

deviseでは、user_signed_in? によりログインしているかどうかの状態を得ることができます。

ログイン中であれば true となりますので、次のようにログイン中にはログアウトするためのリンクを表示させるなどの利用が可能です。

<% if user_signed_in? %>
  <p><%= link_to "ログアウト", destroy_user_session_path, method: :delete %></p>
<% end %>

他にも使えるものはあります。

次のようにすると、ログイン中には、アカウント名のリンクからアカウントページに飛ばしたり、アカウント情報変更ページに飛ばしたり、ログアウトさせたりすることができます。

また、ログイン中でなければ、ログイン画面に飛ばしたり、新規登録画面に飛ばすことができます。

<% if user_signed_in? %>
  <%= link_to current_user.name, home_account_path %>
  <%= 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 %>

current_user.name でログイン中アカウントの名前(name)を取得して、home_account_path でhomeコントローラーの account アクションのパスを設定しています。

 

これで、ログインに関するの一通りの機能が実装できているかと思います。gem「devise」を使えば簡単に実装できるので、ぜひ使用を検討してみてください。