Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails clone copy or duplicate

I have a nested form and once I save, I want to be able to click a link on the show page to copy or clone that form and open a new one. From there I should be able to make edits (like a new id) and save as a new record. I have seen some examples like this deep_cloneable gem, but I have no idea how to implement it. I think this should be simple, but I just don't understand where to put things in the controller and in the show view.

like image 565
FattRyan Avatar asked Apr 19 '11 04:04

FattRyan


People also ask

What is the difference between object DUP and #clone?

In general, clone and dup may have different semantics in descendant classes. While clone is used to duplicate an object, including its internal state, dup typically uses the class of the descendant object to create the new instance. When using dup, any modules that the object has been extended with will not be copied.

How do you duplicate a record in rails?

You generally use #clone if you want to copy an object including its internal state. This is what Rails is using with its #dup method on ActiveRecord. It uses #dup to allow you to duplicate a record without its "internal" state (id and timestamps), and leaves #clone up to Ruby to implement.

How do you clone an object in Ruby?

Ruby does provide two methods for making copies of objects, including one that can be made to do deep copies. The Object#dup method will make a shallow copy of an object. To achieve this, the dup method will call the initialize_copy method of that class. What this does exactly is dependent on the class.


1 Answers

I found these answers a little hard to follow. One answer shows this:

@post = Post.new(@existing_post.attributes)

which will not work as it will also pass the id, and timestamp values. I used .dup to fix that and I show that in my answer.

Here's how I achieved creating a new item from an existing item.

The model is for a Product, the controller Products_Controller.rb. We're going to add a new action to the controller called copy and we're going to link to it from the show view on an existing Product and render a filled out new view ready to be edited and saved.

First we create a route for the copy action in routes.rb

# Routes.rb
resources :Products do
  member do
    get 'copy'
  end
end

Then a copy action in Products_controller.rb

 # ProductController.rb
 def copy
   @source = Product.find(params[:id])
   @product = @source.dup
   render 'new'
 end

Now we need to add a Link to the show view to call our copy action.

# show.html.erb
<%= link_to "copy", copy_product_path(params[:id]) %>

Rails 4-6 Update:

The strong parameter scaffold makes it even shorter:

# ProductController.rb
# GET /products/1/copy
def copy
  @product = @product.dup
  render :new
end

And in the erb template:

# show.html.erb
<%= link_to "copy", copy_product_path(@product) %>
like image 65
Patrick Avatar answered Sep 21 '22 16:09

Patrick