Reputation: 26264
How do I clone a single attribute in a Rails model? This didn't work:
irb(main):309:0> u.reload
=> #<User id: 1, username: "starrychloe", ...
irb(main):310:0> u2 = u.dup
=> #<User id: nil, username: "starrychloe", ...
irb(main):311:0> u2 = u.clone
=> #<User id: 1, username: "starrychloe", ...
irb(main):312:0> u2.username = u.username.clone
=> "starrychloe"
irb(main):313:0> u2.username = 'star'
=> "star"
irb(main):314:0> u.username ############ Changes original
=> "star"
Neither did this:
irb(main):320:0> u.reload
=> #<User id: 1, username: "starrychloe", ...
irb(main):321:0> u2 = u.clone
=> #<User id: 1, username: "starrychloe", ...
irb(main):322:0> u2[:username] = u[:username].clone
=> "starrychloe"
irb(main):323:0> u2.username = 'cow'
=> "cow"
irb(main):324:0> u.username ############ Changes original
=> "cow"
#dup
doesn't copy the ID, and #clone
on the attribute keeps the reference to the same string. This will not solve my problem.
Upvotes: 2
Views: 4161
Reputation: 26264
I ended up making copies of each of the fields I wanted to keep track of:
@oldUsername = @user.username.clone
User.new
looked promising, but it treated the copy as a new object, when it was an existing model, and output invalid forms to edit the model in the views:
> app.controller.view_context.form_for u2 do end # This is from Rails console
=> "<form accept-charset=\"UTF-8\" action=\"/users\" class=\"new_user\" id=\"new_user_1\" method=\"post\">
So it would attempt to PATCH to /users (from the view), which is invalid, when it should PATCH to /users/1/.
It's unbelievable that Rails won't clone objects correctly. In Java, you could use u2.setProperty( u.getProperty().clone() )
and be sure to have a new object that won't interfere with the old one.
Upvotes: 0
Reputation: 44685
You might wanna look into amoeba gem. https://github.com/rocksolidwebdesign/amoeba
Upvotes: 1
Reputation: 9762
To make a copy of the instance with its attributes and de-reference you can do this:
u2 = u.class.new(u.attributes)
Upvotes: 0
Reputation: 23268
u2 = User.new(u.attributes.merge(username: "cow"))
Also, take a look at this question. It has a lot of interesting info on similar subject: What is the easiest way to duplicate an activerecord record?
Upvotes: 2
Reputation: 18080
Do you want to duplicate an instance or an attribute?
To duplicate an instance, use u2 = u.dup
not u2 = u.clone
.
Upvotes: 1