【Ruby on Rails】簡単なメモアプリの作成|ユーザー認証と併せてユーザー機能を実装

作成日: 更新日:

開発環境

  • Ruby:version 3.1.2
  • Ruby on Rails:version 7.0.4
  • Visual Studio Code:version 1.73.0
  • OS:Windows10

Ruby on Railsでユーザー機能の実装手順

Ruby on Railsではユーザー認証と併せてユーザー機能を実装することにより、ユーザーフレンドリーなWebサービスを提供しやすくなります。 今回はメモアプリの作成で使用したgemのdeviseなしで自作したログイン機能を用いた「ユーザー機能」のコードを用いて解説していきます。

ユーザー機能のユーザーモデルの作成

まずはログイン機能で使用するユーザーモデルを作成します。

1rails g model User

次にユーザーモデルのマイグレーションファイルに必要な「名前、メールアドレス、パスワード」のカラムを追加していきます。

1# memo_app\db\migrate\20230108041355_create_users.rb
2class CreateUsers < ActiveRecord::Migration[7.0]
3  def change
4    create_table :users do |t|
5+       t.string :name
6+       t.string :email
7+       t.string :password
8      t.timestamps
9    end
10  end
11end

上記の記述が完了したら、以下のコマンドを叩いてマイグレーションファイルを反映させます。

1rails db:migrate

ユーザーモデルのカラムにそれぞれバリデーションを設定していきます。

1# memo_app\app\models\user.rb
2class User < ApplicationRecord
3+     validates :name, presence: true, length: {minimum:2, maximum:32}
4+     validates :email, presence: true, uniqueness: true
5+     validates :password, presence: true, format: {with: /^[0-9a-zA-Z]+$/, multiline: true}
6end

今回は簡易的になりますが、パスワードのカラムに正規表現を使用して半角英数字(英字は大文字も許可)にしています。

ユーザー機能のルーティングの作成

次にユーザー機能のルーティングを作成していきます。

1# memo_app/config/routes.rb
2
3Rails.application.routes.draw do
4  root :to => 'memos#index'
5+ resource :users, only: [:new, :show, :edit, :create, :update]
6  get 'login', to: 'sessions#new', as: 'new_sessions'
7  post 'login', to: 'sessions#create', as: 'create_sessions'
8  delete 'logout', to: 'sessions#destroy', as: 'destroy_sessions'

今回はshowやeditのアクションでは、URLに:idを含めないようにするため、resourceとしているのがポイントです。

ユーザー機能のコントローラーの作成

次にユーザー機能のコントローラーを作成していきます。

1rails g controller users

コントローラーの作成が完了しましたら、それぞれのアクションに必要な処理を記述していきます。

1# memo_app/app/controllers/users_controller.rb
2class UsersController < ApplicationController
3
4+     def new
5+         @user_new = User.new
6+     end
7+ 
8+     def show
9+         @user = User.find(session[:user_id])
10+     end
11+ 
12+     def edit
13+         @user = User.find(session[:user_id])
14+     end
15+ 
16+     def create
17+         @user_new = User.new(user_params)
18+         if @user_new.save
19+             session[:user_id] = @user_new.id
20+             flash.now[:notice] = "ユーザーの新規登録に成功しました。"
21+             redirect_to memos_path
22+         else
23+             flash.now[:alert] = "ユーザーの新規登録に失敗しました。"
24+             render action: "new"
25+         end
26+     end
27+ 
28+     def update
29+         @user = User.find(session[:user_id])
30+         if @user.update(user_params)
31+             redirect_to users_path
32+             flash.now[:notice] = "ユーザー情報の更新に成功しました。"
33+         else
34+             render action: "edit"
35+             flash.now[:alert] = "ユーザー情報の更新に失敗しました。"
36+         end
37+     end
38+ 
39+     private
40+ 
41+     def user_params
42+         params.require(:user).permit(:name, :email, :password)
43+     end
44
45end

特にユーザー機能ではストロングパラメーターの仕組みを利用するのが推奨されています。 そのため、ユーザー情報のパラメーターを取得する取得するメソッドをユーザーコントローラー内のprivate内にuser_paramsというメソッド名で作成しています。 また、ユーザー登録と同時にsessionメソッドでユーザーのクッキーにユーザーIDを渡すことにより、ユーザー登録と同時にログイン状態にすることができます。

ユーザー機能のユーザー登録画面の作成

次にユーザー機能のユーザー登録画面の作成をしています。

1# memo_app/app/views/users/new.html.erb
2<div class="wrapper">
3    <div class="container">
4        <h2>ユーザー新規登録</h2>
5
6        <%= form_with model: @user_new, url: users_path, local: true, method: :post do |f| %>
7            <%= f.label :name, "Name" %>
8            <%= f.text_field :name, class: "form-box" %>
9
10            <%= f.label :email, "Email" %>
11            <%= f.email_field :email, class: "form-box" %>
12
13            <%= f.label :password, "Password" %>
14            <%= f.password_field :password, class: "form-box" %>
15
16            <%= f.submit "新規登録", class: "btn" %>
17        <% end %>
18    </div>
19</div>

ユーザー登録機能に必要なユーザー名、メールアドレス、パスワードを登録するフォームを作成しています。

ユーザー機能のユーザー詳細画面の作成

次にユーザー機能のユーザー詳細画面の作成をしています。

1# memo_app/app/views/users/show.html.erb
2<div class="wrapper">
3    <div class="container">
4        <h2>ユーザー情報</h2>
5
6        <div class="">
7            <p>Name</p>
8        </div>
9        <div class="form-box">
10            <%= @user.name %>
11        </div>
12
13        <div class="">
14            <p>Email</p>
15        </div>
16        <div class="form-box">
17            <%= @user.email %>
18        </div>
19
20        <%= link_to "編集", edit_users_path, method: :get %>
21
22    </div>
23</div>

ユーザー情報を表示する場合、パスワードなどの機密情報の取り扱いには注意する必要があります。 そのため、ユーザー詳細ページではパスワードは表示しないようにしています。

ユーザー機能のユーザー編集画面の作成

次にユーザー機能のユーザー編集画面の作成をしています。

1# memo_app/app/views/users/edit.html.erb
2<div class="wrapper">
3    <div class="container">
4        <h2>ユーザー編集</h2>
5
6        <%= form_with model: @user, url: users_path, local: true, method: :patch do |f| %>
7            <%= f.label :name, "Name" %>
8            <%= f.text_field :name, class: "form-box" %>
9
10            <%= f.label :email, "Email" %>
11            <%= f.email_field :email, class: "form-box" %>
12
13            <%= f.submit "更新", class: "btn" %>
14        <% end %>
15    </div>
16</div>

ユーザー情報を編集する場合、同じようにパスワードなどの機密情報の取り扱いには注意する必要があります。 もし、パスワードを変更する場合の機能を実装したい場合は、様々なWebアプリケーションと同様に処理を分けてあげたほうが良いかと思います。

ユーザー機能への導線の作成

次にユーザー機能への導線を作成しています。

1# memo_app/app/views/layouts/application.html.erb
2
3        <div class="header-right">
4+         <% if @current_user.nil? %>
5+           <%= link_to "新規登録", new_users_path, method: :get %>
6            <%= link_to "ログイン", new_sessions_path, method: :get %>
7          <% else %>
8+           ログインユーザー:<%= @current_user.name %>さん
9+           <%= link_to "登録情報", users_path, method: :get %>
10            <%= link_to "ログアウト", destroy_sessions_path, method: :delete %>
11          <% end %>
12        </div>

もしユーザーがログイン状態であれば登録情報画面へのリンク、ログアウト状態であれば新規登録画面へのリンクを追加しています。

ユーザー機能のユーザー認証の整理

次にユーザー機能のユーザー認証の整理しています。

1# memo_app/app/controllers/application_controller.rb
2class ApplicationController < ActionController::Base
3
4    def current_user
5        if session[:user_id]
6          @current_user = User.find(session[:user_id])
7        else
8          flash[:alert] = "ログインする必要があります。"
9          redirect_to new_sessions_path
10        end
11    end
12
13    def logged_in?
14        if session[:user_id]
15            @current_user = User.find(session[:user_id])
16            flash[:notice] = "すでにログインしています。"
17            redirect_to memos_path
18        end
19    end
20
21end

また、今回はユーザー機能を実装したことにより、変数が重複してしまうことが多くなるため、わかりやすいように変数を「@current_user」に修正しています。 同じように「app/controllers/sessions_controller.rb」や「app/views/sessions/new.html.erb」の変数も修正しておきましょう。

ユーザー機能にアクセス制限を実装

次にユーザー機能にアクセス制限を実装しています。

1# memo_app/app/controllers/users_controller.rb
2class UsersController < ApplicationController
3+   before_action :current_user, only: [:show, :edit, :update]
4+   before_action :logged_in?, only: [:new, :create]
5
6    def new
7        @user_new = User.new
8    end

ユーザーがログインしていない状態でユーザー情報の閲覧、編集や更新をされては非常に危ないため、ユーザーコントローラーの「show,edit,update」に「current_user」でアクセス制限をかけています。 また、ユーザーはログイン状態ではユーザー登録ができないようにするため、ユーザーコントローラーの「new,create」に「logged_in?」でアクセス制限をかけています。

おわりに

Ruby on Railsで自作ログイン機能を用いたユーザー機能の実装について解説してきましたが、いかがだったでしょうか。 ユーザー管理は非常に重要な機能なため、今回は省略していますがユーザー削除の機能を実装する場合も論理削除とするか、物理削除とするかもWebアプリケーションの方針に深くかかわってきます。 是非、ユーザーがWebアプリケーションを使いやすいようにするためにも、ユーザー機能の実装にチャレンジにしてみてください。

【Ruby on Rails】簡単なメモアプリの作成|ユーザー認証と併せてユーザー機能を実装 | いっしー@Webエンジニア