Copying items in Rails applications

When working with large amounts of data and with complex or detailed forms, there is often a need to bulk add new and similar items and trying to remember all the values to be included can be taxing to say the least.

What would be nice is an option on the page to copy an item and be able to edit the details for the specific instance.

This is fairly simple in Rails. The example below is for the applications resource

Create a new route in config/routes.rb

 resources :applications do
  member do
    get 'copy' => 'applications#create_from_existing'
    post 'copy' => 'applications#create_from_existing'
  end
end

This will capture any ‘copy’ action requests and forward them to a new ‘create_from_existing’ action in the applications controller. Including GET and POST  allows the use of link_to and button_to helpers in the views.

Then, create the ‘create_from_existing’ controller action,

  def create_from_existing
    @existing_app = Application.find(params[:id])
    #create new object with attributes of existing record
    @application = @existing_app.dup
    render :new
  end

This simply creates an ActiveRecord duplicate of the item to be copied and renders it with the (already defined) ‘new’ action.

Finally, we create links to the copy action in our views using helpers like,

<%= link_to image_tag("copy-icon.png", :size => "22x17", :title => "Copy item"), copy_application_path %></td>
<%= link_to 'copy', copy_application_path(@application) %>
<%= button_to 'copy', copy_application_path(@application), :class => "button" %>

The only thing to watch out for when editing the copied item is that the button at the bottom of the form says ‘ Create …’ rather than update; on submission the id of the item being displayed should be that of a new record.

References:

 

2 thoughts on “Copying items in Rails applications

  1. julianrawcliffe Post author

    One point to note here is that has and belongs to many type associations are not included in the copy, but a wee bit of extra work in the controller action should be able to sort that. A follow up post should be able to capture that detail.

    Reply
  2. julianrawcliffe Post author

    In my application, I can simply add something like:

    @application.host_ids = @existing_app.host_ids
    @application.app_user_ids = @existing_app.app_user_ids
    to the controller because I know all the associations I want to capture. I have spent some time looking into reflections with ActiveRecord (using rails c) and while there are a couple of gems to help with this, which I don’t want to use, there doesn’t seem to be much discussion and the documentation isn’t very helpful so I will leave it for now.

    Reply

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.