Question
I want to duplicate an ActiveRecord object in Ruby on Rails while changing one field during the copy process. The new record should have a different id, and I may want to update another attribute before saving it.
I know I could create a new record manually and copy each field one by one, but I assume there is a simpler Rails way to do this.
For example, I am looking for something conceptually like:
new_record = Record.copy(:id)
What is the easiest and most idiomatic way to duplicate an ActiveRecord record?
Short Answer
By the end of this page, you will understand how Rails duplicates ActiveRecord objects, when to use dup, what gets copied and what does not, and how to safely modify attributes before saving the new record.
Concept
In Ruby on Rails, the usual way to duplicate an ActiveRecord model instance is to use dup.
new_record = old_record.dup
This creates a new model object with the same attribute values as the original, but it is treated as a new record. That means Rails does not keep the original primary key value, so when you save the duplicate, it gets a new id.
Example:
new_post = post.dup
new_post.title = "Copied: #{post.title}"
new_post.save!
Why this matters:
- It avoids manually assigning every column.
- It is the idiomatic Rails approach for copying a record.
- It makes cloning data safer and faster in real projects.
Important detail: dup copies the model's attributes, but it does not automatically duplicate associated records such as has_many children. If you need a deep copy, you usually handle associations separately.
In practice, dup is most useful when:
- creating a template-based record
- copying drafts
- reusing existing configuration
- cloning a row with only a few changed fields
Mental Model
Think of an ActiveRecord object like a filled-out form.
- The original record is the submitted form already stored in the database.
dupgives you a fresh blank submission that is pre-filled with the same answers.- The record looks similar, but it is not the same database row.
- When you save it, Rails stores it as a new row with a new
id.
So dup is like saying: give me the same data, but as a new record I can edit and save separately.
Syntax and Examples
The basic syntax is:
copy = original.dup
Then you can change any attributes before saving:
copy = original.dup
copy.name = "New Name"
copy.save!
Example
Suppose you have a Product model:
product = Product.find(1)
Duplicate it:
new_product = product.dup
new_product.name = "#{product.name} (Copy)"
new_product.save!
What happens here
product.dupcopies the attribute valuesnew_productis marked as a new unsaved recordidis not copied as a usable database identity- changing
nameonly affects the new object save!inserts a new row into the database
Common pattern
copied_user = user.dup
copied_user.email =
copied_user.save!
Step by Step Execution
Consider this code:
article = Article.find(1)
copy = article.dup
copy.title = "#{article.title} (Copy)"
copy.save!
Step by step:
Article.find(1)loads the existing record from the database.article.dupcreates a newArticleobject with copied attributes.- The new object is not saved yet.
- Its
idis not treated as the original record's primary key. copy.title = ...changes one field on the duplicate.copy.save!inserts a brand new row into the database.
If the original row looked like this:
| id | title | status |
|---|---|---|
| 1 | Intro to API | draft |
After duplication and saving:
Real World Use Cases
Here are common places where record duplication is useful:
- Copying templates: create a new invoice from a saved invoice template.
- Duplicating drafts: make a new blog post based on an old one.
- Reusing configuration: copy app settings, pricing plans, or workflow rules.
- Cloning catalog items: duplicate a product and change only the SKU or name.
- Admin tools: let staff quickly create similar records without re-entering all fields.
Example in an admin panel:
new_plan = existing_plan.dup
new_plan.name = "Pro Plan 2026"
new_plan.save!
This saves time and reduces manual input mistakes.
Real Codebase Usage
In real Rails codebases, developers often use dup together with validation, guard clauses, and attribute cleanup.
Pattern: duplicate and adjust unique fields
copy = post.dup
copy.slug = nil
copy.title = "#{post.title} Copy"
copy.save!
This is common when fields like slug must be regenerated.
Pattern: guard clause before copying
return unless post.published?
copy = post.dup
copy.status = "draft"
copy.save!
This prevents invalid duplication based on business rules.
Pattern: service object
In larger applications, duplication logic is often moved into a service:
class DuplicateProduct
def self.call(product)
copy = product.dup
copy.name = "#{product.name} Copy"
copy.sku = nil
copy.save!
copy
end
end
This keeps controllers and models cleaner.
Pattern: duplicate associations manually
If a record has child rows, developers usually duplicate them explicitly:
Common Mistakes
1. Forgetting to save the duplicate
Broken example:
copy = product.dup
copy.name = "Copy"
This creates the object in memory, but nothing is written to the database until you call save or save!.
Fix:
copy = product.dup
copy.name = "Copy"
copy.save!
2. Expecting associations to be copied automatically
Broken assumption:
new_order = order.dup
new_order.save!
This does not copy line_items, comments, or other related records.
Fix: duplicate associations manually when needed.
3. Forgetting unique validations
Broken example:
copy = user.dup
copy.save!
If email must be unique, this may fail validation.
Fix:
copy = user.dup
copy.email = "new@example.com"
copy.save!
Comparisons
| Approach | What it does | When to use it | Notes |
|---|---|---|---|
record.dup | Copies attributes into a new unsaved record | Standard record duplication | Most idiomatic Rails approach |
| Manual assignment | Builds a new object field by field | When only a few fields are needed | More verbose but very explicit |
clone | Copies the object more literally in Ruby | Rarely used for ActiveRecord duplication | Usually not the preferred Rails choice |
new(attributes) | Creates a new record from selected attributes | When you want full control | Useful if you want to exclude many fields |
dup vs manual copying
Cheat Sheet
Quick reference
copy = record.dup
copy.some_field = "New value"
copy.save!
Key points
dupcreates a new unsaved ActiveRecord object- the duplicate gets a new
idwhen saved - change attributes before saving
- associations are not deep-copied automatically
- unique fields may need to be changed manually
Typical pattern
copy = original.dup
copy.name = "#{original.name} Copy"
copy.slug = nil
copy.save!
Use save vs save!
savereturnstrueorfalsesave!raises an exception if validation fails
Watch out for
- uniqueness validations
- child associations not being copied
- accidentally editing the original object instead of the duplicate
FAQ
What is the easiest way to duplicate an ActiveRecord record?
Use dup:
copy = record.dup
Then update fields and save it.
Does dup copy the id?
No. The duplicate is treated as a new record and gets a new id when saved.
Does dup copy associated records too?
No. It copies the model's own attributes, not related has_many or similar associations.
Why does saving a duplicated record sometimes fail?
Usually because of validations, especially uniqueness validations on fields like email, slug, or sku.
Should I use dup or clone in Rails?
For duplicating ActiveRecord records, dup is the normal and recommended approach.
Can I change attributes before saving the copy?
Yes. That is one of the main reasons to use .
Mini Project
Description
Build a small Rails-style example that duplicates a blog post, changes its title, resets a unique slug, and saves the new record. This demonstrates the most common real-world pattern for copying existing data into a new database row.
Goal
Create a safe duplicate of an existing ActiveRecord record while updating selected fields before saving.
Requirements
- Find an existing record by ID
- Duplicate it using the Rails idiomatic approach
- Change at least one normal field such as
title - Reset one field that may need to be unique, such as
slug - Save the copied record as a new database row
Keep learning
Related questions
Calling an Overridden Monkey-Patched Method in Ruby
Learn how to call the original method when monkey patching in Ruby, including alias_method patterns, examples, pitfalls, and practical usage.
Difference Between require and include in Ruby
Learn the difference between require and include in Ruby, when to load a file, and when to mix module methods into a class.
Fixing Ruby Gem Native Extension Errors: mkmf.rb Can't Find Header Files for Ruby
Learn why Ruby gem installs fail with missing ruby.h, how native extensions work, and how to fix header file errors on Linux servers.