web-dev-qa-db-ja.com

Rails移行:テーブルへのadd_referenceであるが、外部キーの列名が異なるRails Convention

次の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ですか?

51
Neil

編集:目盛りが表示され、読み続けない人のために!

この答えは、インデックスを使用して、型にはまらない外部キー列名を持つという目標を達成しますが、データベースに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
6
Matt

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 のドキュメントで関連付けオプションの詳細を参照してください。

65
Sia

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
65
schpet
# 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
5
Richard Peck

Schpetの答えを拡張するために、これはcreate_table Rails 5移行ディレクティブは次のようになります。

create_table :chapter do |t|
  t.references :novel, foreign_key: {to_table: :books}
  t.timestamps
end
5
toobulkeh

カバーの下では、add_referenceはadd_columnとadd_indexに委任するだけなので、自分で処理する必要があります。

add_column :people, :foo_bar_store_id, :integer
add_index :people, :foo_bar_store_id
1
boulder