通过 ajax Rails 4 构建的表单将子项添加到父项

Add children to parent from form constructed via ajax Rails 4

我有以下表格:

当用户从下拉列表中选择产品时,将触发 ajax 以查找单个产品的库存以将详细信息附加到 table。

用户可以在订单中附加产品详细信息。

最后我得到了类似的东西:

{"utf8"=>"✓", "authenticity_token"=>"xmlzMouWp0QGUnpKeawQ8OCPJ/GlF2bp0kn97ra2Qyb7TgsCkXmJEGD1l/oZitn+VPVJRc8x79/kTUtgbbDr0A==", "order"=>{"customer_search"=>"", "customer_id"=>"2", "product_search"=>"", "order_detail"=>[{"product_id"=>"10", "product_detail_id"=>"13", "price_id"=>"12"}, {"product_id"=>"1", "product_detail_id"=>"8", "price_id"=>"11"}], "subtotal"=>"111990", "tax"=>"0", "comission"=>"0", "total"=>"111990"}, "product_list"=>"1", "button"=>""}

我创建订单的代码可以正常工作,但我无法添加详细信息。

订单控制器

  def create

    # Creates the order removing the order details from the hash
    @order = Order.create(order_params.except!(:order_detail))

    # Set all the details into an empty array
    order_details_attributes = order_params[:order_detail]

    order_details_attributes.each do |order_detail_attributes|

      # Fill the params with order_id and creates the detail
      order_detail_attributes["order_id"] = @order.id
      @order_detail = OrderDetail.create(order_detail_attributes)

    end

    respond_to do |format|
      if @order.save
        format.html { redirect_to @order, notice: 'Order was successfully created.' }
        format.json { render :show, status: :created, location: @order }
      else
        format.html { render :new }
        format.json { render json: @order.errors, status: :unprocessable_entity }
      end
    end
  end

  def order_params
     params.require(:order).permit(:customer_id, :subtotal, :tax, :comission, :total, :invoice, :shipping_id, :order_detail, order_details_attributes: [:product_id, :product_detail_id, :price_id])
  end

我收到这个错误:

undefined method `delete' for nil:NilClass
order_details_attributes = order_params[:order].delete(:order_detail)

有什么不好的?我真的需要帮助:(

谢谢!!

order_params 没有键 :order,它只有你在 permit 方法中定义的键 order_params。实际上,您不需要手动创建 children 记录,因为 Rails 可以自动创建。看看这个:http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

你只需要在订单模型中添加accepts_nested_attributes_for :order_details,创建订单时填写order_details_attributes参数(目前你填写order_detail,你需要修复你的表格才能成为order_details_attributes,因为这是 Rails 约定之一,或者您可以为此使用 fields_for 帮助器)。然后您只需以标准方式创建订单,如 @order = Order.new(order_params)@order.save,您将获得一起创建的订单和订单详细信息。

这在Rails中真是一团糟。我只能推荐你阅读我发布的 link 并使用 Google 查找一些教程。

至于你得到的错误:

undefined method `delete' for nil:NilClass

order_params 中没有 :order 键。它在 params 中,但不在 order_params 中,因为您调用了 require(:order)。所以 order_params returns 只有你在 permit 方法中指定的键。但是 :order_detail 将是空的,因为您没有将它描述为具有某些键的数组(就像您对 order_details_attributes 所做的那样)。

所以,你的问题是你试图实现嵌套属性,但是你传递了 :order_detail 而不是 :order_details_attributes (嗯,但你仍然在强参数中有它)并尝试创建 children手动关系。不要这样做,只需使用 Rails 提供给您的内容即可。

有两种方法:

  1. 您继续使用 order_detail 参数。在这种情况下,您需要将控制器中的 order_params 更改为如下所示:

    params.require(:order).permit(:customer_id, :subtotal, :tax, :comission, :total, :invoice, :shipping_id, order_detail: [:product_id, :product_detail_id, :price_id])

(只需将 order_details_attributes 替换为 order_detail

然后代替

order_details_attributes = order_params[:order].delete(:order_detail)

你会

order_details_attributes = order_params[:order_detail]

(这里不需要 delete,因为 order_params 是一种 returns 哈希的方法)

并保留其余的控制器代码。而且您不需要嵌套属性,因为您不使用它(糟糕的方式)。

  1. 您完全使用了嵌套属性。我在下面的评论中描述了如何做到这一点。您还需要调整 jquery 代码以生成 order_details_attributes 而不是 order_detail.