具有嵌套属性的Rails表单。 text_field没有出现

时间:2019-06-14 04:38:09

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

问题:我没有嵌套的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进行迭代,以便能够上载一个文件(用于测试的text_field),然后将其保存到具有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"}

型号没有改变。

以参数形式打印文件仍为空白吗?

更新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 %>

在视图的新方法和方法中包含以下内容:

@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,但使用一个布尔值(对于该布尔值而言实际上是活动的),或者搜索附加了ID的print_locations。但是我宁愿不那样做,而只是保存在创建时选择的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_location。

2 个答案:

答案 0 :(得分: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,以避免出现其他错误。

答案 1 :(得分:0)

由于对象没有任何对象,因此您必须告诉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 %>