3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Ruby on Rails】初学者向け-開発の流れについて⑦ ユーザー認証機能追加編

Last updated at Posted at 2024-10-31

Rails開発の流れについて

・Railsプロジェクトの作成とDockerの設定
【Ruby on Rails】初学者向け-開発の流れについて① プロジェクトの作成編

・Gem・DB設定とルーティング
【Ruby on Rails】初学者向け-開発の流れについて② Gem・DB設定とルーティング編

・Bootstrapの導入
【Ruby on Rails】初学者向け-開発の流れについて③ Bootstrapの導入編

・一覧、新規作成、参照、更新、削除画面機能の追加vol.1
【Ruby on Rails】初学者向け-開発の流れについて④ 一覧、新規作成、参照、更新、削除画面機能の追加vol.1

・一覧、新規作成、参照、更新、削除画面機能の追加vol.2
【Ruby on Rails】初学者向け-開発の流れについて④ 一覧、新規作成、参照、更新、削除画面機能の追加vol.2

・検索機能の追加
【Ruby on Rails】初学者向け-開発の流れについて⑤ 検索機能の追加

・DBやモデル周りの整備 & バリデーション機能追加
【Ruby on Rails】初学者向け-開発の流れについて⑥ DBやモデル周りの整備 & バリデーション機能追加

・ユーザー認証機能追加(今回学習するのはこちら)**

(※ 他追加機能があれば随時記事にしていく予定です)


前提
・Docker
・Ruby on Rails 7
・Mysql
・BootStrap
・VSCode


前回のおさらい
…前回はモデルでバリデーションを設定し、ja.ymlの設定や
 エラーメッセージ用のパーシャル作成、といったエラーチェックの処理を追加しました。

ユーザー認証機能追加について

今回はユーザ認証機能についてまとめていきます。
流れとしては以下です。

・パスワードハッシュ化のためのGemをインストール
・Userテーブルの作成
・ユーザー登録画面とログイン画面の作成
・ログインユーザーによって変化する機能の作成

ハッシュ化のためのGemをインストール

まず初めにユーザー認証機能において大事なのがパスワードのハッシュ化です。
ハッシュ化することで容易にパスワードを解読されないようにします。

このパスワードをハッシュ化して登録するために必要なのがbcryptというGemです。

bcrypt
…パスワードを安全に保存するためのハッシュ関数です。

まずGemfileを開き、bcryptのGemを追記します。

Gemfile
gem "bcrypt", "~> 3.1.7"

次にターミナルでdocker compose buildを実行しGemをインストールします

terminal
docker-compose build

これでパスワードをハッシュ化して保存するための準備ができました。


Userテーブルの作成

次に、ユーザーテーブルの作成を行います。
ターミナルで下記コマンドを実行し、migrationファイルとモデルを作成します。

terminal
docker-compose run web rails generate model User name:string password:string

作成されたmigrationファイルを編集します。

db\migrate\20241030071156_create_users.rb
class CreateUsers < ActiveRecord::Migration[7.0]
  def change
    create_table :users do |t|
      t.string :name, null:false
      t.string :password, null:false

      t.timestamps
    end
    add_index :users, :name, unique: true
  end
end

null: false
…このように記載することで、DBに対してnullを許さない(必ず何かしらの値が入る)ようにする制約をかけることができる。

add_index :users, :name, unique: true
…このように記載することで、DBに対してnameカラムの値が一意であるよう制約をかけることができる。

migrationファイルが編集できたら下記コマンドを実行してmigrateします。

terminal
docker-compose exec web rails db:migrate

ユーザー登録画面とログイン画面の作成

Userテーブルが作成できたら次にルーティングの確認を行います。
現在のconfig/routes.rbは以下のようになっています。

config/routes.rb
Rails.application.routes.draw do
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html

  # Defines the root path route ("/")
  root "tasks#index"
  get 'tasks', to: 'tasks#index'
  get 'tasks/new', to: 'tasks#new'
  post 'tasks', to: 'tasks#create'
  get 'tasks/:id', to: 'tasks#show', as: 'task'
  get 'tasks/:id/edit', to: 'tasks#edit', as: 'edit_task'
  patch 'tasks/:id', to: 'tasks#update'
  delete 'tasks/:id', to: 'tasks#destroy'
end

ここまでのところで全てのルーティングを1行ずつ足しこんでいきましたが、
実はこれは以下のように簡略化して記載することが可能です。

config/routes.rb
Rails.application.routes.draw do
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html

  # Defines the root path route ("/")
  root "tasks#index"

  resources :tasks
end

resources :tasks
…このように記述することによってtaskリソースに対する
 標準的なメソッド(追加・更新・削除等)をひとくくりに記載することができます。

(※もし画面遷移でエラーが発生したらhttp://localhost:3000/rails/info/routesで
  新しく設定されたルーティングを確認しながら修正を行ってください。)

今回はユーザーの登録機能追加やログイン機能追加にあたってルーティングを追加する必要があるため、
以下のように記載します。
ログイン画面をルートとするため、今までルートとしていたtaskのindexに遷移する処理に関しては修正が必要となります。

config/routes.rb
Rails.application.routes.draw do
  post 'login', to: 'sessions#create'
  delete 'logout', to: 'sessions#destroy'
  
  root 'home#index'
  resources :users, only: %i[new create]
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html

  # Defines the root path route ("/")

  resources :tasks
  resources :users
end

次にユーザー情報の登録を行うため、コマンドを実行します。
以前は直接VSCodeをかまってファイルを作成していましたが
今回は以下のようにコマンドで必要なファイルの作成を行います。

terminal
docker-compose exec web rails generate controller Users create new

docker-compose exec web rails generate controller <コントローラ名> <アクション名>...
…コントローラーのファイルを作成するコマンドです。後続にアクション名をつけると、
コントローラ内のアクションや必要なファイルが作成されます。

image.png

次にタスク一覧画面から、ユーザー登録画面に遷移できるように
app\views\tasks\index.html.erbに下記を追記します。

app\views\tasks\index.html.erb
<!--~~~~~~~~~~~~~省略~~~~~~~~~~~~~-->
<div class="d-flex align-items-center">
  <h1>タスク一覧</h1>
  <div class="ms-auto">
    <%= link_to '新規作成', new_task_path, class: 'btn btn-outline-dark'%>
    <!--下記を追記-->
    <%= link_to 'ユーザー登録', users_new_path, class: 'btn btn-outline-dark'%>
  </div>
</div>
<!--#~~~~~~~~~~~~~省略~~~~~~~~~~~~~-->

ユーザー登録画面に遷移できるようになったら、
ユーザー登録画面の内容をapp\views\users\new.html.erbに記載していきます。
また、パーシャルとしてapp\views\users_form.html.erbを作成し、フォームを作成します。

app\views\users\new.html.erb
<h1>ユーザー登録</h1>
<%= render partial: 'form', locals: {user: @user} %>
app\views\users_form.html.erb
<%= form_with model: @user, local: true, data: { turbo: false } do |f| %>
  <div class="form-group">
    <%= f.label :name, 'ユーザー名' %>
    <%= f.text_field :name, 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, 'パスワード確認)' %>
    <%= f.password_field :password, class: 'form-control' %>
  </div>

  <%= f.submit '作成', class: 'btn btn-primary' %>
<% end %>

f.password_field
…パスワード入力直後に、黒丸で文字を隠すことができる。

image.png
ユーザー登録画面はこのようになります。

次にログインページの作成を行います。まず、ログイン画面を表示するための
homeディレクトリのindexから作成し、パーシャルである_login_form.html.erbをレンダリングしてくるように記載します。

app\views\home\index.html.erb
<%= render partial: 'users/login_form'%>
app\views\users_login_form.html.erb
<h1>ログイン</h1>

<%= form_with(scope: :session, url: login_path) do |f| %>
  <div class="form-group">
    <%= f.label :name, 'ユーザー名' %>
    <%= f.text_field :name, class: 'form-control' %>
  </div>
  <div class="form-group">
    <%= f.label :password, 'パスワード' %>
    <%= f.password_field :password, class: 'form-control' %>
  </div>
  <%= f.submit 'ログイン', class: 'btn btn-primary' %>
<% end %>

画面からユーザーの登録が行えるようにapp\controllers\users_controller.rbの各アクションに処理を記載していきます。

app\controllers\users_controller.rb
class UsersController < ApplicationController
  def new
    @user = User.new(flash[:user])
  end

  def create
    @user = User.new(user_params)
    if @user.save
      session[:user_id] = @user.id
      render :show
    else
      flash.now[:error_messages] = @user.errors.full_messages
      render :new, status: :unprocessable_entity
    end
  end

  def show

  end

  private
  def user_params
    params.require(:user).permit(:name, :password, :password)
  end
end

ユーザー登録後の画面としてapp\views\users\show.html.erbを作成します。

app\views\users\show.html.erb
<div class="d-flex align-items-center">
    <h1>ユーザーの登録が完了しました</h1>
    <div class="ms-auto boards__linkBox">
            <%= link_to '一覧', root_path, class: 'btn btn-outline-dark'%>
    </div>
</div>

ここまででユーザーの登録が行えます。

次にログインするための処理を作成します。

app\controllers\users_controller.rb
class SessionsController < ApplicationController
    def create
        user = User.find_by(name: params[:session][:name])
        if user 
            session[:user_id] = user.id
            # 一覧画面へ遷移
            redirect_to tasks_path
        else
            render 'home/index'
        end
    end

  # ログアウト時の処理
    def destroy
      session.delete(:user_id)
      redirect_to root_path
    end
  end
  

最後にログイン画面を表示するためのコントローラーのファイルを作成し、
処理を記載します。ここでは特にindexアクション内に処理を記載しなくてもよいです。

app\controllers\home_controller.rb
class HomeController < ApplicationController
    def index
    end
end

これにてログイン画面が表示され、登録したユーザーでのみログインすることが可能となります。
image.png

image.png

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?