つまり、StateとAcquisitionの2つのモデルがあります。州has_many買収。 51レコードの自動インクリメント整数主キーはかなりばかげているように感じました。そこで、StateのモデルをPKに変更しました(Stateは2文字の省略形です。実際の州名は、どこにも保存していません。
class State < ActiveRecord::Base
self.primary_key = "state"
has_many :acquisition_histories
end
問題は、Acquisitionモデルを作成したときに、外部キー列state_idが整数として作成されたことです。より具体的には、スクリプト/生成された移行は次のことを行いました。
class CreateAcquisitions < ActiveRecord::Migration
def self.up
create_table :acquisitions do |t|
t.date :date
t.string :category
t.text :notes
t.references :state
t.timestamps
end
end
end
T.referencesデータ型がintに設定していると仮定しています。問題は、Acquisitionクラスのcreateメソッドが、テーブルの取得のstate_idフィールドに状態の省略形を入れようとしていることです(移行スクリプトで:stateと表示されていても、データベースではstate_idと呼ばれます)。このメソッドは失敗しませんが、state_idフィールドに0を入力し、レコードはエーテルに入ります。
しかし、私はこれが 価値があるよりも多くの問題 あなたが実際にしたい場合に備えて、他の場所でデフォルトに対して作業する余分な努力を考慮すると、そうなるかもしれないことに同意しますあなたが尋ねたことをしなさい:
状態の移行を作成します。
class CreateStatesTable < ActiveRecord::Migration
def change
create_table :states, id: false do |t|
t.string :state, limit: 2
t.string :name
t.index :state, unique: true
end
end
end
州モデル:
class State < ActiveRecord::Base
self.primary_key = :state
end
Rails 3.2以前は、これはset_primary_key = :state
ではなくself.primary_key=
でした。参照: http://guides.rubyonrails.org/3_2_release_notes.html#active -record-deprecations
ここにいる場合は...できるだけ早く離れて次の場所に移動してください: Railsを使用して、主キーを整数型の列にならないように設定するにはどうすればよいですか?
私は主キーとしてUUIDを使用するプロジェクトに取り組んでいますが、正直なところ、絶対に必要であることが確実でない限り、UUIDはお勧めしません。文字列を主キーとして使用するデータベースでは変更せずに機能しないRailsプラグインがたくさんあります。
Rails 5.1では、作成時に主キーのタイプを指定できます。
create_table :states, id: :string do |t|
# ...
end
から ドキュメント :
シンボルを使用して、生成された主キー列のタイプを指定できます。
mkirkの答え は偽の主キーを作成することに注意してください。これは、ActiveRecordに主キーが何であるかを通知する必要がある理由を説明しています。テーブルを調べると、
Table "public.acquisitions"
Column | Type | Modifiers
--------+----------------------+-----------
state | character varying(2) |
name | character varying |
Indexes:
"index_acquisitions_on_state" UNIQUE, btree (state)
実際には、これは期待どおりに機能するので、問題はありませんが、もっと良いかもしれません。
id
列を保持し、そのタイプをstring
*に変更できます。移行は次のようになります
class CreateAcquisitionsTable < ActiveRecord::Migration
def change
create_table :acquisitions do |t|
t.string :name
end
change_column :acquisitions, :id, :string, limit: 2
end
end
テーブルを調べると、null制約ではなく、一意キー制約(一意のインデックスは不要)、自動インクリメントキーなど、すべての機能を備えた実際の主キーがあることがわかります。
Table "public.acquisitions"
Column | Type | Modifiers
--------+----------------------+---------------------------------------------------
id | character varying(2) | not null default nextval('acquisitions_id_seq'::regclass)
name | character varying |
Indexes:
"acquisitions_pkey" PRIMARY KEY, btree (id)
そしてプライマリが何であるかをActiveRecordに明示的に伝える必要はありません。
何も指定されていない場合は、デフォルトIDの設定を検討することをお勧めします。
class MyModel < ActiveRecord::Base
before_create do
self.id = SecureRandom.uuid unless self.id
end
end
*免責事項:正当な理由がない限り、デフォルトの主キーを変更しないでください。
Railsの規則に従う必要があります。追加の主キーは、まったく問題ではありません。使用するだけです。
class CreateAcquisitions < ActiveRecord::Migration
def self.up
create_table :acquisitions, :id => false do |t|
t.date :date
t.string :category
t.text :notes
t.references :state
t.timestamps
end
end
end
私は主キーとして使用される文字列を少し経験しましたが、それは***の苦痛です。デフォルトでは、デフォルトの:controller /:action /:idパターンでオブジェクトを渡したい場合、:idは文字列になり、一部のIDが奇妙な形式になると、ルーティングの問題が発生する可能性があることに注意してください;)