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:

±—±------------------±---------------------------------
±--------------------------------±---------+
| id | name | address |
email | pay_type |
±—±------------------±---------------------------------
±--------------------------------±---------+
| 1 | Reginald | 288 Escolta |
[email protected] | cc |
| 2 | OriginalName | 3421 unkonwn address | [email protected] |
po |
| 3 | Third Eye | 3421 unkonwn address | [email protected]
| po |
±—±-------------------±--------------------------------
±--------------------------------±---------+

What I did was to type the following on ruby script/console:

order=Order.find(2)

   => #<Order:0x4710184 @attributes={"name"=>"OriginalName",

“id”=>“2”, “pay_type”=
>“po”, “address”=>“3421 unkonwn address”,
“email”=>“[email protected]”}>

order.id

   => 2

order.id=6

   => 6

order.save

   => true

Although it displays a true message, there seems to be an error.

order
=> #<Order:0x4709500 @errors=#<ActiveRecord::Errors:0x4705cac
@errors={}, @base=
#<Order:0x4709500 …>>, @new_record_before_save=nil,
@attributes={“name”=>“Orig
inalName”, “id”=>6, “pay_type”=>“po”, “address”=>“3421 unkonwn
address”, “email”
=>“[email protected]”}>

Moreover, when I queried the orders table using mysql, by typing
“select * from orders”, I don’t see any changes.

P.S. I’m using Rails 1.2.2 and MySQL 5.0.27

On 18 Jun 2008, at 10:59, soa_dias wrote:

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.

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:insend’
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:increate_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:insave_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:intransa
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:intransaction’
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

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:

On Jun 18, 6:33 pm, Frederick C. [email protected]

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