1
0

フォームの隠しフィールドによる意図しないNotNullViolationとその解決策

Last updated at Posted at 2024-03-06

背景

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アクションに遷移すると""になってしまう理由については今も不明です。詳細がわかる方がいらっしゃったらご教授いただけると幸いです。

学んだ教訓

  • フォームで使用する隠しフィールドは発見しづらい不具合を生じさせることがあるので注意が必要
1
0
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
1
0