背景
Railsアプリケーションにおいて、予約システムの実装中に意図しない挙動が発生しました。その解決策を備忘録として記事に残します。
問題の詳細
具体的には、reservationsテーブルのTime型のtime_slotカラムの登録の際、params[:reservation][:time_slot]
の値がTime
型ではなく、DateTime
型(String
型)として認識される上に、ストロングパラメータを通過しているにもかかわらず、create
アクションではparams[:reservation][:time_slot]がnil
になるという不具合が発生しました。エラーメッセージは以下の通りです。
# エラーメッセージ
ActiveRecord::NotNullViolation - PG::NotNullViolation: ERROR: null value in column "time_slot" of relation "reservations" violates not-null constraint
問題が生じた状況
reservations_controller.rb
def reservation_params
params.require(:reservation).permit(:customer_id,
:company_id,
:request,
:is_approved,
:date,
:time_slot,
service_ids: [])
end
confirm.html.erb
<%= form_with model: @reservation, url: reservations_path, method: :post do |form| %>
<div class="field">
<strong><%= form.label :time_slot, "Start Time" %></strong>
<%= form.select :time_slot, @available_start_times.map { |time| [time, time] }, { include_blank: true }, { required: true } %>
</div>
...
<%= form.hidden_field :time_slot, value: @time_slot %>
<div class="actions">
<%= form.submit "Confirm Reservation" %>
</div>
<% end %>
原因
<%= form.select :time_slot, @available_start_times.map { |time| [time, time] }, { include_blank: true }, { required: true } %>
でtime_slot
をパラメータとして渡しているつもりでしたが
<%= form.hidden_field :time_slot, value: @time_slot %>
によってパラメータが上書きされ、意図しない値が送信されていたことが原因でした。
解決策
以下の行を削除することで解決しました。
<%= form.hidden_field :time_slot, value: @time_slot %>
残った疑問
削除前はストロングパラメータでフィルタするまではparams[:reservation][:time_slot]
は"2000-01-01 00:00:00 +0900"
でした。それがcreateアクションに遷移すると""
になってしまう理由については今も不明です。詳細がわかる方がいらっしゃったらご教授いただけると幸いです。
学んだ教訓
- フォームで使用する隠しフィールドは発見しづらい不具合を生じさせることがあるので注意が必要