Rails ActiveRecord dup objects

Rails ActiveRecord supports duplicating objects in order to create new objects. Sometimes we need to create a duplicate copy of ActiveRecord object and update a few attributes and then save as a new record. This can be achieved with ActiveRecord::Core#dup method.

Let’s take an example to understand this. Let’s say we have a model Post as given below.

class Post < ApplicationRecord {
  :id => :integer,
  :title => :string,
  :description => :text,
  :published_at => :datetime
}

Duplicating ActiveRecord object

Now, suppose we need to create a new post copied from some older post and just update published_at attribute of the post and create a new record from the same.

We can use ActiveRecord::Core#dup method for the same.

# Fetching last post just for this example.
post = Post.last

The post has values as given below.

#<Post:0x007f9212a74440> {
               :id => 1,
            :title => "Rails ActiveRecord dup objects",
      :description => "Rails ActiveRecord supports duplicating objects in order to create new objects.",
     :published_at => Tue, 25 Jun 2019 07:19:30 UTC +00:00
}
Calling dup on post object
new_post = post.dup

This will create a new Post without an ID as nil and copy over all the other attributes of post object.

The newly created object will look like as given below.

#<Post:0x007f9212a74440> {
               :id => nil,
            :title => "Rails ActiveRecord dup objects",
      :description => "Rails ActiveRecord supports duplicating objects in order to create new objects.",
     :published_at => Tue, 25 Jun 2019 07:19:30 UTC +00:00
}

As we can see dup has created a new ActiveRecord object by removing value of id attribute.

Points to remember
  • The ActiveRecord::Core#dup is a shallow copy of original object
  • It does not include ActiveRecord associations in a newly created object
  • The new object is treated as a new ActiveRecord model object

ActiveRecord dup vs clone

There is a subtle difference between dup and clone methods. ActiveRecord::Core#clone created a shallow copy. It’s similar to clone in Ruby.

Difference between clone and dup

Whenever value of an attribute in cloned object is changed, it’ll be changed in original object as well.

Let’s use Post object described above to illustrate this.

post = Post.last
#
#<Post:0x007f921d889170> {
               :id => 1,
            :title => "Rails ActiveRecord dup objects",
      :description => "Rails ActiveRecord supports duplicating objects in order to create new objects.",
     :published_at => Tue, 25 Jun 2019 07:19:30 UTC +00:00
}

Now, let’s clone post object as given below.

cloned_post = post.clone
#
#<Post:0x007f921d2c2570> {
               :id => 1,
            :title => "Rails ActiveRecord dup objects",
      :description => "Rails ActiveRecord supports duplicating objects in order to create new objects.",
     :published_at => Tue, 25 Jun 2019 07:19:30 UTC +00:00
}

Now, if we check object_id of objects post and cloned_post are difference. If we change title attribute of cloned_post, it will be changed in in post object as well.

cloned_post.title = "Some New Title for the blog post"
# post object will have following values now
#<Post:0x007f921d2c2570> {
               :id => 1,
            :title => "Some New Title for the blog post",
      :description => "Rails ActiveRecord supports duplicating objects in order to create new objects.",
     :published_at => Tue, 25 Jun 2019 07:19:30 UTC +00:00
}

Let’s print original post object.

cloned_post.title = "Some New Title for the blog post"
# cloned_post object has following values
#<Post:0x007f921d889170> {
               :id => 1,
            :title => "Some New Title for the blog post",
      :description => "Rails ActiveRecord supports duplicating objects in order to create new objects.",
     :published_at => Tue, 25 Jun 2019 07:19:30 UTC +00:00
}

Thus, we should be understand this difference between clone and dup methods on ActiveRecord model objects to use them.

References