Rails中Cocoon嵌套表单未附加items_attributes到参数问题
items_attributes未被提交到参数中 我用Cocoon gem给Campaign模型构建嵌套表单,通过link_to_add_association添加新的item行,关联关系配置正确,但从日志中看不到items_attributes被附加到参数里,无法定位问题。
日志信息
Campaign Create (1.8ms) INSERT INTO "campaigns" ("title", "user_id", "status", "created_at", "updated_at", "numberofitems", "shipping_type") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id" [["title", "asdfasdf"], ["user_id", 52], ["status", 1], ["created_at", "2022-11-07 18:25:31.782846"], ["updated_at", "2022-11-07 18:25:31.782846"], ["numberofitems", 11], ["shipping_type", 1]]
表单代码
<%= form_with(model: [@user, @campaign], url: admin_create_campaign_path, method: :post, local: true) do |f| %> <%= render partial: 'step_1', locals: {f: f} %> <h1>Añadir items a la campaña</h1> <%= f.fields_for :items do |ff| %> <%= render partial: 'item_fields', ff: ff %> <% end %> <%= link_to_add_association 'Añadir item', f, :items %> <%= f.submit "Crear campaña", class: "btn btn-primary" %> <% end %>
item_fields局部视图
<div class="nested-fields"> <div class="card"> <%= f.hidden_field :_destroy %> <div class="field form-group"> <%= f.label :product_id, "Producto asociado al item", class: "form-label" %> <%= f.select :product_id, options_from_collection_for_select(Product.all, :id, :name), {}, class: "form-control" %> </div> <div class="field form-group"> <%= f.label :selected_colors, "Color de producto", class: "form-label" %> <%= f.text_field :selected_colors, placeholder: "Color", class: "form-control" %> </div> <div class="field form-group"> <%= f.hidden_field :campaign_id, value: @campaign.id, class: "form-control" %> </div> <div class="field form-group"> <%= f.label :quantity, "Cantidad de item", class: "form-label" %> <%= f.number_field :quantity, value: @campaign.numberofitems, class: "form-control" %> </div> <div class="field form-group"> <button class="btn btn-primary"> <%= link_to_remove_association "Quitar item", f %> </button> </div> </div> </div>
参数白名单代码
def campaign_builder_params params.require(:campaign).permit(:campaign, :id, :status, :recipients_data, :selectedproducts => [], :selectedextras => [], :items_attributes => [:_destroy, :id, :product_id, :campaign_id, :price, :selected_colors, :selected_size, :quantity]) end def items_params params.require(:item).permit(:status, :campaign, :purchasing_price, :price, :carrier, :delivery_date, :tracking_code, :is_design_made_by_client, :supplier, :selected_colors, :selected_size, :design_source_url) end
完善模型嵌套属性配置
确保Campaign模型正确开启嵌套属性支持,若需要删除功能需加上allow_destroy: true:class Campaign < ApplicationRecord has_many :items, dependent: :destroy accepts_nested_attributes_for :items, allow_destroy: true end初始化空Item实例
在控制器的new或create动作中,给@campaign初始化至少一个空item,这样fields_for才会生成正确的表单字段结构:def new @campaign = Campaign.new @campaign.items.build # 初始化空item,确保表单渲染出嵌套字段的基础结构 end修正局部视图变量传递错误
表单渲染item_fields时,局部变量名传递错误,需改成:<%= render partial: 'item_fields', locals: {f: ff} %>原写法
ff: ff会导致局部视图里的f未定义,字段无法生成正确的name属性(比如campaign[items_attributes][0][product_id]),直接导致参数无法被正确识别。移除多余的
campaign_id隐藏字段
嵌套表单会自动处理关联外键,且此时@campaign尚未保存(id为空),手动设置反而干扰参数提交,直接删除该字段:<!-- 删除此行 --> <%= f.hidden_field :campaign_id, value: @campaign.id, class: "form-control" %>修复参数白名单语法与字段遗漏
campaign_builder_params存在语法错误(末尾多余逗号),且遗漏了Campaign的核心字段,修正后:def campaign_builder_params params.require(:campaign).permit( :id, :status, :recipients_data, :title, :numberofitems, :shipping_type, :selectedproducts => [], :selectedextras => [], :items_attributes => [:_destroy, :id, :product_id, :price, :selected_colors, :selected_size, :quantity] ) end注意:不需要
:campaign这个字段,需包含表单中所有Campaign的字段,否则这些字段也无法正确保存。确保控制器使用正确的参数方法
在create动作中,必须使用campaign_builder_params创建Campaign,嵌套属性会随主模型参数一起提交,无需单独调用items_params:def create @campaign = @user.campaigns.build(campaign_builder_params) if @campaign.save # 成功逻辑 else # 失败逻辑 end end
内容的提问来源于stack exchange,提问作者user3074558

