views:

291

answers:

2

I need to save a copy of an ActiveRecord object so I'm using something like:

@original = Model.find(params[:id])
@copy = @original.clone

However, when I attempt to save this to Postgres:

PGError: ERROR: null value in column "id" violates not-null constraint

In the console:

@copy.id
=> nil

How do I get ActiveRecord to not send the id column in the INSERT statement?

Update:

The problem went away after I made a small change:

@new = Model.new(params[:model])
@original = Model.find(x)
@clone = @original.clone
@new.foreign_key_id = @clone.foreign_key_id

I replaced the last line with:

@new.foreign_key_id = @original.foreign_key_id

This change removed 'id' from the INSERT statement. After a successful experiment with this change, I immediately reverted the code and attempted to reproduce the error. I have been unable to reproduce the error. Friday the 13th, maybe?

+1  A: 

Just a guess...but is new_record? returning true for the cloned object?

It might be better to create a new model object and set the attributes equal to the old one, like this:

@copy = Model.new
@copy.attributes = @original.attributes
Luke Francl
+3  A: 

You're calling ActiveRecord::Base#clone, not Object#clone. ActiveRecord::Base#clone is essentially creates a new instance of the model, copies the attributes hash and deletes the id key. Essentially doing what Luke Franci Suggests.

I'm sure this is a PostgreSQL problem. Because this code works with MySQL.

@clone = @original.clone
@clone.save

The error your having might have something to do with the way that PostgreSQL handles auto-increment. I can't tell if ActiveRecord is trying to pass the undefined id in the INSERT statement, when it shouldn't be, or if something went wrong with definition.

I don't know enough about postreges to diagnose the problem. But I suspect the root of your problem might be in the migration defining your table.

Out of curiosity what is the result of Model.new(@original.attributes) == @original.clone ?

EmFi
Good call. I didn't realize ActiveRecord overrode Ruby's clone method. This should be totally fine to call.
Luke Francl
The result was false. I updated the question above to include a solution to this problem, but I think I must have done something else somehow to cause this problem because I can't reproduce it. Thank you both for your help!
londonium