Rails 4不更新嵌套属性

pru*_*ett 18 ruby-on-rails nested-attributes nested-form-for ruby-on-rails-4

问题:当我点击关联的操作时,它们是在现有嵌套属性的基础上创建的,而不是更新嵌套属性#updatefeatures_controller.rb

可能的原因:我认为问题在于我在Rails中缺乏理解form_for.我认为细分在我的视图中,如何呈现持久的嵌套属性,和/或我如何指定嵌套属性的id失败,导致它只是创建一个新的id

feature.rb

class Feature < ActiveRecord::Base
  ...
  has_many :scenarios
  accepts_nested_attributes_for :scenarios,
    allow_destroy: true,
    reject_if: :all_blank
  ...
end
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

_form.html.haml(简体)

= 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, "Scenario"
      = builder.text_area :description, rows: "3", autocomplete: "off"
Run Code Online (Sandbox Code Playgroud)

我确信有更好的方法来实现if @feature.new_record?检查.我也使用一些Javascript钩子来创建动态嵌套属性表单(我已经遗漏了),受Railscast#196嵌套模型表(修订版)的影响很大

我会喜欢一个非常好的Rails-y实现处理这些嵌套的表单.

jas*_*328 41

尝试添加:id到方法的:scenario_attributes一部分feature_params.您只有描述字段和允许销毁的能力.

def feature_params
  # added => before nested attributes
  params.require(:feature).permit(:id, :title, :narrative, :price, :eta, scenarios_attributes => [:id, :description, :_destroy])
end
Run Code Online (Sandbox Code Playgroud)

正如@vinodadhikary建议的那样,您不再需要检查功能是否是新记录,因为Rails,特别是使用该form_for方法,将为您做到这一点.

更新:

您无需if @feature.new_record? ... else在表单中定义.使用时,Rails会照顾它form_for.Rails会检查操作是基于create还是update基于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, rows: "3", autocomplete: "off"
Run Code Online (Sandbox Code Playgroud)

  • 允许用户设置ID是否安全? (5认同)
  • @ Philip7899 id仅用于确定哪个嵌套记录必须更新...如果没有传递它将尝试创建一个新的 (2认同)