Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 4 NOT updating nested attributes

Tags:

Issue: Instead of updating nested attributes, they are being created on top of the existing nested attributes when I hit the #update action of the associated features_controller.rb

Likely Cause: I think the problem lies in my lack of understanding in Rails' form_for. I think the breakdown is in my views, how I render the persisting nested attributes, and/or how I fail to specify the nested attribute's id, causing it to simply create a new one

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, "Scenario"       = builder.text_area :description, rows: "3", autocomplete: "off" 

I'm sure there's a nicer way to achieve the if @feature.new_record? check. I'm also using a few Javascript hooks to create dynamic nested attribute forms (which I've left out), heavily influenced by Railscast #196 Nested Model Form (revised)

I would love a really nice Rails-y implementation of dealing with these sorts of nested forms.

like image 532
pruett Avatar asked Sep 08 '13 16:09

pruett


1 Answers

Try adding :id to the :scenario_attributes portion of your feature_params method. You only have the description field and the ability to allow a destroy.

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

As @vinodadhikary suggested, you no longer need to check if feature is a new record, since Rails, specifically using the form_for method, will do that for you.

Update:

You don't need to define if @feature.new_record? ... else in your form. It will be taken care by Rails when you use form_for. Rails checks if the action is going to be create or update based on object.persisted?, so, you can update your form to:

= 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" 
like image 170
thank_you Avatar answered Oct 19 '22 07:10

thank_you