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