Rails嵌套表单提交时仅向Booking添加1个Passenger对象问题排查
问题原因
- 你的表单每次调用
fields_for都绑定了同一个全局@passenger实例,生成的所有乘客输入框的name属性完全一致,浏览器提交时后输入的内容会直接覆盖之前的内容,所以最终只能拿到最后一位乘客的信息 - 没有为
Booking模型配置一对多关联的嵌套属性支持,fields_for无法识别你需要提交多个乘客的参数结构 - 控制器
new动作只初始化了1个乘客实例,没有根据需要的乘客数量提前为Booking实例构建对应数量的关联乘客对象
修复步骤
1. 配置Booking模型关联和嵌套属性
首先确保Booking模型和Passenger是一对多关联,开启嵌套属性支持:
class Booking < ApplicationRecord has_many :passengers # 开启乘客属性的嵌套写入支持 accepts_nested_attributes_for :passengers end class Passenger < ApplicationRecord belongs_to :booking end
2. 修改控制器逻辑
根据传入的乘客数量,提前为Booking实例构建对应数量的乘客关联对象,同时配置strong参数允许嵌套的乘客属性:
class BookingsController < ApplicationController def new @booking = Booking.new passenger_num = params[:passengers].to_i # 构建对应数量的乘客对象 passenger_num.times { @booking.passengers.build } end def create @booking = Booking.new(booking_params) # 后续保存逻辑... end private def booking_params params.require(:booking).permit(passengers_attributes: [:name, :email]) end end
3. 简化表单逻辑
不需要自己写times循环,直接让fields_for遍历已经构建好的乘客关联集合,自动生成带索引的输入框:
<%= form_for @booking do |f| %> <%= f.fields_for :passengers do |addy_form|%> <%= addy_form.text_field :name, placeholder: "name" %> <%= addy_form.text_field :email, placeholder: "email"%> <% end %> <%= hidden_field_tag(:flight_id, params[:flight_id]) %> <%= hidden_field_tag(:scheduled_for, params[:scheduled_for]) %> <%= hidden_field_tag(:from_airport, params[:from_airport]) %> <%= hidden_field_tag(:to_airport, params[:to_airport]) %> <%= f.submit 'Confirm Booking' %> <% end %>
修改后提交的参数会自动生成booking[passengers_attributes][0][name]、booking[passengers_attributes][1][name]这种带索引的结构,不会出现覆盖问题,所有乘客的信息都能正常提交。
内容的提问来源于stack exchange,提问作者Christian
相关产品推荐
相关产品推荐

