ActiveRecord 4.1+MySQLで、特別な拡張を入れなくても任意の名前・型のカラムをPKにできたのでメモしておきます。
書き方
名前だけ変える
primary_key: 'my_id'
create_table "items", primary_key: 'my_id', force: true do |t|
...
end
型だけ変える
id: 'bigint primary key auto_increment'
create_table "items", id: 'bigint primary key auto_increment', force: true do |t|
...
end
名前・型を変える
primary_key: 'my_id', id: 'bigint primary key auto_increment'
create_table "items", primary_key: 'my_id', id: 'bigint primary key auto_increment', force: true do |t|
...
end
ダンプ
ダンプすると名前の情報は出力されますが型の情報(id: xxx
)は出力されません。
create_table "items", primary_key: "my_id", force: true do |t|
...
end
解説
create_table
でPKの定義を生成しているのが以下の箇所:
unless options[:id] == false
pk = options.fetch(:primary_key) {
Base.get_primary_key table_name.to_s.singularize
}
td.primary_key pk, options.fetch(:id, :primary_key), options
end
:id
がfalse
でないとき、:primary_key
の値を名前、:id
の値を型としてPKを定義しています。
MySQLのネイティブな型の定義は以下の通り:
abstract_mysql_adapter.rb#L152
NATIVE_DATABASE_TYPES = {
:primary_key => "int(11) auto_increment PRIMARY KEY",
:string => { :name => "varchar", :limit => 255 },
:text => { :name => "text" },
:integer => { :name => "int", :limit => 4 },
:float => { :name => "float" },
:decimal => { :name => "decimal" },
:datetime => { :name => "datetime" },
:timestamp => { :name => "datetime" },
:time => { :name => "time" },
:date => { :name => "date" },
:binary => { :name => "blob" },
:boolean => { :name => "tinyint", :limit => 1 }
}
実際にSQLを発行するときはtype_to_sqlメソッドでネイティブな型に変換していますが
if native = native_database_types[type.to_sym]
...
else
type.to_s
end
native_database_types
にないものはそのままSQLの型として使われるので、:id
に「任意の型」+primary key
を設定すると、任意の型でPKを作成できます。