44

I have a model Foo with attributes id, name, location. I have an instance of Foo:

f1 = Foo.new
f1.name = "Bar"
f1.location = "Foo York"
f1.save

I would like to copy f1 and from that copy, create another instance of the Foo model, but I don't want f1.id to carry over to f2.id (I don't want to explicitly assign that, I want the db to handle it, as it should).

Is there a simple way to do this, other than manually copying each attribute? Any built in functions or would writing one be the best route?

Thanks

user94154
  • 16,176
  • 20
  • 77
  • 116
  • Thus far I have created a method .copy for the specific model, ie: f2 = f1.copy f2.name = "Baz" f2.save still trying different solutions – user94154 Aug 11 '09 at 20:10

5 Answers5

80

As per the following question, if you are using Rails >= 3.1, you can use object.dup :

What is the easiest way to duplicate an activerecord record?

Community
  • 1
  • 1
mydoghasworms
  • 18,233
  • 11
  • 61
  • 95
62

This is what ActiveRecord::Base#clone method is for:

@bar = @foo.clone

@bar.save
Martijn Courteaux
  • 67,591
  • 47
  • 198
  • 287
Vitaly Kushner
  • 9,247
  • 8
  • 33
  • 41
  • 92
    Use @foo.dup now for rails 3.1 and on. Clone copies the id. – Ultimation Oct 01 '12 at 16:10
  • 1
    Note that both `@foo.dup` and `@foo.clone` only perform shallow copies, and will still contain reference to other objects when copying into more complex variables. – kylegill Jun 04 '18 at 14:42
  • Nowadays, this is the wrong answer. `clone` uses the same attributes as the original. If the attributes of the clone are changed, the original changes as well. Use `dup` instead. – nyi Jul 18 '23 at 18:35
3

You can make duplicate record in rails like

@bar = @foo.dup
@bar.save!
Foram
  • 483
  • 5
  • 12
2

a wrong way to do this would be:

f2 = Foo.new( f1.attributes )     # wrong!
f2.save                           # wrong!

or in one line, but still wrong:

f2 = Foo.create( f1.attributes )  # wrong!

see comments for details

bjelli
  • 9,752
  • 4
  • 35
  • 50
  • 7
    THIS WILL NOT WORK! all attributes that are not in attr_accessible, or are in attr_protected will be lost! or if you are using one of the attribute protection plugins will result in an exception thrown! – Vitaly Kushner May 02 '10 at 21:12
  • 3
    Not only that, all the ids are still the same, so save will just do an update – txwikinger Feb 29 '12 at 20:31
-2

You could use the built-in attributes methods that rails provides. E.g.

f2 = Foo.new(f1.attributes)

or

f2 = Foo.new
f2.attributes = f1.attributes
Shadwell
  • 34,314
  • 14
  • 94
  • 99
  • This is not the right way. The Primary Key of `f1` will get copied over to `f2`. – Zabba Jan 13 '11 at 00:55
  • 1
    No, it won't. The primary key is not included in attributes assigned in this way in a similar way to any attr_protected attributes. – Shadwell Jan 13 '11 at 17:02
  • For me in Rails 3.1, it seems clone does copy the id across. But dup does not. – Kris Nov 30 '11 at 11:37