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を追記します。
gem "bcrypt", "~> 3.1.7"
次にターミナルでdocker compose buildを実行しGemをインストールします
docker-compose build
これでパスワードをハッシュ化して保存するための準備ができました。
Userテーブルの作成
次に、ユーザーテーブルの作成を行います。
ターミナルで下記コマンドを実行し、migrationファイルとモデルを作成します。
docker-compose run web rails generate model User name:string password:string
作成されたmigrationファイルを編集します。
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します。
docker-compose exec web rails db:migrate
ユーザー登録画面とログイン画面の作成
Userテーブルが作成できたら次にルーティングの確認を行います。
現在の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行ずつ足しこんでいきましたが、
実はこれは以下のように簡略化して記載することが可能です。
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に遷移する処理に関しては修正が必要となります。
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をかまってファイルを作成していましたが
今回は以下のようにコマンドで必要なファイルの作成を行います。
docker-compose exec web rails generate controller Users create new
docker-compose exec web rails generate controller <コントローラ名> <アクション名>...
…コントローラーのファイルを作成するコマンドです。後続にアクション名をつけると、
コントローラ内のアクションや必要なファイルが作成されます。
次にタスク一覧画面から、ユーザー登録画面に遷移できるように
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を作成し、フォームを作成します。
<h1>ユーザー登録</h1>
<%= render partial: 'form', locals: {user: @user} %>
<%= 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
…パスワード入力直後に、黒丸で文字を隠すことができる。
次にログインページの作成を行います。まず、ログイン画面を表示するための
homeディレクトリのindexから作成し、パーシャルである_login_form.html.erbをレンダリングしてくるように記載します。
<%= render partial: 'users/login_form'%>
<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の各アクションに処理を記載していきます。
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を作成します。
<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>
ここまででユーザーの登録が行えます。
次にログインするための処理を作成します。
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アクション内に処理を記載しなくてもよいです。
class HomeController < ApplicationController
def index
end
end