1

Possible Duplicate:
ActiveRecord: How can I clone nested associations?

I have a table with invoices which in turn can have many items.

Now in my invoices index view I would like to place a link next to each invoice saying Duplicate Invoice.

Without the child records this would be quite easy:

<%= link_to "Duplicate", new_invoice_path(invoice.attributes) %>

But how can this be done if the invoice's items should be duplicated as well?

As a Rails newbie I can't get my head around this. Can all this be handled by the new action inside my controller?

def new
  @invoice = current_user.invoices.build(:project_id => params[:project_id])
  @title = "New invoice"
end

Or do I need to create another function named e.g. copy inside my controller?

What is the best practice?

Thanks for any input...

Community
  • 1
  • 1
Tintin81
  • 9,821
  • 20
  • 85
  • 178

2 Answers2

8

The logic should go in the model

in invoice.rb:

def deep_dup
  new_invoice = Invoice.create(self.dup.attributes)
  items.each do |item|
    new_invoice.items.create(item.dup.attributes)
  end
  return new_invoice
end

Then in the controller, make an action called duplicate:

def duplicate
  new_invoice = @invoice.deep_dup
  redirect to new_invoice
end
Aaron Perley
  • 629
  • 3
  • 4
0

Maybe something like this in your create action:

def create
  @invoice = Invoice.new(params[:invoice]
   #find duplicate invoice (if exists)
   duplicate_invoice = Invoice.find(params[:duplicate_invoice_id])
   unless duplicate_invoice.nil?
     items = nil
     duplicate_items = duplicate_invoice.items
     duplicate_items.each do |child|
       item = Item.new(child.attributes)
       item.save
       items << item
     end  
   end
   if @invoice.save
     @invoice.items << items #add the duplicate items to the duplicate invoice
     #handle your redirects....
   end
end

Essentially what you can do pass the id of the duplicate invoice to your create action, find the invoice that you intent to duplicate and then process it's children items into an array of duplicate items. The final step is to add those newly duplicated items to your newly duplicated invoice. This is obviously untested and it's going to require a little additional work on your end but I hope you get the gist of the idea. There's probably other ways to accomplish this.

Of course, there are also gems that can do this for you but it's your call.

Noz
  • 6,216
  • 3
  • 47
  • 82