Accepts_Nested_Attributes_For Rails 4 Is Not Deleting

accepts_nested_attributes_for rails 4 is not deleting

You need to allow the :_destroy parameter for your nested model as well, as this gets used when you check the 'Delete' checkbox in the form. It's Rails' way of flagging model instances that have to be destroyed.

def land_params  
params.require(:land).permit(uploads_attributes: [:id, :filename, :_destroy])
end

Rails 4 deleting nested attributes, works on create but not on edit/update

when you are doing

# Never trust parameters from the scary internet, only allow the white list through.
def patient_params
params.require(:patient).permit!
end

it permits all of your attributes and it's not recommended. It's more of a hack rather than a solution.

If you look at your question

Rails 4 deleting nested attributes, works on create but not on edit/update

and if you look at your params permitted

# Never trust parameters from the scary internet, only allow the white list through.
def patient_params
params.require(:patient).permit(:first_name, :last_name, medications_attributes: [:name, :_destroy])
end

This will work on creating patients but not on updating or editing them because when you create a new record it doesn't require you to permit id but when you want to update or edit a record you need its id to be permitted as well.

Fix:

Just pass the id attribute to permitted attributes and it will work for you

# Never trust parameters from the scary internet, only allow the white list through.
def patient_params
params.require(:patient).permit(:id, :first_name, :last_name, medications_attributes: [:id,:name, :_destroy])
end

Rails accepts_nested_attributes_for with belongs_to. How to delete relation, not item?

Rails nested_attributes (in particular for this case your rubic_attributes Hash) means that you are modifying the associated record(s) and not the record itself. Because item_id is an attribute of the Material model and not the associated Rubic model, then nested attribute Hash won't be able to update that value (unless its associated record is destroyed through _destroy, of which Rails seem to automatically update material.rubric_id to nil).

But because you do not want to destroy the associated record but just update material.rubric_id to nil through the material.update(rubric_attributes: {...}) Hash and that you do not want to use the "normal-way" of simply doing material.update(rubric_id: nil), then you can do a workaround like below which still makes use of rubric_attributes:

class Material < ApplicationRecord
belongs_to :rubric, optional: true
accepts_nested_attributes_for :rubric, allow_destroy: true
end

class Rubric < ApplicationRecord
has_many :materials, dependent: :nullify
accepts_nested_attributes_for :materials
end

Usage:

rubric = Rubric.create!
material = Material.create!(rubric: rubric)

material.update!(
rubric_attributes: {
id: material.rubric.id,
materials_attributes: {
id: material.id,
rubric_id: nil # or `rubric: nil`
}
}
)

puts material.rubric_id
# => 1

# not sure why `material` needs to be reloaded. Rails `inverse_of` seems to not work on "nested" nested_attributes
material.reload

puts material.rubric_id
# => nil

puts Rubric.exists?(id: 1)
# => true

# now you've updated material.rubric_id to nil, but not destroying the Rubric record

IMPORTANT! If this nested attributes is going to be used in the controller, for security purposes, don't forget to only permit the params.permit(rubric_attributes: [materials_attributes: [:rubric_id]]) ... or any other fields you deem whitelistable.

Rails 6 nested attributes not deleting existing records when updating

If I understand you correctly you're deleting the options one by one by clicking a button next to the option. Thats not actually something you need or want to use nested attributes for. Nested attributes is only relevant when you're creating/editing multiple records at once.

While you can destroy a single nested record by updating the parent:

patch '/questions/1', params: { 
question: { options_attributes: [{ id: 1, _destroy: true }] }
}

Its very clunky and not really a good RESTful design.

Instead you can just setup a standard destroy action:

# config/routes.rb
resources :options, only: :destroy
<%= button_to 'Destroy option', option, method: :delete %>
class OptionsController < ApplicationController
# @todo authenticate the user and
# authorize that they should be allowed to destroy the option
# DELETE /options/1
def destroy
@option = Option.find(params[:id])
@option.destroy
respond_to do |format|
format.html { redirect_to @option.question, notice: 'Option destroyed' }
format.json { head :no_content }
end
end
end

This uses the correct HTTP verb (DELETE instead of PATCH) and clearly conveys what you're doing.

rails nested attributes creating, but not updating and not deleting

It appeared that it happens due to this association declaration:

has_and_belongs_to_many :people

I had this relation defined as HABTM initially, but later as it often happens I needed to get access to the join table and created a corresponding model CompaniesPerson, but didn't update :people association to work via has_many through. And now I discovered that changing the above statement to

has_many :people, through: :companies_people

or just completely commenting it out fixes the issue with nested attributes not updating and not deleting. Wow, pretty unexpected.



Related Topics



Leave a reply



Submit