LoginSignup
2
2

More than 3 years have passed since last update.

[Rails]enumを使ったデータの扱い方

Posted at

今回、enumを使用してステータスの更新を行う機会があり、色々と調べて格闘しながら実装したので、
enumについて書いていこうと思います。

環境

Ruby : 2.6.3
Ruby on Rails : 5.2.4

流れ

1. enumとは
2. enumの書き方
3. 実装する上で困った事

1. enumとは

enumは配列を組んでカラム内に予めデータを格納し、取得や更新などの管理を行うことができます。
今回のようにデータの数、選択肢が決まっている場合に活用します。

実装した際はこちらの記事を参考にさせていただきました。
-【Rails】 enumとは? enumを用いてselectボックスを作ってみた
https://qiita.com/clbcl226/items/3e832603060282ddb4fd

2. enumの書き方

今回は注文モデル(order)とそれに関連づいた注文商品モデル(order_product)に下記のようにステータスを持たせました。それぞれが連動するように実装するのですが、今回は省略します。
書き方はシンプルでkeyにvalueを持たせる形になります。

order.rb
  belongs_to :customer
  has_many :order_products, dependent: :destroy

  enum status: {
    入金待ち: 0,
    入金確認: 1,
    製作中: 2,
    発送準備中: 3,
    発送済み: 4
  }

order_product.rb

  belongs_to :order
  belongs_to :product

  enum making_status: {
    製作不可: 0,
    製作待ち: 1,
    製作中: 2,
    製作完了: 3
  }

3. 数値で更新する

ステータスを更新する際、form_withを使って下記のような書き方をしていました。

orders/show.html.erb

 <%= form_with model: order, url: admin_order_path(order), class:"update_status" do |f| %>
    <%= f.select :status, Order.statuses.keys %>
    <%= f.submit "更新", class:'btn btn-info' %>
  <% end %>

orders_controller.rb
class Admin::OrdersController < ApplicationController

  def update
    order = Order.find(params[:id])
    order.update(status: order.status)
    redirect_to admin_order_path(order)
  end

end

この場合、例えばビューで「入金確認」を選択して更新すると、パラメータにはそのまま「入金確認」という文字列が渡されてしまいます。
問題なく動作はするのですが、
せっかくenumで管理してるのに数値でデータの受け渡しをしないのはどうなのか、、、と思っていました。

orders/show.html.erb
  <%= form_with model: order, url: admin_order_path(order), class:"update_status" do |f| %>
    <%= f.select :status, options_for_select(Order.statuses.to_a, selected: order.status_before_type_cast) %>
    <%= f.submit "更新", class:'btn btn-info' %>
  <% end %>

そこで、このように渡す値を数値にするような書き方をしてみましたが、
これではString型で渡ってしまい、データの更新ができませんでした。

色々と調べていた結果、どうやらString型で渡したものをコントローラでInteger型に変換してあげる必要があるみたいです。

orders_controller.rb
    order = Order.find(params[:id])
    status = params[:order][:status].to_i
    order.update(status: status)
    redirect_to admin_order_path(order)

これで無事数値でデータを更新することができました!
もう少し簡潔にできればいいのですが(できるのかもしれない)

今後も色々と使う機会が出てくるかもしれないので、しっかりと身に付けていきたい。
内容に不備、間違いがあればコメントいただけますと幸いです。

2
2
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
2
2