`marked_for_destruction?` returns `false` after parent object is passed

Hello everyone,

I’m having a sort of interesting issue in Ruby 3.0.2 / Rails 6.1.4.

I have a controller which “builds” an Invoice object. Whether the Invoice already exists or it’s an Invoice.new, it is passed to the Invoice.build function where it is manipulated.

Now, an Invoice has_many :invoice_items, and inside the function I some of the invoice_items are marked_for_deletion. All is well, and at the end I return the Invoice object originally passed from the controller.

The issue I’m having is that in the controller, after @invoice = Invoice.build(...) I’m retrieving the object I want, but noticed that all @invoice.invoice_items are not marked_for_deletion?.

What would I need to do to persist the marked_for_deletion? across the model and controller?

This build function is used across the app, so I’m really wanting to avoid simply copying/pasting it (it’s a large function) into the controller itself.

Here is the code from the controller:

  def build
    contractor = Contractor.find(invoice_params[:contractor_id])

    # Moved Xero connection checking to view for Turbo, but we still need:
    @company = contractor.client.company

    invoice = Invoice.find_by_invoice_no(invoice_params[:invoice_no])
    invoice = Invoice.new if invoice.blank?

    @invoice = Invoice.build(
      invoice,
      contractor,
      'test',
      invoice_params[:invoice_no],
      invoice_params[:invoice_start_date].blank? ? nil : Date.parse(invoice_params[:invoice_start_date]),
      invoice_params[:invoice_end_date].blank? ? nil : Date.parse(invoice_params[:invoice_end_date]),
      invoice_params[:due_date].blank? ? nil : Date.parse(invoice_params[:due_date]),
      invoice_params[:xero_invoice_id].blank? ? nil : Invoice.find_by_xero_invoice_id(invoice_params[:xero_invoice_id]),
      invoice_params[:invoice_type]
    )
    @invoice.currency = contractor.client.currency_code
    @invoice.status = 'DRAFT'
    
    puts '-----------------> Scanning for @invoice.invoice_items where marked_for_destruction? :'
    @invoice.invoice_items.each do |invoice_item|
      puts "-----------------> InvoiceItem #{invoice_item.id} : #{invoice_item.marked_for_destruction?}"
    end

    respond_to do |format|
      format.html
      format.turbo_stream
    end
  end

I posted too soon. It turns out I was using a where call which creates new objects from the database call, so I wasn’t returning the same objects in the function.