5
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Rails】enumで対応ステータスを更新する

Posted at

自作アプリを作成しているときに、管理者機能として、フォームからのお問い合わせの対応ステータスを更新する機能があったらいいなと思い、調べながら実装してみたので、メモしておきます!

実装画面はこんな感じです👇
Videotogif (1).gif

前提

構成(モデル等は生成済の前提で進めます)

  • MODEL (FormInquiry)
    • t.integer "user_id"
    • t.text "content"
    • t.integer "response_status", default: 0
    • t.datetime "created_at"
    • t.datetime "updated_at"
  • CONTROLLER (form_inquiries)
    • 問い合わせ一覧(index action)
    • 問い合わせ詳細(show action)
    • 対応ステータス更新(update action)
  • VIEWS
    • 問い合わせ一覧(index.html)
    • 問い合わせ詳細(show.html)

ライブラリ

  • enum_help(enumをI18n化するgem)
  • devise(ユーザー/管理者認証)

その他

  • 会員(エンドユーザー)をUser、管理者をAdminとしてそれぞれテーブルを作成しています。
  • 会員からフォームで問い合わせを受け付けると、管理者の問い合わせ一覧画面に表示されます。
  • 管理者は問い合わせ詳細画面を開き、対応ステータス(未対応/対応中/対応済)の更新を行えます。更新すると、フラッシュメッセージが表示され、問い合わせ一覧のステータスも更新されます。

環境
ruby 2.6.3
rails 5.2.6
OS:Linux(CentOS)
IDE:Cloud9

実装

enumとは?
「列挙型」という、整数が割り当てられた文字列を順に出力していく変数のことで、0を男性、1を女性のように、整数の値に何かしらの意味づけを行ってデータを管理することができます。「hashのkey部分の定数を保存すると、そのkeyに対応するvalueの整数が保存される仕組み」とのこと(【Rails】 enumチュートリアルより)

今回は、以下のような値で進めていくことにします。
{ 0: outstanding(未対応), 1: in_progress(対応中), 2: closed(対応済)}

STEP1. enumの定義

👇 FormInquiryモデルのresponse_statusカラムに対して、enumを定義します

app/models/form_inquiry.rb
belongs_to :user
enum response_status: { outstanding: 0, in_progress: 1, closed: 2 }

次に、enumを日本語化します。
👇 Gemfileにenum_helpを追記して、保存したらbundle installします。

Gemfile
gem 'enum_help'

👇 英語名に対応する日本語の値を、ja.ymlに定義します。

config/locales/ja.yml
ja:
  time:
    formats:
      default: "%Y/%m/%d %H:%M"
  enums:
    form_inquiry:
      response_status:
        outstanding: "未対応"
        in_progress: "対応中"
        closed: "対応済"

👇 もしアプリケーションのデフォルト言語が日本語になっていない場合は、設定しておきます

config/application.rb
module App
  class Application < Rails::Application
    # 略
    config.i18n.default_locale = :ja
  end
end

STEP2. コントローラーに記述

対応ステータスの更新はupdateアクションで行います。
更新できたら、問い合わせ詳細画面にリダイレクトし、フラッシュメッセージを表示するようにしています。

app/controllers/form_inquiry_controller.rb
class Admin::FormInquiriesController < ApplicationController
  before_action :authenticate_admin!
  before_action :set_form_inquiry, only: [:show, :update]

  def index
    @form_inquiries = FormInquiry.all.includes(:user).order(created_at: "DESC").page(params[:page]).per(10)
  end

  def show
    @user = User.find(@form_inquiry.user_id)
  end

  def update
    if @form_inquiry.update(form_inquiry_params)
      redirect_to admin_form_inquiry_path(@form_inquiry), notice: "対応ステータスを更新しました"
    else
      render :show, alert: "対応ステータスを更新できませんでした"
    end
  end

  private

  def form_inquiry_params
    params.require(:form_inquiry).permit(:response_status)
  end

  def set_form_inquiry
    @form_inquiry = FormInquiry.find(params[:id])
  end
end

STEP3. ビューの記述

問い合わせ詳細(show)

👇 対応ステータスの更新は、問い合わせ詳細画面で行うため、show.html.erbにセレクトボックスを実装します(※該当部分のみ抜粋しています)

app/views/form_inquiries/show.html.erb
   <%= form_with model: [:admin, @form_inquiry], method: :patch, local: true do |f| %>
     <%= f.select :response_status, FormInquiry.response_statuses.keys.map {|k| [I18n.t("enums.form_inquiry.response_status.#{k}"), k]} %>
     <%= f.submit "変更" %>
   <% end %>

ここでは、enumの値(未対応/対応中/対応済)のセレクトボックスを作成するため、mapメソッド(配列の要素の数だけブロック内で処理を繰り返して、新しい配列を返すメソッド)を使用します。

ここで何をしているか確認しておくと、

  • keysメソッドでハッシュオブジェクトからキーのみ配列の形で取り出している(outstanding/in_progress/closed
  • I18nのtranslateメソッド(I18n.t)でenumのキーの内容を翻訳している
  • keysメソッドで取り出した値一つ一つに対しmapメソッドで処理し、二次元配列(配列の中に、配列が格納された形の配列のこと)を戻り値として返す

試しにrails cで返り値を見てみると、こうなっています👇
[3]はtranslateメソッドを使わなかった場合を一応出力してみた形です。
image.png

二次元配列の2つ目の要素(["対応中", "in_progress"])を選択して、検証ツールで見てみると、この二次元配列の1つ目の要素がoptionタグの表示部分に、2つ目の要素がvalueに入る仕組みであることがわかります。

image.png

これが他2つの二次元配列に対しても展開されて、セレクトボックスが生成されているようですね。

問い合わせ一覧(index)

👇 7〜13行目で、一覧に表示する対応ステータスをif文を使って分岐させています。
日本語化した定数の値を表示したいので、カラム名の末尾に_i18nを追記します。

app/views/form_inquiries/index.html.erb
    <table>
      <% @form_inquiries.each do |form_inquiry| %>
        <tr>
          <td><%= l form_inquiry.created_at %></td>
          <td><%= link_to form_inquiry.user.name, admin_user_path(form_inquiry.user.id) %></td>
          <td>
            <% if form_inquiry.response_status == 'outstanding' %>
              <%= form_inquiry.response_status_i18n %>
            <% elsif form_inquiry.response_status == 'in_progress' %>
              <%= form_inquiry.response_status_i18n %>
            <% else %>
              <%= form_inquiry.response_status_i18n %>
            <% end %>
          </td>
          <td>
            <%= link_to "詳細", admin_form_inquiry_path(form_inquiry.id), class:'btn btn-sm py-0 btn-outline-secondary' %>
          </td>
        </tr>
      <% end %>
    </table>

これで対応ステータスが更新できるようになりました!

keysメソッドやmapメソッドの部分は、個人的にまだ理解が難しいのですが、言語化することで理解が少し深まったように思います。何かお気づきの点があれば、ぜひご教示ください。

参考資料

5
8
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
5
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?