问题:当我点击相关的features_controller.rb的#update操作时,不会更新嵌套属性,而是在现有的嵌套属性之上创建它们.
可能的原因:我认为问题在于我在Rails的form_for中缺乏理解.我认为细分在我的看法,我如何呈现持久的嵌套属性,和/或我如何无法指定嵌套属性的id,导致它只是创建一个新的
feature.rb
class Feature < ActiveRecord::Base ... has_many :scenarios accepts_nested_attributes_for :scenarios,allow_destroy: true,reject_if: :all_blank ... end
features_controller.rb
def update ... project = Project.find(params[:project_id]) @feature = Feature.find(params[:id]) if @feature.update_attributes(feature_params) # checking feature_params looks good... # feature_params['scenarios'] => { <correct object hash> } redirect_to project else render :edit end end ... private def feature_params params.require(:feature).permit(:title,:narrative,:price,:eta,scenarios_attributes[:description,:_destroy]) end
_form.html.haml(simplified)
= form_for [@project,@feature] do |f| ... - if @feature.new_record? -# if we are creating new feature = f.fields_for :scenarios,@feature.scenarios.build do |builder| = builder.label :description,"Scenario" = builder.text_area :description,rows: "3",autocomplete: "off" - else -# if we are editing an existing feature = f.fields_for :scenarios do |builder| = builder.label :description,autocomplete: "off"
我确定有一个更好的方式来实现if @ feature.new_record?检查.我也使用一些Javascript钩子来创建动态嵌套的属性表单(我已经遗漏了),受到了Railscast #196 Nested Model Form (revised)的很大影响
我会喜欢一个非常好的Rails-y实现来处理这些嵌套表单.
解决方法
尝试将:id添加到feature_params方法的:scenario_attributes部分.你只有描述字段和允许破坏的能力.
def feature_params # added => before nested attributes params.require(:feature).permit(:id,:title,scenarios_attributes => [:id,:description,:_destroy]) end
正如@vinodadhikary所建议的那样,您不再需要检查功能是否是新的记录,因为Rails,特别是使用form_for方法,将为您做到这一点.
更新:
你不需要定义@ feature.new_record? …你的形式当您使用form_for时,它将被Rails照顾. Rails会检查是否要根据object.persisted?创建或更新该操作,因此,您可以将表单更新为:
= form_for [@project,@feature] do |f| ... = f.fields_for :scenarios,@feature.scenarios.build do |builder| = builder.label :description,"Scenario" = builder.text_area :description,autocomplete: "off"