1

In my Rails app I have an invoices_controller.rb with these actions:

def new
  @invoice = current_user.invoices.build(:project_id => params[:project_id])
  @invoice.build_item(current_user)
  @invoice.set_number(current_user)
end

def create
  @invoice = current_user.invoices.build(params[:invoice])    
  if @invoice.save
    flash[:success] = "Invoice created."
    redirect_to edit_invoice_path(@invoice)
  else
    render :new
  end
end

Essentially, the new method instantiates a new invoice record plus one associated item record.

Now, what sort of method do I need if I want to duplicate an existing invoice?

I am a big fan of Rails's RESTful approach, so I wonder if I should add a new method like

def duplicate

end

or if I can use the existing new method and pass in the values of the invoice to be duplicated there?

What is the best approach and what might that method look like?

4

3 回答 3

2

Naturally, you can extend RESTful routes and controllers.

To be rally RESTful, it is important to look exactly, what you want.

i.e. if you want a new invoice and use an existing one as a kind of template, then it is comparable to a new action, and the verb should be GET (get the input form). As is it based on an existing invoice, it should reference that object. After that you would create the new invoice in the usual way.

So in you routes:

resources :invoices do
  member do
    get 'duplicate'
  end
end

giving you a route duplicate_invoice GET /invoices/:id/duplicate(.format) invoices#duplicate

So in your view you can say

<%= link_to 'duplicate this', duplicate_invoice_path(@invoice) %>

and in your controller

def duplicate
  template = Invoice.find(params[:id])
  @invoice= template.duplicate # define in Invoice.duplicate how to create a dup
  render action: 'new'
end
于 2013-06-09T11:33:19.157 回答
1

If I understand correctly your question you can:

resources :invoices do
  collection do
    get 'duplicate'
  end
end

and with this you can do:

def duplicate
  # @invoice = [get the invoice]
  @invoice.clone_invoice
  render 'edit' # or 'new', depends on your needs
end

clone_invoice could be a custom method which should have a invoice.clone call in your custom method.

于 2013-06-09T11:06:04.580 回答
1

If you question if you can use additional methods except REST, you absolutely can. Google, for example, encourage developers to use something, what they call "extended RESTful" on GoogleIO, http://www.youtube.com/watch?v=nyu5ZxGUfgs

So use additional method duplicate, but don't forget about "Thin controllers, fat models" approach to incapsulate your duplicating logic inside model.

于 2013-06-09T11:17:53.247 回答