johnrbnz
johnrbnz

Reputation: 387

Updating and creating a new instance at the same time

When a user updates an invoice form, i want to create a new invoice record with the updated attributes, but also change one or two fields of the old record and save it, too.

How would the outline of a controller action look like which could accomplish this?

Upvotes: 0

Views: 100

Answers (3)

johnrbnz
johnrbnz

Reputation: 387

Nested attributes made things a bit tricky. So in order to create new instances I had to use the dup method for both the resource and its nested items.

Generally, it is advisable to keep the controllers slim and make the models fat. Nevertheless, I have decided to include this code into my Invoices controller:

def revise_save
  @contact = Contact.find(params[:contact_id])
  @invoice = @contact.invoices.find(params[:invoice_id])
  @invoice_old = @invoice.dup
  @invoice.invoice_items.each do |item|
    @invoice_old.invoice_items << item.dup
  end

  @invoice.datum = DateTime.now.to_date

  # archive old invoice
  # @invoice_old. ...

  @invoice_old.save

  # make old new invoice

  @invoice.datum = Time.now
  # ...
  @invoice.update(invoice_params)

  redirect_to invoices_path 

end

Note that in this solution the currently edited (original) invoice becomes the new invoice, the old one is paradoxically created anew.

Thanks to @iwan-b for pointing me in the right direction.

Upvotes: 0

Maxence
Maxence

Reputation: 2339

I am rather new with Rails but this seems pretty straightforward. As you mention the user is 'updating" an invoice, your controller view has probably been passed all the data available to the user for further change.

When submitting the form, your update action can easily update the current record data, as well as creating a new one on top of this

Though as it is automated, you need to make clear:

  • if a new invoice record is created each time an invoice record is
    updated (thi can create a lot of copies of the same invoice)
  • how you make the old record an archive to avoid duplicates
  • can the 'additional" amendments be automated and easily processed through an algorithm...

Upvotes: 1

Iwan B.
Iwan B.

Reputation: 4166

Instead of a controller action i put the code in the model, using callbacks:

  before_save do |rec|
    if !rec.new_record?
      attrb = rec.attributes.delete_if{|k, v| ["id"].include? k }
      Book.create(attrb)

      rec.restore_attributes
      rec.year = rec.year + 2 # some custom change
      true
    end
  end

I keep all attributes unless the 'id' (otherwise i get an error) for create a new record with the new attributes. Then i restore the attributes of the existing record. I do some custom change before saving.

Upvotes: 1

Related Questions