Rails 嵌套表单无效(根本未传递子参数)
Rails nested form not working (child parameters not passed at all)
型号
`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
。
求助!
如果您的 f.fields_for 块是正确的并且其中有数据,那么即使强参数决定阻止它们,参数也会是正确的。它们没有出现在参数中但其他字段确实出现在参数中这一事实让我觉得问题出在你的 f.fields_for 块中。
找到了答案...但有点担心,因为这似乎是一个很常见的问题,而且我在任何地方都没有看到它被提及。所以如果我做错了什么...请给我线索。
发生的事情是 orders_attributes
在提交失败的第二次尝试中没有通过(我在这里 运行 rspec 测试)。他们没有通过的原因是因为他们在表格上不存在。原因如下:
def new
@buyer = Buyer.new
@buyer.orders.build
end
在 new
操作中,表单为 buyer
和 order
创建字段,因为两者都已初始化。但是我原来的 create
动作是这样的:
def create
@buyer = Buyer.new(buyer_params)
...
if @buyer.save
redirect_to '/'
else
render 'new'
end
end
换句话说,如果一切顺利,并且 buyer_params 构建出有效的 buyer
和 order
,太棒了!但是如果发生某种错误,并且页面重新呈现,则没有 order
对象来构建表单字段!
结果,答案:
def create
@buyer = Buyer.new(buyer_params)
@buyer.orders.first_or_intialize
if @buyer.save
...
end
结果是这样的:
- 如果没有错误 第一行同时创建
buyer
和 order
第二行是一个有争议的点,因为它只会调用刚刚创建的 order
(在我的例子中,即使我把它写成 has_many
,实际上 buyer
只有一个 order
;即使那不是在这种情况下,我没有使用 order
对象做任何事情,所以第二行没有害处)
- 如果有错误则第二行实例化一个
order
对象,这样当页面重新渲染时,就有一个order
对象为 建立字段
型号
`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
。
求助!
如果您的 f.fields_for 块是正确的并且其中有数据,那么即使强参数决定阻止它们,参数也会是正确的。它们没有出现在参数中但其他字段确实出现在参数中这一事实让我觉得问题出在你的 f.fields_for 块中。
找到了答案...但有点担心,因为这似乎是一个很常见的问题,而且我在任何地方都没有看到它被提及。所以如果我做错了什么...请给我线索。
发生的事情是 orders_attributes
在提交失败的第二次尝试中没有通过(我在这里 运行 rspec 测试)。他们没有通过的原因是因为他们在表格上不存在。原因如下:
def new
@buyer = Buyer.new
@buyer.orders.build
end
在 new
操作中,表单为 buyer
和 order
创建字段,因为两者都已初始化。但是我原来的 create
动作是这样的:
def create
@buyer = Buyer.new(buyer_params)
...
if @buyer.save
redirect_to '/'
else
render 'new'
end
end
换句话说,如果一切顺利,并且 buyer_params 构建出有效的 buyer
和 order
,太棒了!但是如果发生某种错误,并且页面重新呈现,则没有 order
对象来构建表单字段!
结果,答案:
def create
@buyer = Buyer.new(buyer_params)
@buyer.orders.first_or_intialize
if @buyer.save
...
end
结果是这样的:
- 如果没有错误 第一行同时创建
buyer
和order
第二行是一个有争议的点,因为它只会调用刚刚创建的order
(在我的例子中,即使我把它写成has_many
,实际上buyer
只有一个order
;即使那不是在这种情况下,我没有使用order
对象做任何事情,所以第二行没有害处) - 如果有错误则第二行实例化一个
order
对象,这样当页面重新渲染时,就有一个order
对象为 建立字段