1

I have two models namely Invoice and InvoiceDetails and:

class Invoice < ActiveRecord::Base

  has_many :invoice_details

Now an User has the ability to edit an invoice, so he can remove the invoiceDetails attributes from the invoice. So how can I delete those nested attributes of the invoiceDetails model while updating the invoice(parent) model.

I'm using AngularJS for client side.

The Update Action :

  def update
    invoice_id = params[:id]
    invoice = Invoice.find(invoice_id)
    if invoice.update(invoice_params)
      render json: invoice, status: 200
    else
      render json: { errors: invoice.errors }, status: 422
    end
  end

  def invoice_params
    invoice_params = params.require(:invoice).permit(:total_amount,:balance_amount, :customer_id, :totalTax, :totalDiscount, :bill_date,:company_id, { invoice_details: [:id,:invoice_id,:product_id,:quantity, :discount, :subtotal, :tax] })
    invoice_params[:invoiceDetails_attributes] = invoice_params.delete :invoice_details
    invoice_params.permit!
  end

The Invoice Model

class Invoice < ApplicationRecord
  has_many :invoiceDetails, inverse_of: :invoice, dependent: :destroy
  belongs_to :customer
  accepts_nested_attributes_for :invoiceDetails
end

The InvoiceDetails Model

class InvoiceDetail < ApplicationRecord
  belongs_to :invoice
  belongs_to :product
end
2
  • You need to pass _destroy parameter true or false for every InvoiceDetail object. Commented Jul 8, 2017 at 11:52
  • Can you please elaborate the answer by giving an example Commented Jul 8, 2017 at 12:06

2 Answers 2

0

In case someone is stalled on this, here is what I did. I added an attribute is_hide in InvoiceDetails(child) model. When a user deletes an InvoiceDetails attribute, the is_hide property is set to true.

In the Invoice(parent) model, I used the before_save callback and iterated through the InvoiceDetails attributes and called mark_for_destruction where is_hide = true.

This is how my Invoice model looks :

class Invoice < ApplicationRecord
  has_many :invoiceDetails, inverse_of: :invoice, dependent: :destroy, autosave: true
  belongs_to :customer
  accepts_nested_attributes_for :invoiceDetails

  before_save :mark_children_for_removal

  def mark_children_for_removal
    invoiceDetails.each do |child|
      child.mark_for_destruction if child.is_hide?
    end
  end

end
Sign up to request clarification or add additional context in comments.

Comments

0

By now (not sure since when actually) this feature is built in and you can just use the _destroy attribute. Make sure to allow it in your parameters and the just add a checkbox to the nested form:

<%= nested_form.check_box '_destroy' %>

This will then remove all marked items on update/saving.

See also this answer: https://stackoverflow.com/a/7151191/1595029

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.