【问题标题】:Rails form with nested attributes. text_field not appearing带有嵌套属性的 Rails 表单。 text_field 没有出现
【发布时间】:2019-06-14 04:38:09
【问题描述】:

问题:我有一个嵌套的 fields_for text_field 没有出现,我不确定我做错了什么。

目标:在创建记录时,使用预设变量遍历模型,并将文件(使用 text_field 测试)保存到保存预设变量和表单记录 ID 的连接表中

型号:

class PrintLocation < ApplicationRecord
  has_many :shop_products, through: :shop_product_print_files
  has_many :shop_product_print_files
  accepts_nested_attributes_for :shop_product_print_files
end

class ShopProductPrintFile < ApplicationRecord
  belongs_to :shop_products
  belongs_to :print_locations
end

class ShopProduct < ApplicationRecord
    ...
  has_many :shop_product_print_files
  has_many :print_locations, through: :shop_product_print_files
  accepts_nested_attributes_for :print_locations
  accepts_nested_attributes_for :shop_product_print_files
    ...
end

表格:

<%= form_for @shop_product do |f| %>
   <%= f.collection_select :product_id, @products, :id, :sku %>
   <% PrintLocation.all.each do |print_location| %>
     <%= print_location.title %>
        <%= f.fields_for :shop_product_print_files do |a| %>
           <%= a.text_field :print_file %>
        <% end %>
     <% end %>
   <%= f.submit %>
<% end %>

这样,text_field 不会出现,但print_location.title 会出现。这没有错误。

在保存@shop_product 时,我希望能够遍历可能定义的print_location 变量,然后对于每个可能的print_location,然后能够上传文件(用于测试的文本字段),然后将其保存到具有 shop_product_idprint_location_idprint_file 属性的 ShopProductPrintFile 模型中。

我对如何使用fields_for 有什么误解吗?

店铺产品总监:

创建:

@shop_product = ShopProduct.new(shop_product_params)
shop = Shop.find(params["shop_product"]["shop_id"])
product = Product.find(params["shop_product"]["product_id"])    @shop_product.product_id = product.id
@shop_product.shop_id = shop.id
respond_to do |format|
   if @shop_product.save!
...

更新:

@shop_product = ShopProduct.find_by(store_variant_id: params["shop_product"]["store_variant_id"])
@product = Product.find(params["shop_product"]["product_id"])

强参数:

def shop_product_params
   params.require(:shop_product).permit(:product_id, :store_product_id, :shop_id, :store_variant_id, :sync, :shop_product_print_file_attributes[:id, :print_files, :print_location_ids => [], :shop_product_ids => []], {print_location_ids: []})
end

更新 2:

更新和创建方法:

@shop_product.shop_product_print_files.build

表格:

<% PrintLocation.all.each do |print_location| %>
  <%= print_location.title %>
    <%= f.fields_for :shop_product_print_files_attributes do |a| %>
       <%= a.text_field :print_file %>
       <%= a.hidden_field :print_location_id, value: print_location.id %>
       <%= a.hidden_field :shop_product_id, value: shop_product.id %>
    <% end %>
<% end %>

参数:

def shop_product_params
   params.require(:shop_product).permit(:shop_product_print_files_attributes => [:ids => [], :print_files => [], :print_location_ids => [], :shop_product_ids => []])
end

错误: Shop product print files shop products must exist Shop product print files print locations must exist

通过的参数:

Parameters: {"utf8"=>"✓", "authenticity_token"=>"u/c103465uNCjF/trYrMleqxJ8b9wyLbU/vjPK4llYtCg/ODj92q5MN24==", "shop_product"=>{"sync"=>"1", "product_id"=>"3", "shop_product_print_files_attributes"=>{"print_file"=>"", "print_location_id"=>"6", "shop_product_id"=>"42"}, "store_product_id"=>"191234345", "store_variant_id"=>"15341234273", "id"=>"42"}, "commit"=>"Sync", "id"=>"42"}

模型没有改变。

params 中的打印文件还是空白?

更新 3:

**使用这种形式:感谢@arieljuod **

<%= f.fields_for :shop_product_print_files do |ff| %>
    <%= ff.object.print_location.title # get the print location from the association %> 
    <%= ff.hidden_field :print_location_id # save the print_location_id as a hidden field %>
    <%= ff.file_field :print_file # file input %>
  <% end %>

在容纳视图的新方法中使用 this:

@shop_product = ShopProduct.new
PrintLocation.all.each{|p| @shop_product.shop_product_print_files.build(print_location: p)}

在创作中工作。

由于 API 在页面加载之前不知道 ShopProduct 的 ID,因此仍然会出现问题,并且一个页面上可能存在多个 ID。

我使用:

<% if @shop_products.find_by(store_variant_id: variant.id)  %>
<% shop_product = @shop_products.find_by(store_variant_id: variant.id)  %>
   <%= form_for shop_product do |f| %>
   ...

其中,variant 来自 API 定义的循环:

<% @in_store_variants.each do |variant| %>

现在当使用shop_products 时(从variant.id 查找shop_product 已经存在时),fields_for 不会出现。假设这是因为不存在相关的记录。只有存在 shop_product.shop_product_print_files 时才会出现。

据我所知,目前唯一的解决方法是保存所有 print_locations,但使用实际处于活动状态的布尔值,或者搜索哪些 print_locations 附加了 ID。但我宁愿不这样做,只保存在创建时选择的 print_locations(通过上传print_file 选择)。

为了“解决”这个问题,我:

  1. 添加了accepts_nested_attributes_for reject_if: proc { |attributes| attributes['print_file'].blank? },它不会保存 ShopProductPrintFile 的,除非 print_file 字段提交了某些内容...

  2. 使用此表格(2 个表格,取决于是否存在)

    <% if @shop_products.find_by(store_variant_id: variant.id)  %>
       <%= form_for shop_product do |f| %>
       <% PrintLocation.all.each{|p| shop_product.shop_product_print_files.build(print_location: p)} %>
       <%= f.fields_for :shop_product_print_files do |ff| %>
           <%= ff.object.print_location.title %>
          <%= ff.hidden_field :print_location_id %>
            <%= ff.text_field :print_file %>
       <% end %>
      <%= f.submit "Sync" %>
    <% end %>
    <% else %>
       <%= form_for @shop_product do |f| %>
       <% PrintLocation.all.each{|p| @shop_product.shop_product_print_files.build(print_location: p)} %>
       <%= f.fields_for :shop_product_print_files do |ff| %>
           <%= ff.object.print_location.title %>
           <%= ff.hidden_field :print_location_id %>
           <%= ff.text_field :print_file %>
       <% end %>
        ...
    

2 的问题是我关联了 PrintLocation 1、2、3,它将显示 9 个字段,1、2、3 准备好更新,6 准备好创建。

是否可以在已创建的 ShopProducts 上调用 PrintLocation.all.each{|p| @shop_product.shop_product_print_files.build(print_location: p)} 以获取与可能的打印位置相关的 shop_product_print_file 不存在的情况。

例如... 使用打印位置创建 ShopProduct,1,2,3(共 6 个)

现在,存在 print_location 的 shop_product_print_location 将在表单中显示以进行更新,即 1,2 和 3。我怎样才能拥有它,以便其他未创建的 3 个现在显示以更新 ShopProduct 并创建新的 ShopProductPrintFile ?因此可以更新 ShopProduct 以使 shop_product_print_file 模型具有更多 print_locations。

【问题讨论】:

  • 很好,也许可以尝试像 f.fields_for :shop_product_print_files_attributes 这样添加“_attributes”,但我不确定
  • 你很虔诚,但是,我仍然对 print_file 参数不通过有疑问。它像"shop_product_print_file_attributes"=&gt;{"print_file"=&gt;"", "print_location_id"=&gt;"6", "shop_product_id"=&gt;"42"} 一样通过空白,在我的强大参数中我有` :shop_product_print_file_attributes [ :print_files, :shop_product_ids, :print_location_ids ]` 但收到错误:参数太多
  • 我也有这个问题,但在我的情况下它不是嵌套的。所以我认为这是因为 print_location_ids 和 shop_product_ids 是数组。所以,在强大的参数中会像product_ids:[] and shop_product_ids:[] 这样我不知道这个错误,也许是缺少箭头? :shop_product_print_file_attributes => [ ... ] 我希望它有效 ...
  • 另外...检查控制台是否在提交表单时显示“不允许的参数”之类的内容,有时会发生这种情况..
  • @GuilhermeNunes 最终是因为我的 strong_params 但仍然没有问题。如果你可以看一下,我在底部更新了我的帖子

标签: ruby-on-rails ruby form-for nested-form-for


【解决方案1】:

我有一个嵌套的fields_for text_field 没有出现,我不确定 我做错了什么。

您应该在创建操作中添加这一行

@shop_product = ShopProduct.new(shop_product_params)
@shop_product.shop_product_print_files.build #this one

还将shop_product_print_file_attributes 更改为shop_product_print_files_attributes 以避免任何进一步的错误。

【讨论】:

  • 谢谢...@shop_product.shop_product_print_files.build 应该同时进行更新和创建吗? (用户可以更新)
  • 我用收到的新表单、参数和新错误更新了我的 OP。
  • 如果有帮助的话,我正在使用 Ruby 2.4.5 ... Rails 5.2.2
  • 这样做:@shop_product.shop_product_print_files.build(shop_product_id: @shop_product.id, print_location_id: params["shop_product"]["shop_product_print_files_attributes"]["print_location_id"]) 在更新中有效。但是print_file 在提交的表单上仍然显示为空白...在创建ShopProduct 时也有问题,因为为了保存到ShopProductPrintFile 模式,我需要一个 ShopProduct,它尚未创建,所以@shop_product在create方法中没有通过?
  • 我还将 ShopProductPrintFile 模型中的 belongs_to 都更改为单数而不是复数
【解决方案2】:

你必须告诉rails在每次迭代中使用哪个PrintLocation,因为你的对象没有任何

<%= f.fields_for :shop_product_print_files, print_location do |a| %>

我不确定这是否是您想要的,但该字段会出现。

编辑:所以,我认为你需要这样的东西:

在控制器上

@shop_product = something_to_get_the_product
PrintLocation.all.each{|p| @shop_product.shop_product_print_files.build(print_location: p)}

我更喜欢在这里这样做,我不喜欢视图上的那种逻辑

现在您已经在商店产品对象上预先构建了所有可能的打印位置

在表格上

# note here the multipart option to allow files
<%= form_for @shop_product, multipart: true do |f| %>
  <%= f.collection_select :product_id, @products, :id, :sku %>

  <%= f.fields_for :shop_product_print_files do |ff| %>
    <%= ff.object.print_location.title # get the print location from the association %> 
    <%= ff.hidden_field :print_location_id # save the print_location_id as a hidden field %>
    <%= ff.file_field :print_file # file input %>
  <% end %>

  <%= f.submit %>
<% end %>

【讨论】:

  • 嗯,也许我会尝试,但我在帖子底部做了更新
  • 使用使页面无法加载:ActionView::Template::Error (undefined method print_file' for #<0x000055ace1e55e50>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多