How to change the primary key value of a table

Hello,

    I am having problem changing the primary key value of a table using active record. I want to change the id of OriginalName from 2 to 6.

orders table:

Hello,

   I am having problem changing the primary key value of a table using active record. I want to change the id of OriginalName from 2 to 6.

Rails won't do that for you like that. Order.update_all would probably
handle it. (maybe Order.update too)

Fred

I think I might have the answer.

I believe the problem you are having is "when" you are changing the ID value. I had to deal not long ago with the same problems you're facing.

In order to make it work I had to add a 'before_save' method in the model:

def before_save     self.id = new_value_here end

AR will disregard the changes you make to the ID value, probably because it needs the original one for validations, etc. However, when it is ready to save the data to the table (and the 'before_save' method can be used) it does not need the ID any longer and is free for you to change it.

I hope this helps.

Excellent. Order.update_all allowed me to change the primary key value, thanks a lot. Order.update doesn't work though, but that's alright :slight_smile:

Thanks for your input, but I couldn't get your method to work, perhaps I was doing it wrong. I added the following to the Order model:

def before_save(new_value)     self.id = new_value end

Then, I fired up script/console. typed the following: order = Order.find(2) order.before_save(6) order.save

After which an error would occur:

ArgumentError: wrong number of arguments (0 for 1)         from C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/ activerecord-1.15.2/lib /active_record/callbacks.rb:348:in `before_save'         from C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/ activerecord-1.15.2/lib /active_record/callbacks.rb:348:in `send'         from C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/ activerecord-1.15.2/lib /active_record/callbacks.rb:348:in `callback'         from C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/ activerecord-1.15.2/lib /active_record/callbacks.rb:241:in `create_or_update'         from C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/ activerecord-1.15.2/lib /active_record/base.rb:1552:in `save_without_validation!'         from C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/ activerecord-1.15.2/lib /active_record/validations.rb:762:in `save_without_transactions!'         from C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/ activerecord-1.15.2/lib /active_record/transactions.rb:133:in `save!'         from C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/ activerecord-1.15.2/lib /active_record/connection_adapters/abstract/database_statements.rb: 59:in `transa ction'         from C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/ activerecord-1.15.2/lib /active_record/transactions.rb:95:in `transaction'         from C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/ activerecord-1.15.2/lib /active_record/transactions.rb:121:in `transaction'         from C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/ activerecord-1.15.2/lib /active_record/transactions.rb:133:in `save!'         from (irb):20

Hello again.

The reason why the method would not work is because the method is a 'callback' method. I don't believe it accepts parameters.

A callback method is automatically called by Rails when you call the 'save' method (order.save in this case). This callback method, if declared, is called for you by Rails before the record is actually saved to the DB:

you do:   order.save

Rails does:   order.before_save   then it saves the record

You would need to have a way of knowing the new value for ID from within before_save, like storing it in an instance variable before you invoke order.save:

in your code:   order.new_value = 6   order.save

def before_save   self.id = self.new_value end

Although you already got the problem solved I would still try this. It might help in the future. Good luck.

Pepe