К сожалению, я решил, что это невозможно сделать без использования execute
.
Почему это не работает
Изучив источник ActiveRecord, мы можем найти код для 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
Таким образом, мы видим, что при попытке указать первичный ключ в параметрах 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);"
И как Шон МакКлири упомянул , ваша модель ActiveRecord должна установить первичный ключ, используя set_primary_key
:
class Employee < ActiveRecord::Base
set_primary_key :emp_id
...
end