Rails 2.3.4 migrations: rename_column on primary key results in wailing, gnashing of teeth

Howdy folks

I recently updated one of our apps to Rails 2.3.4 from 2.1.2. The
following migrations, which worked previously, now fail:

Migration 1:

class CreateInitialSchema < ActiveRecord::Migration
self.up
create_table :states, :id => false do |t|
t.column :state_code, :integer
t.column :state_name, :string
end
add_index “states”, “state_code”, :name =>
“index_state_by_code”, :unique => true
add_index “states”, “state_name”, :name =>
“index_state_by_name”, :unique => true
State.create(:state_code => 0, :state_name => ‘Antarctica’)
…etc…

Migration 2:

class State < ActiveRecord::Base; set_primary_key “state_digit”; end
class AddStateCode < ActiveRecord::Migration
self.up
rename_column :states, :state_code, :state_digit
add_column :states, :state_code, :string, :limit => 3
State.reset_column_information
State.find(:all).each do |s|
s.state_code =
case s.state_digit.to_i
when 0; “ANT”
…edit…
else raise “No such state #{s.state_digit}”
end
s.save!
end
…etc…

Migration 3:

class State < ActiveRecord::Base; set_primary_key “state_digit”; end
class RemoveUnusedStates < ActiveRecord::Migration
self.up
State.find_by_state_name(“Antarctica”).destroy
State.find_by_state_name(“External Territories”).destroy
…etc…

It would seem the problem is in migration 2. Renaming the primary key
column and adding a new column with the name of the previous primary
key causes problems in the model which the call to
reset_column_information can’t resolve. In migration 2 and 3,
state_digit is always nil for all records.

Because migration 3 was also failing I take it that Rails caches
classes between migrations?

I don’t what changed from Rails 2.1.2 and 2.3.4 to break these
migrations. If anyone’s encountered this issue or can shed some light
on the problem it would give me some peace of mind.

I worked around the problem by dynamically creating and destroying
classes to access the state table each time I need them, but I’d much
rather understand the root cause of the problem and fix it if needed.

Cheers
Nick

I don’t what changed from Rails 2.1.2 and 2.3.4 to break these
migrations. If anyone’s encountered this issue or can shed some light
on the problem it would give me some peace of mind.

I worked around the problem by dynamically creating and destroying
classes to access the state table each time I need them, but I’d much
rather understand the root cause of the problem and fix it if needed.

The core issue is that the right way to do this is to do

class SomeMigration < ActiveRecord::Migration
class State < ActiveRecord::Base
end
end

Like that each migration has its own copy of the class, no
interfering. The big difference between 2.1.2 and later versions is
probably that by default in production modes all classes are loaded up
front, so in migrations 2 & 3 you are not creating a new state class -
you’re reopening the application’s state class which could easily have
validations, callbacks etc. and be confused by the fact that the
columns aren’t as expected. Last but not least, running all the
migrations from the first to the last is not the reccomended way to
deploy an app - you should be loading the schema file.

Fred

Hey Fred

Thanks for the reply. So the scope of the State model definition in
each class is causing the problem. That makes sense… I’ll try moving
them and see if that fixes the problem more cleanly.

I understand that running the migrations end to end isn’t recommended
but the application is what it is and because the migrations were
written prior to seed.rb being introduced, there’s quite a bit of data
manipulation going on in there leaving me no choice but to re-create
the database this way. Live and learn, eh.

N.

On Oct 23, 6:51 pm, Frederick C. [email protected]

Nick T. wrote:

Hey Fred

[…]

I understand that running the migrations end to end isn’t recommended

It’s pretty much a Certified Bad Idea.

but the application is what it is and because the migrations were
written prior to seed.rb being introduced, there’s quite a bit of data
manipulation going on in there leaving me no choice but to re-create
the database this way.

Couldn’t you just do rake db:schema:load and then seed the DB?

Live and learn, eh.

N.

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]