次の2つのモデルがあります。
class Store < ActiveRecord::Base
belongs_to :person
end
class Person < ActiveRecord::Base
has_one :store
end
ここに問題があります:移行を作成して、peopleテーブル内に外部キーを作成しようとしています。ただし、Storeの外部キーを参照する列の名前はstore_idではなく、Railsコンベンションですが、代わりに名前付きfoo_bar_store_id.
Railsの規則に従っていれば、次のように移行します。
class AddReferencesToPeople < ActiveRecord::Migration
def change
add_reference :people, :store, index: true
end
end
ただし、列名はstore_idではなく、foo_bar_store_idそれでは、外部キー名が異なるだけで、インデックスを維持するように指定するにはどうすればよいですか?高速なパフォーマンスを維持するためにtrueですか?
編集:目盛りが表示され、読み続けない人のために!
この答えは、インデックスを使用して、型にはまらない外部キー列名を持つという目標を達成しますが、データベースにfk制約を追加しません。 add_foreign_key
や 'add_reference'を使用したより適切なソリューションについては、他の回答を参照してください。
注:常に他の答えを見て、受け入れられたものが常に最良とは限りません!
元の回答:
AddReferencesToPeople
移行では、次を使用してフィールドとインデックスを手動で追加できます。
add_column :people, :foo_bar_store_id, :integer
add_index :people, :foo_bar_store_id
そして、次のようにモデルに外部キーを知らせます。
class Person < ActiveRecord::Base
has_one :store, foreign_key: 'foo_bar_store_id'
end
Rails 4.2では、カスタム外部キー名を使用してモデルまたは移行をセットアップすることもできます。例では、移行は次のようになります。
class AddReferencesToPeople < ActiveRecord::Migration
def change
add_column :people, :foo_bar_store_id, :integer, index: true
add_foreign_key :people, :stores, column: :foo_bar_store_id
end
end
ここ は、このトピックに関する興味深いブログ投稿です。 ここ はRails Guides。の半暗号セクションです。ブログ投稿は間違いなく私を助けてくれました。
アソシエーションについては、外部キーまたはクラス名を次のように明示的に記述します( 'belongs_to'が外部キーを持つクラスに移動すると、元のアソシエーションが切り替えられたと思います)。
class Store < ActiveRecord::Base
has_one :person, foreign_key: :foo_bar_store_id
end
class Person < ActiveRecord::Base
belongs_to :foo_bar_store, class_name: 'Store'
end
Class_nameアイテムは文字列でなければならないことに注意してください。 foreign_keyアイテムは、文字列またはシンボルのいずれかです。これにより、次のように、意味的に名前が付けられた関連付けを使用して、気の利いたActiveRecordショートカットにアクセスできます。
person = Person.first
person.foo_bar_store
# returns the instance of store equal to person's foo_bar_store_id
belongs_to および has_one のドキュメントで関連付けオプションの詳細を参照してください。
in Rails 5.xでは、次のような別の名前でテーブルに外部キーを追加できます。
class AddFooBarStoreToPeople < ActiveRecord::Migration[5.0]
def change
add_reference :people, :foo_bar_store, foreign_key: { to_table: :stores }
end
end
# Migration
change_table :people do |t|
t.references :foo_bar_store, references: :store #-> foo_bar_store_id
end
# Model
# app/models/person.rb
class Person < ActiveRecord::Base
has_one :foo_bar_store, class_name: "Store"
end
Schpetの答えを拡張するために、これはcreate_table
Rails 5移行ディレクティブは次のようになります。
create_table :chapter do |t|
t.references :novel, foreign_key: {to_table: :books}
t.timestamps
end
カバーの下では、add_referenceはadd_columnとadd_indexに委任するだけなので、自分で処理する必要があります。
add_column :people, :foo_bar_store_id, :integer
add_index :people, :foo_bar_store_id