Unfortunately, I decided that this cannot be done without using execute .
Why it does not work
After examining the source of ActiveRecord, 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 see that when we try to specify the primary key in the create_table parameters, it creates a primary key with the specified name (or, if none is specified, id ). He does this by calling the same method that you can use inside the table definition block: primary_key .
In schema_statements.rb :
def primary_key(name) column(name, :primary_key) end
This simply creates a column with the specified type name :primary_key . The following are installed on standard database adapters:
PostgreSQL: "serial primary key" MySQL: "int(11) DEFAULT NULL auto_increment PRIMARY KEY" SQLite: "INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL"
Workaround
Since we are obsessed with them as primary key types, we must use execute to create a primary key that is not an integer (PostgreSQL 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 McCleery noted , your ActiveRecord model should set the primary key using set_primary_key :
class Employee < ActiveRecord::Base set_primary_key :emp_id ... end
Rudd Zwolinski Sep 16 '09 at 18:52 2009-09-16 18:52
source share