Rails嵌套表单不起作用(子参数根本没有传递)

时间:2015-10-23 23:35:08

标签: ruby-on-rails ruby-on-rails-4 nested-forms nested-attributes

模型

`Buyer has_many :orders`
`Buyer accepts_nested_attributes_for :order`
`Order belongs_to :buyer`

查看(buyers#new

<%= form_for @buyer do |f| %>
  <%= f.fields_for :orders do |o| %>
    <div class="row">
      <div class="col-xs-12">
        <%= o.label "Select your meal" %>
      </div>
    </div>
    <div class="row section">
      <div class="col-xs-1"></div>
        <% ["Pasta, pesto, & pea greens (veggie)",
           "Mushroom cutlets & mornay sauce (veggie)",
           "Italian breaded pork chop",
           "Chicken kabobs with tzatziki",
        "Asian-style sweet & sour beef"].each do |m| %>
           <div class="col-xs-2 zero-padding">
             <div class="col-xs-12">
               <% image_tag "#{m}.jpg" %>
             </div>
             <div class="col-xs-12 text-center">
               <%= o.radio_button :meal, m %>
               <br>
               <%= m %>
             </div>
           </div>
        <% end %>
      <div class="clearfix">
    </div>
  <% end %>
  ...
<% end %>

控制器(buyers

 def new
    @buyer = Buyer.new
    @buyer.orders.build
 end

 def create
   # just to illustrate what i'm talking about, even the unsanitized parameters do not have orders_attributes
   puts params
   => {"utf8"=>"✓", "buyer"=>{"first_stripe_token"=>"tok_16zExiKQ2oHmpkBLo9y45Cv3", "delivery_instructions"=>"random", "zipcode"=>"02110", "email"=>"test@example.com", "phone1"=>"123", "phone2"=>"456", "phone3"=>"0789", "agree_tos"=>"1"}, "controller"=>"buyers", "action"=>"create"}
 end

 def buyer_params
    params.require(:buyer).permit(:first_stripe_token, :phone1, :phone2, :phone3, :zipcode, :delivery_instructions, :agree_tos, :email, orders_attributes: [:meal] )
 end

路线

match '/ondemand/create', to: 'buyers#create', via: :post, as: "buyers"

有些人提出了有关如何通过强参数允许嵌套属性的问题。那不是我的挑战。就我而言,嵌套属性在某种程度上是完全正确的,正如您在上面看到的那样,我对未经过类型化的参数进行了puts

帮助!

2 个答案:

答案 0 :(得分:0)

如果你的f.fields_for块是正确的并且其中有数据,那么即使强params决定阻止它们,params也是正确的。事实上,他们没有出现在参数中,但其他字段确实显示在参数中,这让我觉得问题出在你的f.fields_for块中。

答案 1 :(得分:0)

想出答案......但是有点担心,因为这似乎是一个常见的问题而我在任何地方都没有看到它。所以,如果我做错了什么......请告诉我。

发生的事情是orders_attributes没有通过第二次尝试提交失败(我在这里运行rspec测试)。他们没有被传递的原因是因为他们在表格上不存在。这就是原因:

def new
  @buyer = Buyer.new
  @buyer.orders.build
end

new操作中,表单会为buyerorder创建字段,因为两者都已初始化。但我原来的create动作看起来像这样:

def create
  @buyer = Buyer.new(buyer_params)
  ...
  if @buyer.save
    redirect_to '/'
  else
    render 'new'
  end
end

换句话说,如果一切顺利,且buyer_params建立了有效buyerorder,那就太棒了!但如果发生某种错误,并且页面重新呈现,则没有order对象来构建表单字段!

结果,答案是:

def create
  @buyer = Buyer.new(buyer_params)
  @buyer.orders.first_or_intialize

  if @buyer.save
    ...
end

结果如下:

  • 如果没有错误,第一行会同时创建buyerorder,第二行就是一个有争议的点,因为它只会调用刚创建的order(就我而言,即使我已将其写为has_many,实际上buyer只有一个order;即使这不是order在这种情况下,我没有使用order对象做任何事情,所以第二行没有坏处)
  • 如果有错误,则第二行会实例化order对象,以便在重新呈现页面时,有一个void List::Delete(int data) { // Create a temp pointer Node *tmp = head; // No nodes if ( tmp == NULL ) return; // Last node of the list if ( tmp->Next() == NULL ) { delete tmp; head = NULL; } else { // Parse through the nodes Node *prev; do { if ( tmp->Data() == data ) break; prev = tmp; tmp = tmp->Next(); } while ( tmp != NULL ); // Adjust the pointers prev->SetNext(tmp->Next()); // Delete the current node delete tmp; } 对象来构建< / LI>