「参照」移行での列名の指定


124

migration別のテーブルを参照してRailsで作成したい。通常、私は次のようなことをします:

add_column :post, :user, :references

これにより、テーブルに名前が付けられた列が作成さuser_idpostsます。しかし、ではなく、のuser_idようなものが欲しい場合はどうなりauthor_idますか?どうやってやるの?

回答:


59

手動で行う:

add_column :post, :author_id, :integer

しかし、今、belongs_toステートメントを作成するときは、それを変更する必要があるため、次のように呼び出す必要があります。

def post
    belongs_to :user, :foreign_key => 'author_id'
end

1
インデックスを追加する必要はありませんか?
caarlos0

1
はい、移行時にインデックスを作成する必要があります。
トムハリソン

1
Railsはごまかす-デフォルトでは実際にはインデックスを使用しません。ここで、インデックスが必要な場合(これは素晴らしいアイデアです-Railsが完全に無視するという事実にもかかわらず)、確実に追加できます。移行に関する一般的な情報については、私がリンクしているガイドを確認することをお勧めします。最終的には、SQLコードを直接呼び出して移行することもできます。Railsの通常の部分ではないので無視します。Railsのデフォルトで生成されたSQLクエリはそれを利用しないため、パフォーマンスは0になります。 リンク
mschultz

うーん理解しました。どうもありがとうございました!
caarlos0

schema_plusgem を使用t.references :category, index: true, foreign_key: true, references: :match_categoriesして、マイグレーションファイルでも動作しました。
elquimista 2016

251

Rails 5以降

初期定義:

あなたが定義している場合はPost、モデルのテーブルを、あなたが設定することができreferencesindexかつforeign_key1行で:

t.references :author, index: true, foreign_key: { to_table: :users }

既存のものを更新:

既存のテーブルへの参照を追加する場合、これを行うことができます:

add_reference :posts, :author, foreign_key: { to_table: :users }

注: のデフォルト値indexはtrueです。


最初の定義ではnullが許可されますか?そうでない場合は、null許容の代替案を知っていますか?
Vorpulus Lyphane

5
この定義ではnullsを使用できます。それらを許可しない場合は、通常のオプションを追加しますnull: false
愛鷹2017年

ありがとう。「初期定義」は「index:true」は必要ないと思います。私はそれがあってもなくても同じスキーマ変更を取得します。気にしないで; 最後にあなたのメモを見ました。
Joey

ありがとう、これは私が探していたものです!
フィリップB.

250

Rails 4.2 +あなたも設定することができ、外部キーを、DB内にも素晴らしいアイデアです

単純な関連付けの場合、これはをt.references追加するforeign_key: trueときにも実行できますが、この場合は2行必要です。

# The migration
add_reference :posts, :author, index: true
add_foreign_key :posts, :users, column: :author_id

# The model
belongs_to :author, class_name: "User"

2
ありがとうございます。ただし、質問のタグはRails3です。私はただ手伝ってくれて嬉しいです
ecoologic

2
ああ、気づかなかった。まあ、それはto.meにとても役立っています。:)
bonh 2016

2
これを見たときはもうほとんど諦めていました!@ecoologicありがとうございます!
ダンウィリアムズ

2
@ecoologic、あなたが追加したいと思うかもしれないことの1つだけ、add_foreign_keyはレール4.2+のみです。;)
ダンウィリアムズ

4
通話でreferences: :usersオプションが必要かわかりませんadd_reference。私はそれがドキュメントに文書化されているのを見ません、そしてそれなしで私の側で動作するようです。
jakecraige 2017

87

Rails 4では、postgresqlとschema_plus gemを使用すると、次のように書くことができます

add_reference :posts, :author, references: :users

これにより、author_id正しく参照する列が作成されusers(id)ます。

そして、あなたのモデルでは、あなたは書きます

belongs_to :author, class_name: "User"

新しいテーブルを作成するときは、次のように書くことができます。

create_table :things do |t| 
  t.belongs_to :author, references: :users 
end 

注:schema_plusgemは完全にrails 5+と互換性がありませんが、この機能は、rails 5と互換性のあるgem schema_auto_foreign_keysschema_plusの一部)によって提供されます。


28
そしてあなたが使用している場合create_tablet.references :author, references: :users
Michael Radionov 14

2
@MichaelRadionovのコメントを回答に追加すると、完璧になります。
toxaq 2015

2
私はRails 4.1のソースを調べてきましたが、:references実際に何かをしている証拠を見つけることができません。
jes5199 2015年

1
はい、そうです。私はschema_plus古くからこの宝石を使用しており、実際にその機能を追加しています。私はそれに応じて私の答えを編集しました。
nathanvda 2016年

2
Rails 6では、t.references :col_name, references: other_table_name追加のgemをインストールしなくても構文が機能するようです。
Qqwy

51

外部キーを使用していない場合は、他のテーブルの実際のテーブル名が何であるかは関係ありません。

add_reference :posts, :author

Rails 5以降、外部キーを使用している場合は、外部キーオプションで他のテーブルの名前を指定できます。(議論についてはhttps://github.com/rails/rails/issues/21563を参照してください

add_reference :posts, :author, foreign_key: {to_table: :users}

Rails 5以前は、外部キーを個別のステップとして追加する必要があります。

add_foreign_key :posts, :users, column: :author_id

12
to_tableは複数形です{to_table: :users}
。– hoffmanc

-3

alias_attribute(new_name、old_name)は非常に便利です。モデルと関係を作成するだけです。

rails g model Post title user:references

次に、モデルを編集して、属性エイリアスを追加します

alias_attribute :author, :user

その後、次のようなものを実行できるようになります

Post.new(title: 'My beautiful story', author: User.first)

1
これは、別のモデルへの複数の参照を定義する必要がある場合には機能しません。たとえば、投稿(作成者、編集者)
ultrajohn
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.