ruby-on-rails - 我的“不允许的参数::passenger”Rails 错误来自哪里?
问题描述
我正在使用 Rails 构建一个航班预订应用程序,让您可以选择机场、日期和乘客人数。一旦您选择了机场和日期,它会为您提供单选按钮来选择您想要的航班,一旦您点击提交,您将被带到一个预订确认页面,您需要提供乘客信息。
确认页面(bookings#new) 有一个嵌套表单以将乘客包含在预订对象中。为此,我首先设置了以下模型和关联:
class Passenger < ApplicationRecord
belongs_to :booking
end
class Booking < ApplicationRecord
belongs_to :flight
has_many :passengers
accepts_nested_attributes_for :passengers
end
以及导致以下模式表的相关迁移:
create_table "bookings", force: :cascade do |t|
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.integer "flight_id"
t.integer "passenger_id"
end
create_table "passengers", force: :cascade do |t|
t.string "name"
t.string "email"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.integer "booking_id"
t.index ["booking_id"], name: "index_passengers_on_booking_id"
end
据我了解,流程是这样的:用户选择航班-> 用户提交航班,通过我控制器上的#new 方法转到 Booking#new:
class BookingsController < ApplicationController
def new
@booking = Booking.new
@flight = Flight.find(params[:flight_id])
params[:passengers_number].to_i.times do #params passed from select flight page
@booking.passengers.build
end
end
然后,我构建的表单接管了 new.html.erb:
<%= form_with model: @booking, url: bookings_path do |f| %>
<%= f.hidden_field :flight_id, value: @flight.id %>
<% @booking.passengers.each_with_index do |passenger, index| %>
<%= f.fields_for passenger, index: index do |form| %>
<h4><%= "Passenger #{index+1}"%> <br> </h4>
<%= form.label :name, "Full name:" %>
<%= form.text_field :name %>
<%= form.label :email, "Email:" %>
<%= form.email_field :email %>
<% end %>
<% end %>
<%= f.submit "Confirm details"%>
<% end %>
我用姓名和电子邮件填写它,单击“确认详细信息”,我在终端上收到此错误:
Unpermitted parameter: :passenger
为什么?我已经设置accepts_nested_attributes_for :passengers
了我的 Booking 模型,我的 booking_params 方法是:
def booking_params
params.require(:booking).permit(:flight_id,
:passengers_attributes => [:name, :email, :passenger_id, :created_at, :updated_at])
end
我的#create 方法是:
def create
@booking = Booking.new(booking_params)
respond_to do |format|
if @booking.save
format.html { redirect_to @booking, notice: "booking was successfully created." }
format.json { render :show, status: :created, location: @booking }
else
format.html { redirect_to root_path, alert: "booking failed, #{@booking.errors.full_messages.first}" , status: :unprocessable_entity }
format.json { render json: @booking.errors, status: :unprocessable_entity }
end
end
end
有什么我不允许的吗?请注意,如果我设置booking_params
为params.require(:booking).permit!
它会给我一个unknown attribute 'passenger' for Booking
错误。但至少据我所知,我已经定义了关于乘客和预订的关联和数据库。
提前致谢
编辑:生成错误的服务器日志是:
Started POST "/bookings" for ::1 at 2021-08-27 17:52:17 +0300
Processing by BookingsController#create as HTML
Parameters: {"authenticity_token"=>"[FILTERED]", "booking"=>{"flight_id"=>"5", "passenger"=>{"0"=>{"name"=>"Jason Smason", "email"=>"jason@ymail.com"}, "1"=>{"name"=>"Joe Smith", "email"=>"Joe@smith.com"}}}, "commit"=>"Confirm details"}
Unpermitted parameter: :passenger
Edit2:我听从 PCurell 的建议,将我的fields_for
to <%= f.fields_for :passengers, passenger, index: index do |form| %>
和我的预订参数更改为:passenger => [:name, :email, :passenger_id, :created_at, :updated_at])
这产生了一个不同的错误:Unpermitted parameter: passengers_attributes'. So I changed my controller's
booking_params` to:
def booking_params
params.require(:booking).permit(:flight_id,
:passengers_attributes => [:name, :email, :passenger_id, :created_at, :updated_at],
:passenger => [:name, :email, :passenger_id, :created_at, :updated_at])
end
有了这个,我成功地创建了一个有 2 名乘客的预订。但是,乘客是空白的;他们name
和email
为零。日志说:
Parameters: {"authenticity_token"=>"[FILTERED]", "booking"=>{"flight_id"=>"1", "passengers_attributes"=>{"0"=>{"0"=>{"name"=>"John Smith", "email"=>"John@smith.com"}}, "1"=>{"1"=>{"name"=>"Burger King", "email"=>"bk@bk.com"}}}}, "commit"=>"Confirm details"}
Unpermitted parameter: :0
Unpermitted parameter: :1
我也许可以硬编码 :0 和 :1 以通过,但肯定不是 Rails 方式。有没有办法让他们动态进入?还是我做错了整个事情?
解决方案
你的用法fields_for
不正确。当您查看指南中的示例时,您会注意到没有必要用.each
if 来包装它作为集合。
10.2 嵌套表单
以下表单允许用户创建一个
Person
及其关联的地址。<%= form_with model: @person do |form| %> Addresses: <ul> <%= form.fields_for :addresses do |addresses_form| %> <li> <%= addresses_form.label :kind %> <%= addresses_form.text_field :kind %> <%= addresses_form.label :street %> <%= addresses_form.text_field :street %> ... </li> <% end %> </ul> <% end %>
当一个关联接受嵌套属性时,
fields_for
它会为关联的每个元素呈现一次它的块。特别是,如果一个人没有地址,则它不会呈现任何内容。一种常见的模式是控制器构建一个或多个空子,以便向用户显示至少一组字段。下面的示例将导致在新人员表单上呈现 2 组地址字段。def new @person = Person.new 2.times { @person.addresses.build } end
将其应用于您的代码时,删除.each
包装器并更改passenger
为:passengers
应该可以解决问题。您可以通过传递给块index
的FormBuilder
实例 ( ) 访问。form
fields_for
<%= form_with model: @booking, url: bookings_path do |f| %>
<%= f.hidden_field :flight_id, value: @flight.id %>
<%= f.fields_for :passengers do |form| %>
<h4>Passenger <%= form.index + 1 %></h4>
<%= form.label :name, "Full name:" %>
<%= form.text_field :name %>
<%= form.label :email, "Email:" %>
<%= form.email_field :email %>
<% end %>
<%= f.submit "Confirm details"%>
<% end %>
推荐阅读
- python - ID 为“None”的 djongo 公司不存在。也许它被删除了?
- phpstorm - 在不打开 PhpStorm 的情况下更改 PhpStorm 启动运行时
- android - 何时在 PlayStore 的应用内购买中调用“消费”
- python - 获取用于图像分割的 semtorch 学习模型的 TypeError
- angularjs - 使用 Angular 将大数据从 Excel 导入数据库
- python-3.x - 在python中修复数据框中的索引值
- xamarin.android - 签名 Xamarin 应用签名和 Google Play 商店上传
- android-studio - Android Studio 布局错误
- javascript - Nuxtjs - 第 3 方脚本导致控制台中的“TypeError:无法读取 null 的属性(读取'文档')”循环
- nginx - Nuxt SSR + Nginx + 仅静态缓存?