2017-02-19 51 views
0

我有一个嵌套的表单,我想将一个散列保存到field_form中,但是这只保存最后一个在params中。Ruby on Rails。来自field_form的嵌套表单只返回一个散列而不是散列的散列

这是我的控制器

def new 
    @inventory_products = [] 
    @inventory   = Inventory.new 
    @products    = Product.all 
    @products.each do |p| 
    @inventory_products << p.inventory_products.build 
    end 
end 

这是形式

<%= form_for @inventory do |f| %> 
    <%= render 'shared/error_messages', object: f.object%> 
    <%= f.label :description, "Description" %> 
    <%= f.text_area :description, class: 'form-control' %> 
    <%= f.label :warehouse, "Warehouse" %> 
    <%= f.select :warehouse_id, options_for_select(Warehouse.all.map { 
           |b| [ b.name, b.id ] }), 
       prompt: "foobar"%> 
    <%= f.label :products, "Productos" %> 
    <table class = "table table-bordered"> 
     <thead> 
     <tr> 
      <th>+</th> 
      <th>Codigo</th> 
      <th>Nombre</th> 
      <th>Cantidad a Ingresar</th> 
     </tr> 
     </thead> 
     <tbody> 
     <% @inventory_products.each_with_index do |i, index|%> 
     <%= f.fields_for "inventory_products[]", i do |iv|%> 
     <tr> 
      <td> 
      <%= iv.check_box :product_id, {class: 'add_product',checked:false},iv.object.product_id.to_s, "0" %> 
      </td> 
      <td><%= @products[index].code %></td> 
      <td><%= @products[index].name %></td> 
      <td> 
      <%= iv.number_field :quantity, class:"form-control quantity#{iv.object.product_id.to_s}", readonly: true %> 
      </td> 
     </tr> 
     <% end %> 
    <% end %> 

库存模型

class Inventory < ApplicationRecord 
    has_many :inventory_products 
    has_many :products, through: :inventory_products 
    belongs_to :warehouse 
    accepts_nested_attributes_for :inventory_products 
    validates:description, presence:true, length: {maximum:150} 
end 

库存产品型号

class InventoryProduct < ApplicationRecord 
    belongs_to :product 
    belongs_to :inventory 
    accepts_nested_attributes_for :product 
    validates:quantity, presence:true, numericality: { greater_than: 0} 
end 

产品型号

class Product < ApplicationRecord 
    has_many :inventory_products 
    has_many :inventories, through: :inventory_products 
end 

PARAMS

<ActionController::Parameters {"utf8"=>"✓", "authenticity_token"=>"xwu4sCQCCCWOwXqbJkvVl9MDs2HRmjdT8IL2eMdMi0KHbibzHuQNmIWpot7fVqohvvxDlMIAEBzlDZB0OW3DCQ==", "inventory"=>{"description"=>"", "warehouse_id"=>"", "inventory_products"=>{"product_id"=>"1", "quantity"=>""}}, "commit"=>"Agregar", "controller"=>"inventories", "action"=>"create"} 
+1

您可以包括有问题的模型以及期望的结果是什么?你在做什么看起来像是应该如何使用'fields_for'和'accep_nested_attributes'的黑客版本,但它很难看到你实际上想要完成什么。 – max

+0

你应该添加到这个问题的是一个高层次的描述“当创建一个订单时,用户应该能够...然后...” – max

+0

我更新模型@max并更改问题的标题, params后,inventory_products fields_for只返回一个散列而不是数组散列 –

回答

0
def new 
    @inventory   = Inventory.new 
    @products    = Product.all 
    @products.each do |p| 
    @inventory << p.inventory_products.new(product: p) 
    end 
end 

def create 
    @inventory = Inventory.new(inventory_params) 
    if @inventory.save 
    # ... 
    else 
    # ... 
    end 
end 

private 

def inventory_params 
    params.require(:inventory).permit(inventory_products_attributes: [:product_id, :quantity, :_keep]) 
end 

替代通过手动迭代记录你只需要使用fields_for对联想和Rails会创建正确的PARAMS:

<%= form_for(@inventory) do |f| %> 
    <%= f.fields_for :inventory_products do |iv|%> 
    <tr> 
     <td> 
     <%= iv.hidden_field :product_id %> 
     <%= iv.check_box :_keep, { class: 'add_product', checked:false }%> 
     </td> 
     <td><%= iv.object.code %></td> 
     <td><%= iv.object.name %></td> 
     <td> 
     <%= iv.number_field :quantity, class:"form-control quantity#{iv.object.product_id.to_s}", readonly: true %> 
     </td> 
    </tr> 
    <% end %> 
<% end %> 

我们还引入一个名为_keep而不是使用复选框的产品ID的虚拟属性 - 这似乎是一个非常过于复杂和哈克建立。

class InventoryProduct < ApplicationRecord 
    belongs_to :product 
    belongs_to :inventory 
    attr_reader :_keep 
    accepts_nested_attributes_for :product, reject_if: :not_acceptable? 
    validates :quantity, 
    presence: true, 
    numericality: { greater_than: 0 } 

    def _keep=(value) 
    @_keep = typecast_to_boolean(value) 
    end 

    def not_acceptable?(attributes) 
    !typecast_to_boolean(attributes[:_keep]) 
    end 

    private 

    def typecast_to_boolean(value) 
    ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value) 
    end 
end 
+0

感谢您的答案,但如果更改新的方法,我得到的错误未定义的方法'<<'的库存, –

+0

我想制作一个数组inventory_products_attributes –

+0

抱歉复制粘贴错误。您不需要使用'fields_for'手动创建数组。如果你在一对多或多对多关联中使用'fields_for',它将遍历记录并为每个相关项创建输入。 http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-fields_for – max