不幸的是,我已经确定没有使用execute
是不可能的。
为什么不起作用
通过查看ActiveRecord源代码,我们可以找到create_table
的代码:
在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
我们可以看到,在
create_table
选项中尝试指定主键时,它将创建一个指定名称的主键(如果未指定,则为
id
)。它通过调用你可以在表定义块中使用的相同方法来实现:
primary_key
。
在
schema_statements.rb
中:
def primary_key(name)
column(name, :primary_key)
end
这只是创建了一个指定名称的列,类型为:primary_key
。在标准数据库适配器中,设置如下:
PostgreSQL: "serial primary key"
MySQL: "int(11) DEFAULT NULL auto_increment PRIMARY KEY"
SQLite: "INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL"
解决方法
由于我们只能使用这些作为主键类型,因此我们必须使用execute
来创建一个非整数的主键(PostgreSQL的serial
是使用序列的整数):
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);"
正如Sean McCleary所提到的,你的ActiveRecord模型应该使用set_primary_key
来设置主键:
class Employee < ActiveRecord::Base
set_primary_key :emp_id
...
end
rake db:migrate
后表约束设置正确,但自动生成的模式定义不包含此约束! - pymkin