1. ホーム
  2. ruby-on-rails

[解決済み] Railsで、主キーが整数型でないカラムを設定するには?

2023-05-04 23:29:27

質問

Railsのmigrationsを使ってデータベーススキーマを管理しているのですが、主キーとして非整数の値(特に文字列)を使いたい簡単なテーブルを作成しています。私の問題から抽象化するために、例えばテーブル employees というテーブルがあり、従業員は英数字の文字列で識別されているとします。 "134SNW" .

こんな感じでマイグレーションでテーブルを作成してみました。

create_table :employees, {:primary_key => :emp_id} do |t|
    t.string :emp_id
    t.string :first_name
    t.string :last_name
end

この結果、完全に無視されたように見えるのが t.string :emp_id の行を完全に無視し、先に進んでそれを整数カラムにしたようなものです。PRIMARY_KEY制約(PostgreSQLを使用しています)をrailsに生成させる他の方法はないでしょうか。 execute の呼び出しでSQLを書く必要はありません。

ノート : 私は文字列カラムを主キーとして使用するのが最善ではないことを知っています。私はいずれにせよ1つを追加するかもしれませんが、この質問はまだ有効です。

どのように解決するのですか?

残念ながら、私が判断したところでは 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);"

そして ショーン・マクレアリー氏が言及 を使用して主キーを設定する必要があります。 set_primary_key :

class Employee < ActiveRecord::Base
  set_primary_key :emp_id
  ...
end