7
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

updated at

ActiveRecord 4.1+MySQLで任意のカラムをPKにする

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の定義を生成しているのが以下の箇所:

schema_statements.rb#L190

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

:idfalseでないとき、: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を作成できます。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
7
Help us understand the problem. What are the problem?