2017-02-19 122 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