PR/BLOG

広報・ブログ

Ruby on Rails でログイン画面を作る

畝地さん

技術開発推進部の畝地(あぜち)です。
少しずつ暖かくなってきましたね。二輪はまだ我慢・・・

前回の続きです。
構築した環境でログイン画面とユーザー一覧画面を作成していきます。

bcrypt 導入

今回のログイン画面ではメールアドレスとパスワードを入力します。

パスワードは暗号化して保存するのが今となっては当たり前なので、Railsのパスワード暗号化で一般的に使われる bcrypt を導入します。

Gemfile編集

フォルダ内の Gemfile を開き、以下の2行を追加します。

# 暗号化
gem 'bcrypt'
ビルド実行、サービス起動

フォルダ内で以下を実行します。

$ docker-compose build

ビルドが終わったらサービスを起動します。

$ docker-compose up

 

scaffold でユーザー画面を作成

scaffoldとは

Ruby on Rails にはMVCとCRUDのひな型を作成してくれる「scaffold」という機能があります。

  • MVC・・・モデル/ビュー/コントローラ
  • CRUD・・・生成(Create)/読み取り(Read)/更新(Update)/削除(Delete)

scaffold はマスタ管理画面を作ってくれる機能。と表現するとわかりやすいでしょうか。

コンテナの確認

前述のとおり scaffold は Rails の機能なので、実行するためには Rails が動いているコンテナに入る必要があります。

コマンドプロンプトをもうひとつ開き、フォルダ内で以下を実行します。

$ docker-compose ps

以下のように表示されるので、「web_1」と付いている方の「Name」をメモします。

     Name                   Command                State   Ports
--------------------------------------------------------------------------------------------
railstest_db_1    docker-entrypoint.sh mysqld      Up      0.0.0.0:3316->3306/tcp, 33060/tcp
railstest_web_1   bundle exec rails s -p 300 ...   Up      0.0.0.0:3000->3000/tcp
コンテナに入る

フォルダ内で以下を実行します。

$ docker exec -it [メモしたweb_1] /bin/bash

以下のように表示されるはずです。
(「487085381b8f」部分は環境により可変)

root@487085381b8f:/myapp#
scaffold

コンテナに入れたので、scaffold してみましょう。
以下を実行します。

rails g scaffold User name:string email:string password_digest:string

上記をざっくり説明すると

  • User という画面を作る。
  • User で扱うデータは name(string型)、email(string型)、password_digest(string型)の3つ。

という事になります。

データはそのままでは使えない(テーブルは作成されていない)ので、コンテナ内で以下を実行します。

rails db:migrate
画面確認

画面が表示されるか確認してみましょう。
ブラウザで http://localhost:3000/users にアクセスすると、以下のような画面が表示されるはずです。

表示が確認できたら次へ進みます。
(データ追加等は少しお待ちください)

 

セッション管理

ログイン機能を使う場合「ログインしているのは誰か?」を判断する必要があるので、セッション用ヘルパーモジュールを利用してこれを実装します。

コントローラー作成

コンテナ内で以下を実行します。
(モデルとビューは必要ないので、コントローラーのみを作成)

rails g controller Sessions new

実行すると、フォルダ内に app\controllers\sessions_controller.rb が作成されます。
sessions_controller.rb には new アクションのみなので、ログイン(create)とログアウト(destroy)のアクションを追加します。

class SessionsController < ApplicationController
  def new
  end

  def create
    user = User.find_by(email: params[:session][:email].downcase)
    if user && user.authenticate(params[:session][:password])
      log_in user
      redirect_to root_url
    else
      render 'new'
    end
  end

  def destroy
    log_out if logged_in?
    redirect_to root_url
  end
end
  • create・・・ログイン処理
  • destroy・・・ログアウト処理

フォルダ内の config\routes.rb を開き、以下のように編集します。
(赤:削除、黄色:追加)

Rails.application.routes.draw do
  root 'users#index'
  get 'sessions/new'
  get    '/login',  to: 'sessions#new'
  post   '/login',  to: 'sessions#create'
  delete '/logout', to: 'sessions#destroy'
(以下略)
ログイン画面作成

フォルダ内の app\views\sessions\new.html.erb を開き、以下のように編集します。
(元々ある2行は削除してください)

<h1>ログイン</h1>
<%= form_for(:session, url: login_path) do |f| %>
  <%= f.label :email %>
  <%= f.email_field :email %>
  <%= f.label :password %>
  <%= f.password_field :password %>
  <%= f.submit "Log in" %>
<% end %>
ログイン状況に応じて表示切り分け

ログインしている場合はユーザー一覧とログアウトボタンを表示、
ログインしていない場合はログイン画面へのリンクを表示するようにします。

フォルダ内の app\views\users\index.html.erb_logged_in.html.erb にリネームします。
リネームした app\views\users\_logged_in.html.erb を開き、最後に以下を追加します。

<%= link_to "ログアウト", logout_path, method: :delete %>

次にフォルダ内の app\views\users に index.html.erb を作成し、以下のように編集します。

<% if logged_in? %>
  <%= render 'users/logged_in' %>
<% else %>
  <%= render 'users/not_logged_in' %>
<% end %>

同様にフォルダ内の app\views\users に _not_logged_in.html.erb を作成し、以下のように編集します。

<p>Railsサンプルアプリです。ログインしていません。</p>
<%= link_to "ログイン", login_path%>
セッション用ヘルパー作成

フォルダ内の app\helpers\sessions_helper.rb を開き、以下のように編集します。

module SessionsHelper
  # 渡されたユーザーでログインする
  def log_in(user)
    session[:user_id] = user.id
  end

  # 現在ログイン中のユーザーを返す(いる場合)
  def current_user
    if session[:user_id]
      # find だとユーザーがログインしていない場合に例外が発生するので find_by で検索
      @current_user ||= User.find_by(id: session[:user_id])
    end
  end

  #受け取ったユーザーがログイン中のユーザーと一致すれば true を返す
  def current_user?(user)
    user == current_user
  end

  # ユーザーがログインしていれば true、その他なら false を返す
  def logged_in?
    !current_user.nil?
  end

  # 現在のユーザーをログアウトする
  def log_out
    session.delete(:user_id)
    @current_user = nil
  end
end
セッション用ヘルパーの読み込み

セッション用ヘルパーを全てのページで使えるように ApplicationController で読み込みます。また、ログイン済みかの確認も行います。
フォルダ内の app\controllers\application_controller.rb を開き、以下のように編集します。

class ApplicationController < ActionController::Base
  include SessionsHelper

  private
  # ログイン済みユーザーかどうか確認
  def logged_in_user
    unless logged_in?
      redirect_to login_url
    end
  end
end
アクション前チェック

アクション前にログインされているかのチェックを行い、不正な処理が行われないようにします。
フォルダ内の app\controllers\users_controller.rb を開き、以下のように編集します。

class UsersController < ApplicationController
  before_action :logged_in_user, only:[:edit, :update, :destroy]
(以下略)

 

パスワード暗号化対応

最後に暗号化したパスワードを扱えるようにしたり、パスワードを暗号化して保存するように実装します。

フォルダ内の app\models\user.rb を開き、以下のように編集します。

class User < ApplicationRecord
  has_secure_password
end

フォルダ内の app\controllers\users_controller.rb を開き、以下のように編集します。
(黄色:変更)

class UsersController < ApplicationController
(中略)
  # Only allow a list of trusted parameters through.
  def user_params
    #params.require(:user).permit(:name, :email, :password_digest)
    params.require(:user).permit(:name, :email, :password, :password)
  end
end

フォルダ内の app\views\users\_form.html.erb を開き、以下のように編集します。
(黄色:変更)

<%= form_with(model: user, local: true) do |form| %>
(中略)
  <div class="field">
    <%= form.label :password %>
    <%= form.text_field :password %>
  </div>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

 

確認

それでは確認してみましょう。
まず、docker-compose up を行ったコマンドプロンプトで Ctrl + C を行い一度停止、
再度 docker-compose up を行って起動します。

起動したらブラウザで http://localhost:3000/users にアクセスしてみましょう。
以下のような画面が表示されるはずです。

「ログイン」をクリックしてみましょう。
ログイン画面が表示されるはずです。

ですが、ログインしようにもユーザーを登録していません。
最初のユーザーは手動で登録してみましょう。

ユーザー手動登録

scaffold を行った時の手順を参考に、コンテナに入り、以下を実行します。

rails c

プロンプトが「irb(main):001:0>」に変わったのを確認したら、以下を実行します。

User.create(name: "admin", email: "admin@test.com", password: "hogehoge", password_confirmation: "hogehoge")

登録できたら「exit」で抜けます。

再度ブラウザで http://localhost:3000/users にアクセスし、
Emailに「admin@test.com」、Passwordに「hogehoge」を入力し「Log in」してみましょう。
以下のように表示されるはずです。

・Password digest は暗号化されたパスワードです。

あとは好きにユーザーを作ったり消したりしてみてください。

終わりに

次回(最終回)は Bootstrap と Font Awesome を使って画面を装飾していきます。

 

  • 当ページの人物画像はNIGAOE MAKERで作成しました。
一覧に戻る
ゆりちゃん

技術開発推進部ゆりちゃんからのお願い顔マークを押して、技術ブログの
感想をお聞かせください^^