Rails belongs_to 多个模型 accept_nested_attributes_for
Rails belongs_to multiple models with accept_nested_attributes_for
我正在为汽车贸易商构建一个发票系统,其中每张发票都与一个客户和一辆车相关联,客户可能有很多发票,而车辆也有很多发票。我已经使用一个嵌套模型执行以下操作:
purchase_invoice.rb
class PurchaseInvoice < ApplicationRecord
belongs_to :vehicle
accepts_nested_attributes_for :vehicle
end
vehicle.rb
class Vehicle < ApplicationRecord
has_many :purchase_invoices
end
purchase_invoices_controller.rb
def new
@vehicle = Vehicle.new
@purchase_invoice = @vehicle.purchase_invoices.build
end
def create
@vehicle = Vehicle.new
@purchase_invoice = @vehicle.purchase_invoices.build(invoice_params)
if @purchase_invoice.save
redirect_to @purchase_invoice
else
render 'new'
end
end
private
def invoice_params
params.require(:purchase_invoice).permit(:buyer, :location, :vehicle_price, :transfer_fee, :balance_due, :payment_cash, :payment_bank_transfer, :payment_comment, :status, vehicle_attributes: [:vrm, :date_first_registered, :make, :model, :colour, :transmission, :vin, :fuel, :power])
end
new.html.erb
<%= form_with model: @purchase_invoice, local: true do |form| %>
<%= form.fields_for @vehicle do |vehicle_form| %>
<% end %>
<% end %>
然而,当我像这样添加第二个关系时:
purchase_invoice.rb
class PurchaseInvoice < ApplicationRecord
belongs_to :customer
belongs_to :vehicle
accepts_nested_attributes_for :customer
accepts_nested_attributes_for :vehicle
end
我收到一条错误消息:'Unpermitted parameters: :vehicle'
有人知道为什么吗?另外,我将如何在保持强参数的同时修改控制器 new/create 构建操作?
我已经在谷歌上搜索了四个小时,尝试了很多但没有成功。在此先感谢大家!
更新
这是我的日志:
Started POST "/purchase_invoices" for 127.0.0.1 at 2018-03-20 15:10:01 +0000
Processing by PurchaseInvoicesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"JB8py9zNxew6aQ6/za3JHDEb4j8f9HGujTlS6P1Eyhb+5NtPPP47fW7AHBkt9eURcnXg0gh9Mf1DCKCSwvlAbg==", "purchase_invoice"=>{"customer"=>{"name"=>""}, "vehicle"=>{"vrm"=>"SA07SSX", "make"=>"VAUXHALL", "model"=>"MERIVA DESIGN", "colour"=>"Silver", "vin"=>"W0L0XCE7574216645", "date_first_registered"=>"20/03/2007"}, "vehicle_odomoter_reading"=>"", "vehicle_number_of_keys"=>"", "vehicle_mot_expiry"=>"", "vehicle_hpi_clear"=>"", "vehicle_comments"=>"", "buyer"=>"", "location"=>"", "vehicle_price"=>"", "transfer_fee"=>"0", "balance_due"=>"", "payment_cash"=>"", "payment_bank_transfer"=>"", "payment_comments"=>""}, "commit"=>"Create Purchase invoice"}
Vehicle Load (0.3ms) SELECT "vehicles".* FROM "vehicles" WHERE "vehicles"."vrm" = ? ORDER BY "vehicles"."id" ASC LIMIT ? [["vrm", "SA07SSX"], ["LIMIT", 1]]
Unpermitted parameters: :customer, :vehicle, :payment_comments
(0.1ms) begin transaction
(0.1ms) rollback transaction
Rendering purchase_invoices/new.html.erb within layouts/application
Rendered purchase_invoices/new.html.erb within layouts/application (10.2ms)
Rendered layouts/_header.html.erb (1.7ms)
Completed 200 OK in 63ms (Views: 54.4ms | ActiveRecord: 0.4ms)
你的方法有一些问题,但你已经很接近了。 PurchaseInvoice 模型属于 Vehicle 和 Customer,它存储 customer_id 和一个 vehicle_id。这是正确的。正如您在评论中所说,它不仅仅是一个连接模型,因为它包含许多其他数据,例如价格、转账费用等。无论如何,您传递了很多关于 vehicle 的参数要购买的 ,而不是 车辆 的 id。事实上,您是在 PurchaseInvoice 创建中创建 vehicle,这是没有意义的。此外,你的 vehicle_attributes 不应该是一个数组,而是一个散列(因为 PurchaseInvoice belongs_to :vehicle
; 所以它只是一个),并且应该只有 vehicle_id。鉴于您只需要 vehicle_id,您不需要 nested_attributes
(客户也不需要)。我会改变:
控制器:
def new
@vehicles = Vehicle.all #All vehicles, to select from the list
@customers = Customer.all #All customers, to select from the list (unless you use current_user)
@purchase_invoice = PurchaseInvoice.new
end
def create
@vehicle = Vehicle.find(params[:vehicle_id])
@customer = Customer.find(params[:customer_id]) # Or use current_user
#The above is only needed to check if vehicle and customer exist, but it is not needed below
@purchase_invoice = PurchaseInvoice.create(invoice_params)
if @purchase_invoice.save
redirect_to @purchase_invoice
else
render 'new'
end
end
def invoice_params
params.require(:purchase_invoice).permit(:customer_id, vehicle_id, :location, :vehicle_price, :transfer_fee, :balance_due, :payment_cash, :payment_bank_transfer, :payment_comment, :status)
end
观点:
<%= form_with model: @purchase_invoice, local: true do |form| %>
<!-- This is necessary to choose the customer. If the customer is current_user, just remove it. -->
<%= form.collection_select(:customer_id, @customers, :id, :name %>
<!-- This is necessary to choose the vehicle. This is extremely simplified -->
<!-- The customer should be able to look at many attributes of the car -->
<!-- to be able to select one to purchase -->
<%= form.collection_select(:vehicle_id, @vehicles, :id, :make %>
<!-- All other invoice fields. -->
<% end %>
我正在为汽车贸易商构建一个发票系统,其中每张发票都与一个客户和一辆车相关联,客户可能有很多发票,而车辆也有很多发票。我已经使用一个嵌套模型执行以下操作:
purchase_invoice.rb
class PurchaseInvoice < ApplicationRecord
belongs_to :vehicle
accepts_nested_attributes_for :vehicle
end
vehicle.rb
class Vehicle < ApplicationRecord
has_many :purchase_invoices
end
purchase_invoices_controller.rb
def new
@vehicle = Vehicle.new
@purchase_invoice = @vehicle.purchase_invoices.build
end
def create
@vehicle = Vehicle.new
@purchase_invoice = @vehicle.purchase_invoices.build(invoice_params)
if @purchase_invoice.save
redirect_to @purchase_invoice
else
render 'new'
end
end
private
def invoice_params
params.require(:purchase_invoice).permit(:buyer, :location, :vehicle_price, :transfer_fee, :balance_due, :payment_cash, :payment_bank_transfer, :payment_comment, :status, vehicle_attributes: [:vrm, :date_first_registered, :make, :model, :colour, :transmission, :vin, :fuel, :power])
end
new.html.erb
<%= form_with model: @purchase_invoice, local: true do |form| %>
<%= form.fields_for @vehicle do |vehicle_form| %>
<% end %>
<% end %>
然而,当我像这样添加第二个关系时:
purchase_invoice.rb
class PurchaseInvoice < ApplicationRecord
belongs_to :customer
belongs_to :vehicle
accepts_nested_attributes_for :customer
accepts_nested_attributes_for :vehicle
end
我收到一条错误消息:'Unpermitted parameters: :vehicle'
有人知道为什么吗?另外,我将如何在保持强参数的同时修改控制器 new/create 构建操作?
我已经在谷歌上搜索了四个小时,尝试了很多但没有成功。在此先感谢大家!
更新
这是我的日志:
Started POST "/purchase_invoices" for 127.0.0.1 at 2018-03-20 15:10:01 +0000
Processing by PurchaseInvoicesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"JB8py9zNxew6aQ6/za3JHDEb4j8f9HGujTlS6P1Eyhb+5NtPPP47fW7AHBkt9eURcnXg0gh9Mf1DCKCSwvlAbg==", "purchase_invoice"=>{"customer"=>{"name"=>""}, "vehicle"=>{"vrm"=>"SA07SSX", "make"=>"VAUXHALL", "model"=>"MERIVA DESIGN", "colour"=>"Silver", "vin"=>"W0L0XCE7574216645", "date_first_registered"=>"20/03/2007"}, "vehicle_odomoter_reading"=>"", "vehicle_number_of_keys"=>"", "vehicle_mot_expiry"=>"", "vehicle_hpi_clear"=>"", "vehicle_comments"=>"", "buyer"=>"", "location"=>"", "vehicle_price"=>"", "transfer_fee"=>"0", "balance_due"=>"", "payment_cash"=>"", "payment_bank_transfer"=>"", "payment_comments"=>""}, "commit"=>"Create Purchase invoice"}
Vehicle Load (0.3ms) SELECT "vehicles".* FROM "vehicles" WHERE "vehicles"."vrm" = ? ORDER BY "vehicles"."id" ASC LIMIT ? [["vrm", "SA07SSX"], ["LIMIT", 1]]
Unpermitted parameters: :customer, :vehicle, :payment_comments
(0.1ms) begin transaction
(0.1ms) rollback transaction
Rendering purchase_invoices/new.html.erb within layouts/application
Rendered purchase_invoices/new.html.erb within layouts/application (10.2ms)
Rendered layouts/_header.html.erb (1.7ms)
Completed 200 OK in 63ms (Views: 54.4ms | ActiveRecord: 0.4ms)
你的方法有一些问题,但你已经很接近了。 PurchaseInvoice 模型属于 Vehicle 和 Customer,它存储 customer_id 和一个 vehicle_id。这是正确的。正如您在评论中所说,它不仅仅是一个连接模型,因为它包含许多其他数据,例如价格、转账费用等。无论如何,您传递了很多关于 vehicle 的参数要购买的 ,而不是 车辆 的 id。事实上,您是在 PurchaseInvoice 创建中创建 vehicle,这是没有意义的。此外,你的 vehicle_attributes 不应该是一个数组,而是一个散列(因为 PurchaseInvoice belongs_to :vehicle
; 所以它只是一个),并且应该只有 vehicle_id。鉴于您只需要 vehicle_id,您不需要 nested_attributes
(客户也不需要)。我会改变:
控制器:
def new
@vehicles = Vehicle.all #All vehicles, to select from the list
@customers = Customer.all #All customers, to select from the list (unless you use current_user)
@purchase_invoice = PurchaseInvoice.new
end
def create
@vehicle = Vehicle.find(params[:vehicle_id])
@customer = Customer.find(params[:customer_id]) # Or use current_user
#The above is only needed to check if vehicle and customer exist, but it is not needed below
@purchase_invoice = PurchaseInvoice.create(invoice_params)
if @purchase_invoice.save
redirect_to @purchase_invoice
else
render 'new'
end
end
def invoice_params
params.require(:purchase_invoice).permit(:customer_id, vehicle_id, :location, :vehicle_price, :transfer_fee, :balance_due, :payment_cash, :payment_bank_transfer, :payment_comment, :status)
end
观点:
<%= form_with model: @purchase_invoice, local: true do |form| %>
<!-- This is necessary to choose the customer. If the customer is current_user, just remove it. -->
<%= form.collection_select(:customer_id, @customers, :id, :name %>
<!-- This is necessary to choose the vehicle. This is extremely simplified -->
<!-- The customer should be able to look at many attributes of the car -->
<!-- to be able to select one to purchase -->
<%= form.collection_select(:vehicle_id, @vehicles, :id, :make %>
<!-- All other invoice fields. -->
<% end %>