いわりょのBlog

IT関連で学んだことを書いていきます。

rails 基本的なログインシステム Part1

作ったもの

HPを作成したのですが、管理人だけがページを閲覧しながら記事などの投稿や編集、削除を行えるようにしたかったので、動画のようにログイン後に同じnewsのページに移動すると投稿機能が使えるようになっています。

この記事では「ログイン機能」の実装について書いていきます。

条件

rails 5.1.7
ruby 2.6.3
bcrypt 3.1.12

すること

  1. 管理人をユーザーモデルで作成
  2. ログインのcontroller作成やルーティング設定
  3. ログインのビュー作成
  4. ログイン機能作成
  5. ちょっと発展機能を加える
  6. ログイン機能を実装したことによって利用できること

長くなりそうなのでこの記事では3番目のログインのビュー作成までを書いていこうと思います。

1.管理人をユーザーモデルで作成

f:id:Ryo10Leo:20200105145932p:plain

Userモデルの中身はこんな感じ

パスワードは暗号化して、メッセージダイジェストで保存したいのでgemの「bcrypt」を使います。

gem 'bcrypt'
bundle install


作っていきます。

rails generate model User name:string email:string password_digest:string

マイグレーションファイルはこんな感じ。

20191221045711_create_users.rb

class CreateUsers < ActiveRecord::Migration[5.1]
  def change
    create_table :users do |t|
      t.string :name
      t.string :email
      t.string :password_digest
      
      t.timestamps
    end
  end
end
rails db:migrate

パスワードをダイジェストで保存するにはユーザーのモデルファイルに下記のようにhas_secure_passwordを追記

app/models/user.rb

class User < ApplicationRecord
  has_secure_password
end

これでpassword_digestカラムに暗号化されたパスワードが保存されます。
Userを作成する際は下記のように:passwordと:password_confirmationの二つを入力しなくてはならない。

User.new(name : 'aaa', email: 'aaa.example.com', password: 'aaa', password_confirmation: 'aaa')

今回作成したHPではユーザーは管理者一人のみなので、サインアップページなどを作成してユーザーを増やすことはありません。
なので管理者のユーザー一つをseeds.rbで作っておきます。

seeds.rb

User.create(name: "Ryo", email: "ryo@example.com",
            password: "password", password_confirmation: "password")
rails db:seed

細かい設定は後にして、とりあえず管理者ユーザーは完成しました!

ログインのcontroller作成やルーティング設定

ログイン画面表示はnewアクション
ログイン処理はcreteアクション
ログアウト処理はdestroyアクション
をそれぞれ使います。

早速コントローラー作成

rails generate controller sessions new create destroy

ファイルはこんな感じ

class SessionsController < ApplicationController
  def new
  end

  def create
  end

  def destroy
  end
end

続いてルーティングの設定

routes.rb

Rails.application.routes.draw do

  get      '/login',  to: 'sessions#new'
  post     '/login',  to: 'sessions#create'
  delete   '/logout', to: 'sessions#destroy'

end

このような記述で、/loginや/logoutでアクションが呼び出せますし、login_path,logout_pathメソッドも使えるようになりました。

3.ログインのビュー作成

newアクションを呼び出した時のビューをnew.html.erbに書いていきます。

app/views/sessons/new.html.erb

  <div id="form">
    <h1>Login</h1>
  
    <%= form_for(:session, url: login_path) do |f| %>

      <div class="form-item">
      <p class="formLabel">Email</p>
      <%= f.email_field :email, class: 'form-style form-control',autocomplete: 'off' %>
      </div>

      <div class="form-item">
      <p class="formLabel">Password</p>
      <%= f.password_field :password, class: 'form-style form-control' %>
      </div>

      <%= f.submit "Log in", class: "login pull-right" %>
    <% end %>
  </div>

form_for(:session, url: login_path)と書くことで送信ボタンを押した時に、sessionsコントローラーのcreateアクションでparams[:session][:email]email、params[:session][:password]を使って、ログインフォームで入力されたメールアドレスとパスワードを取得できます。
どう利用するかは後編で書きます。

CSSデザインはお好みで
僕の場合こちらを参考にしました。↓↓
https://codepen.io/Timurtek/pen/LblHd/


アラートも表示させたいのでそのためのパーシャルも用意しておきます。

app/views/sessions/_alert.html.erb

    <% if flash[:danger] %>
      <% flash.each do |message_type, message| %>
      <div class="alert alert-<%= message_type %>">
        <%= message %>
      </div>
    <% end %>
    <% else %>
      <p class="form-msg">こちらは管理人専用ページです。</p>
     <% end %>

追加します。

app/views/sessions/new.html.erb

  <div id="form">
    <h1>Login</h1>
  
<%= render 'sessions/alert' %>

   (中略)

  </div>

ログイン失敗にアラートが表示された状態でログイン画面に戻るように設定。

class SessionsController < ApplicationController
  def new
  end

  def create
    if 入力された情報のユーザーが存在するか?
        #ログイン処理を書きます
    else
      flash.now[:danger] = '有効なメールアドレス、またはパスワードではありません。'
      render 'new'
    end
  end

  def destroy
  end
end

これでログイン失敗時の動きが完成しました。

具体的なログイン機能は次回。

ryo10leo.hatenablog.com