今回、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を持たせる形になります。
belongs_to :customer
has_many :order_products, dependent: :destroy
enum status: {
入金待ち: 0,
入金確認: 1,
製作中: 2,
発送準備中: 3,
発送済み: 4
}
belongs_to :order
belongs_to :product
enum making_status: {
製作不可: 0,
製作待ち: 1,
製作中: 2,
製作完了: 3
}
##3. 数値で更新する
ステータスを更新する際、form_withを使って下記のような書き方をしていました。
<%= 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 %>
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で管理してるのに数値でデータの受け渡しをしないのはどうなのか、、、と思っていました。
<%= 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型に変換してあげる必要があるみたいです。
order = Order.find(params[:id])
status = params[:order][:status].to_i
order.update(status: status)
redirect_to admin_order_path(order)
これで無事数値でデータを更新することができました!
もう少し簡潔にできればいいのですが(できるのかもしれない)
今後も色々と使う機会が出てくるかもしれないので、しっかりと身に付けていきたい。
内容に不備、間違いがあればコメントいただけますと幸いです。