Assuming fairly recent version of Rails you can always run:
rake db:migrate:up VERSION=20090408054532
Where version is the timestamp in the filename of the migration.
Edit: At some point over the last 8 years (I'm not sure what version) Rails added checks that prevent this from running if it has already been run. This is indicated by an entry in the schema_migrations
table. To re-run it, simply execute rake db:migrate:redo VERSION=20090408054532
instead.
Unfortunately, I've determined it's not possible to do it without using execute
.
Why it doesn't work
By examining the ActiveRecord source, we can find the code for create_table
:
In schema_statements.rb
:
def create_table(table_name, options={})
...
table_definition.primary_key(options[:primary_key] || Base.get_primary_key(table_name.to_s.singularize)) unless options[:id] == false
...
end
So we can see that when you try to specify a primary key in the create_table
options, it creates a primary key with that specified name (or, if none is specified, id
). It does this by calling the same method you can use inside a table definition block: primary_key
.
In schema_statements.rb
:
def primary_key(name)
column(name, :primary_key)
end
This just creates a column with the specified name of type :primary_key
. This is set to the following in the standard database adapters:
PostgreSQL: "serial primary key"
MySQL: "int(11) DEFAULT NULL auto_increment PRIMARY KEY"
SQLite: "INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL"
The workaround
Since we're stuck with these as the primary key types, we have to use execute
to create a primary key that is not an integer (PostgreSQL's serial
is an integer using a sequence):
create_table :employees, {:id => false} do |t|
t.string :emp_id
t.string :first_name
t.string :last_name
end
execute "ALTER TABLE employees ADD PRIMARY KEY (emp_id);"
And as Sean McCleary mentioned, your ActiveRecord model should set the primary key using set_primary_key
:
class Employee < ActiveRecord::Base
set_primary_key :emp_id
...
end
Best Answer
Default migration generator does not handle default values (column modifiers are supported but do not include
default
ornull
), but you could create your own generator.You can also manually update the migration file prior to running
rake db:migrate
by adding the options toadd_column
:add_column :tweet, :retweets_count, :integer, :null => false, :default => 0
... and read Rails API