Rails集合form_for创建报错及库存表单店铺标识问题求助
商品库存天数表单更新问题处理
问题背景
系统中有Product模型,每个商品对应不同店铺的min_stock_days(最低库存天数)和max_stock_days(最高库存天数)。在app/views/product/edit视图创建表单更新这些数据时遇到一系列问题,目前已解决部分报错,但仍无法区分输入框对应的店铺名称。
初始代码与报错
初始视图代码
<%= form_for @product.product_stores, :url => {:action => "update_stocks"} do |form| %> <% @product.product_stores.each do |e| %> <strong><%= e.store.name %></strong> <br/> <%= e.id %> <br/> <div class="row g-3 align-items-center"> <div class="col-auto"> <%= form.label :min_stock_days, class: "col-form-label" %> </div> <div class="col"> <%= form.text_field :min_stock_days, class: "form-control" %> </div> </div> <% end %> <% end %>
报错信息
undefined method `to_key' for #<ActiveRecord::Associations::CollectionProxy [#<ProductStore id: 913, min_stock_days: nil, max_stock_days: nil, product_id: 975, store_id: 24, created_at: "2024-01-17 16:14:53.475034000 -0300", updated_at: "2024-01-17 16:14:53.475034000 -0300">, #<ProductStore id: 11617, min_stock_days: nil, max_stock_days: nil, product_id: 975, store_id: 1, created_at: "2024-01-17 16:58:08.503417000 -0300", updated_at: "2024-01-17 16:58:08.503417000 -0300">, ...(省略部分ProductStore实例) ]> Did you mean? to_set to_ary
已完成的修正步骤
- 在
models/product.rb中添加嵌套属性支持:accepts_nested_attributes_for :product_stores, update_only: true - 在
products_controller.rb的product_params中添加参数权限:product_stores: [:min_stock_days, :max_stock_days] - 修改视图代码为:
<%= form_for @product, as: :post, method: :post, :url => {:action => "update_stocks"} do |form| %> <%= form.fields_for :product_stores, @product.product_stores.each do |ps|%> <strong> <%= ps %> </strong> <div class="row g-3 align-items-center"> <div class="col-auto"> <%= ps.label :min_stock_days, class: "col-form-label" %> </div> <div class="col"> <%= ps.text_field :min_stock_days, class: "form-control" %> </div> </div> <div class="row g-3 align-items-center"> <div class="col-auto"> <%= ps.label :max_stock_days, class: "col-form-label" %> </div> <div class="col"> <%= ps.text_field :max_stock_days, class: "form-control" %> </div> </div> <% end %> <div> <%= form.submit "Salvar", class: "btn btn-primary" %> </div> <% end %>
当前待解决问题
表单可正常渲染,但无法区分每个min_stock_days和max_stock_days输入框对应的店铺名称。
解决方案
1. 修改视图代码,显示店铺名称并确保参数正确关联
<%= form_for @product, as: :post, method: :post, :url => {:action => "update_stocks"} do |form| %> <%= form.fields_for :product_stores, @product.product_stores do |ps|%> <!-- 显示对应店铺名称 --> <strong><%= ps.object.store.name %></strong> <!-- 隐藏字段传递ProductStore的ID,确保更新对应记录 --> <%= ps.hidden_field :id %> <div class="row g-3 align-items-center"> <div class="col-auto"> <%= ps.label :min_stock_days, class: "col-form-label" %> </div> <div class="col"> <%= ps.text_field :min_stock_days, class: "form-control", value: ps.object.min_stock_days %> </div> </div> <div class="row g-3 align-items-center"> <div class="col-auto"> <%= ps.label :max_stock_days, class: "col-form-label" %> </div> <div class="col"> <%= ps.text_field :max_stock_days, class: "form-control", value: ps.object.max_stock_days %> </div> </div> <hr> <!-- 分隔不同店铺的表单区域,提升可读性 --> <% end %> <div> <%= form.submit "Salvar", class: "btn btn-primary" %> </div> <% end %>
2. 更新控制器参数配置
修正product_params的参数键名(使用嵌套属性标准命名)并允许id参数:
def product_params params.require(:product).permit( # 保留其他Product模型的允许参数 product_stores_attributes: [:id, :min_stock_days, :max_stock_days] ) end
说明:
- 移除
fields_for中的.each,因为fields_for会自动遍历关联集合,手动添加会导致重复遍历问题 - 通过
ps.object获取当前ProductStore实例,进而关联到对应的店铺模型获取名称 - 添加
hidden_field :id确保Rails能识别需要更新的具体ProductStore记录
内容的提问来源于stack exchange,提问作者Diogo Amaral
相关产品推荐
相关产品推荐

