Help us understand the problem. What is going on with this article?

[初心者] deviseを使ってログイン機能を実装してみよう

More than 1 year has passed since last update.

はじめに

railsのアプリケーションにログイン機能を実装したい、deviseって言うgemがあるみたいだけど初めてでどうやって使うんだ?という方向けに簡単なアプリケーションを作成しながら解説したいと思います。チュートリアル的に見てもらえると幸いです。

実際にdeviseを使い始めるのは3からなので、そこから見てもらっても大丈夫だと思います。

完成版サンプル

未ログイン時の画面
スクリーンショット 2018-10-27 11.49.03.png
未ログイン時は"現在ログインしていません"と表示されログインと新規登録ができる。

ログイン時の画面
スクリーンショット 2018-10-27 11.50.16.png

ログイン時には新規登録時に登録したユーザー名とメールアドレスが表示されログアウトができる。

※アプリケーションの機能は最低限に絞っています。

環境

Rails 5.1.6
MySQL 5.6.4(使ってる環境に応じて読み替えてください)
devise 4.5.0

基本的に記事投稿時の最新版をそのまま使用しています。

そもそもdeviseとは?

ログイン機能やユーザー登録機能をとても簡単に実装することができるgem。
この記事がめちゃくちゃ詳しい:[Rails] deviseの使い方(rails5版)

では実装していきましょう。

1.アプリケーションの作成

とりあえずアプリケーションを作成しましょう。以下のコマンドを入力してください。

$ rails new login_app -d mysql
$ cd login_app

DBは今回はMySQLを利用しています。環境に合わせて読み替えてください。

2.アプリケーションの雛形作成

ルート、コントローラーの設定をしていきます。以下のコマンドを入力してください。

$ bundle exec rake db:create # アプリのDB作成
$ rails g controller comments index # コントローラーの作成 ついでにアクションとビューも

rails g controller コントローラー名 アクション名 とコマンドを打ち込むことによってコントローラの作成と同時に指定したアクションとルートの設定とビューファイルの作成も行えます。
ただしrootは設定してくれないので手動で設定します。

login_app/config/routes.rb
Rails.application.routes.draw do
  root 'comments#index' # ここを追記します
  get 'comments/index' # 自動で設定されたルーティング
end

ここで rails s でアプリを起動して http://localhost:3000/ に接続してみましょう。上手く設定できていれば以下のような画面になっているはずです。

スクリーンショット 2018-10-27 12.57.13.png

このビューはコントローラの作成時に一緒に作ったビューです。deviseの導入後はこのファイルを編集していきます。

3.deviseの導入

いよいよ本番です。アプリケーションにdeviceを導入しましょう。まずgemfileを編集します。

login_app/gemfile
gem 'devise' # gemfileの一番下に記述

gemfileに記述ができたらbundle installを行いアプリにdeviseをインストールしましょう。
インストールが終わったらrails sをしてサーバーを立て直しましょう。

次はdiviseを利用するのに必要なファイルを作成しましょう。以下のコマンドを入力してください。

$ rails g devise:install # deviseの設定ファイルを作成する

上記のコマンドはdeviseの設定ファイルを作成するdevise専用のコマンドです。ここで作成されたファイルは今回は触らないので気にしなくて大丈夫です。

ファイルを作成できたらログイン機能用のモデル(テーブル)の作成を行います。以下のコマンドを入力してください。

$ rails g devise user #ログイン機能用のモデルを作成
$ rake db:migrate #マイグレート

rails g devise テーブル名はdeviseでログイン機能をつける概念のモデルを作成する際に利用するコマンドです。このコマンドによってログイン機能のために必要なカラムがモデルに追加されるマイグレーションファイルなどが生成されます。

このコマンドを実行すると以下のようなDBが作成されます。

mysql> desc users;
+------------------------+--------------+------+-----+---------+----------------+
| Field                  | Type         | Null | Key | Default | Extra          |
+------------------------+--------------+------+-----+---------+----------------+
| id                     | bigint(20)   | 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    |                |
| created_at             | datetime     | NO   |     | NULL    |                |
| updated_at             | datetime     | NO   |     | NULL    |                |
+------------------------+--------------+------+-----+---------+----------------+

ではビューの実装に取り掛かっていきます。

4.アプリケーションのビューの実装

ユーザー新規要録画面やログイン画面はコマンドでまとめて作成できます。

$ rails g devise:views #ログイン機能に必要なビューファイルをまとめて作成

上記のコマンドを実行すると沢山ビューファイルが作成されますが、重要なのは以下の2つのファイルです。

新規登録画面:app/views/devise/registrations/new.html.erb
ログイン画面:app/views/devise/sessions/new.html.erb

基本的にはこのファイルを編集していけばログイン機能の実装は可能だと思います。
ここでもう一度rails sをしてサーバーを再起動しましょう。

ではトップページのビューを編集してログイン画面に遷移できるようにしましょう。views/comments/index.html.erb ファイルを以下のように編集します。元からある記述は消して大丈夫です。

views/comments/index.html.erb
<h1>ログインアプリ</h1>

<% if user_signed_in? %> <!-- ユーザーがログインしているか調べる -->
  <!-- ユーザーがログインしていた時の処理 -->

  <h4> メールアドレス: <%= current_user.email %> </h4>
  <%= link_to "ログアウト", destroy_user_session_path, method: :delete %> <!-- ログアウトをする -->
<% else %>
  <!-- ユーザーがログインしていなかった時の処理 -->
  <h2> 現在ログインしていません </h2>
  <%= link_to "ログイン", new_user_session_path, class: 'post' %> <!-- ログイン画面に移行する -->
  <%= link_to "新規登録", new_user_registration_path, class: 'post' %> <!-- 新規登録画面に移行する -->
<% end %>

user_signed_in?とはdiviseをアプリに導入すると使えるようになるメソッドで、ユーザーがログインしているかどうか調べることができるメソッドです。ログインしている場合にはtrueを返し、ログインしていない場合にはfalseを返します。
今回の場合はユーザーがログインしていればメールアドレスを表示し、ログアウトのリンクを出します。ログインをしていなければ"現在ログインしていません"と表示し、ログインと新規登録画面のリンクを出します。

current_userは今ログインしているユーザーの情報が入っており、current_user.emailとすると今ログインしているユーザーのメールアドレスが取得できます。current_user.カラム名は良く使うので覚えておくと便利です。

記述ができたら http://localhost:3000/ に接続してみてください。完成版サンプルの未ログイン時の画面と同じ画面になっていると思います。

さて、実際に機能を試してみましょう。とりあえず新規登録を行ってユーザーを新しく作成します。
画面の新規登録をクリックしてEメールとパスワードを入力して実際に登録をしてみましょう。

スクリーンショット 2018-10-29 11.46.53.png

すると以下の画面に切り替わったと思います。

スクリーンショット 2018-10-29 11.32.28.png

先ほど新規登録画面で登録したメールアドレスが表示されています。これでログイン機能の実装が完了しました!一度ログアウトをして今度はログインしてちゃんと登録されているか試してみましょう!

しかし、ログイン機能は完成しましたが名前が登録されていません。
これは上にあるusersテーブルを見ればわかりますが名前に当たるカラムがありません。そもそも新規登録画面で名前を入力するフォーム欄が存在しません。diviseは初期状態ではメールアドレスとパスワードしか登録できないのです(多分拡張性を持たせる為だと思います)。
なので名前を登録できるように機能を追加しましょう。

5.新規登録時に名前を入力できるようにする

必要な作業は4つあります。

・usersテーブルにnameカラムを追加する
・新規登録画面に名前を入力できる欄を追加する
・ストロングパラメータで名前を保存できるようにする
・メインページで登録した名前が表示されるようにする

ではusersテーブルにnameカラムを追加する所からやっていきます。以下のコマンドを入力してください。

$ rails g migration AddNameToUsers name:string # usersテーブルにnameカラムをstring型で追加するマイグレーションファイルを作成
$ rake db:migrate # マイグレート

これでusersテーブルにnameカラムが追加されました。次は新規登録画面を編集して名前を入力できるようにフォーム欄を追加します。
新規登録画面は app/views/devise/registrations/new.html.erb に存在しています。

login_app/app/views/devise/registrations/new.html.erb
<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 :email %><br />
    <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
  </div>

  <!-- ここから追加してください -->
  <div class="field">
    <%= f.label :name %> <br />
    <%= f.text_field :name %>
  </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" %>

編集が終わったら新規登録画面に行ってみましょう。以下のように名前を入力する欄が追加されているはずです。

スクリーンショット 2018-10-29 13.52.08.png

さてこれで名前が入力できるようになったのですが実はこのままでは名前はDBに保存されません。何故ならdeviseでは初期状態で新規登録時にメールアドレスとパスワードのみを受け取るようにストロングパラメーターが設定してあるからです。
なのでdeviseのストロングパラメーターを編集して名前も受け取るようにしなければいけないのですが、deviseのストロングパラメーターはdeviseのgem内に記述されているので直接編集することができません。
じゃあどうするのかと言うとdeviseが提供しているconfigure_permitted_parametersメソッドを利用することになります。
このメソッドはdeviseのストロングパラメーターを追加できるメソッドで、application_controllerに記述をします。以下のように編集を行ってください。

login_app/app/controllers/application_controller
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  # ここから追加します
  before_action :configure_permitted_parameters, if: :devise_controller?

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:name]) # 新規登録時(sign_up時)にnameというキーのパラメーターを追加で許可する
  end
  # ここまで追加します
end

これで新規登録時に名前が登録できるようになりました。最後にトップページを編集して登録した名前を表示されるようにしましょう。

views/comments/index.html.erb
<h1>ログインアプリ</h1>

<% if user_signed_in? %> <!-- ユーザーがログインしているか調べる -->
  <!-- ユーザーがログインしていた時の処理 -->
  <h2> 現在 <%= current_user.name %> さんがログインしています </h2> <!-- ここを追加します -->
  <h4> メールアドレス: <%= current_user.email %> </h4>
  <%= link_to "ログアウト", destroy_user_session_path, method: :delete %> <!-- ログアウトをする -->
<% else %>
  <!-- ユーザーがログインしていなかった時の処理 -->
  <h2> 現在ログインしていません </h2>
  <%= link_to "ログイン", new_user_session_path, class: 'post' %> <!-- ログイン画面に移行する -->
  <%= link_to "新規登録", new_user_registration_path, class: 'post' %> <!-- 新規登録画面に移行する -->
<% end %>

名前の表示を行うのはcurrent_user.nameです。今ログインしているユーザー(current_user)の名前(name)をDBから取得しています。

これで実装完了です!お疲れ様でした!

まとめ

以下のメソッドは良く使うので覚えておきましょう。

user_signed_in?:ユーザーがログインしているか調べる。ログインしているかどうかでビューを変えたい時などに利用する。
current_user.カラム名:現在ログインしているユーザーのデータをDBから取ってくる。
configure_permitted_parameters:ストロングパラメーターの許可を追加する。

またメソッド以外では以下のことを覚えておくと便利だと思います。

rails g devise:views:ログイン機能に必要なビューファイルをまとめて作成するコマンド
新規登録画面:app/views/devise/registrations/new.html.erb
ログイン画面:app/views/devise/sessions/new.html.erb

<%= link_to "ログイン", new_user_session_path %>
ログイン画面に移行するリンク。urlだと/users/sign_inとなる。

<%= link_to "新規登録", new_user_registration_path %>
新規登録画面に移行するリンク。urlだと/users/sign_upとなる。

<%= link_to "ログアウト", destroy_user_session_path, method: :delete %>
ログアウトするリンク。urlだと/users/sign_outとなる。

エラーが出たら

再起動をすれば治る可能性があります。rails s を試してみてください。

終わりに

以上が基本的なdeviseの使い方でした。良かったら参考にしてみてください。また、これはdeviseの基本的な機能なので色々調べてみると面白いと思います。

Orangina1050
にわかプログラマ。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした