has_and_belongs_to_many結合テーブルのRails移行


122

リレーションシップのscript/generate migration結合テーブルを作成するにはどうすればよいhas_and_belongs_to_manyですか?

アプリケーションはRails 2.3.2で実行されますが、Rails 3.0.3もインストールされています。

回答:


228

どこ:

class Teacher < ActiveRecord::Base
  has_and_belongs_to_many :students
end

そして

class Student < ActiveRecord::Base
  has_and_belongs_to_many :teachers
end

レール4の場合:

rails generate migration CreateJoinTableStudentTeacher student teacher

レール3の場合:

rails generate migration students_teachers student_id:integer teacher_id:integer

レール<3

script/generate migration students_teachers student_id:integer teacher_id:integer

(テーブル名には両方の結合テーブルがアルファベット順にリストされていることに注意してください)

次に、レール3以下の場合のみ、idフィールドが作成されないように、生成されたマイグレーションを編集する必要があります。

create_table :students_teachers, :id => false do |t|

16
これが実際に質問に答える唯一の返信です。
pingu 2012

8
@pingu:少なくともRails 3.2では機能しないことを除いて。生成された移行ファイルは空白です。
hoffmanc 2013

7
Works for Rails 4
フェリペザヴァン14

2
@hoffmancフィールドを指定しない場合、空の移行ファイルが生成されます。Railsで自動的にフィールドを移行ファイルに追加する場合は、フィールドを指定する必要があります。
Andrew

1
こんにちは、私はのrails generate migration CreateJoinTableTeacherStudent teacher student代わりに試みていますrails generate migration CreateJoinTableStudentTeacher student teacher、それは同じですか?S(学生)はT(それぞれ)の前に必要ですか?
zx1986、2015

138

has_and_belongs_to_many表には、この形式と一致する必要があります。結合する2つのモデルhas_and_belongs_to_manyがすでにDBにあるapplesと想定しています:およびoranges

create_table :apples_oranges, :id => false do |t|
  t.references :apple, :null => false
  t.references :orange, :null => false
end

# Adding the index can massively speed up join tables. Don't use the
# unique if you allow duplicates.
add_index(:apples_oranges, [:apple_id, :orange_id], :unique => true)

:unique => trueインデックスでを使用する場合は、(rails3で)に渡す:uniq => true必要がありhas_and_belongs_to_manyます。

詳細:Railsドキュメント

更新済み2010-12-13 IDとタイムスタンプを削除するように更新しました...基本的MattDiPasqualenunopoloniaは正しいです。IDがあってはならず、タイムスタンプやレールが機能してはいけませんhas_and_belongs_to_many


6
実際、結合テーブルには2つの参照列のみがあり、ID列またはタイムスタンプ列はありません。以下は、指定したリンクからのhas_and_belongs_to_many移行のより良い例です。コマンドラインからそれを行う方法を探していscript/generate migrationます...
ma11hew28

まあ、それはタイムスタンプを持つ必要はありません。私の例ではオプションとしてマークしました。ただし、IDを追加することをお勧めします。IDまたはタイムスタンプのいずれかが役立つ場合があります。しかし、私はIDを強くお勧めします。
docwhat 2010

OK。IDが役立つケースは何ですか?
ma11hew28 2010

1つの例は、関係がビューを持つのに十分重要である場合です。繰り返し検索するのではなく、relationship.idを渡すことにより、データベースへのアクセスを高速化するためにも使用できます。また、データベースのトラブルシューティングも簡単になります。特に、他の列のIDが本当に高い場合。id:54321-id:67890の代わりにid:12345を覚える方が簡単です-しかし、そうは言っても、テーブルが非常に大きくなる場合は、関係ごとに別のIDを割り当てないことでスペースを節約できるようにしたい場合があります。
docwhat

2
マルチカラムインデックスがこれに対する適切なソリューションであるとは思いません。特定のリンゴを検索して関連するオレンジを見つけることはできますが、その逆はできません。2つのシングルカラムインデックスを使用すると、特定のリンゴとオレンジの組み合わせの存在チェックにわずかな損失が生じる可能性があるため、両方向を効率的にクエリできます。
ジョセフ卿

14

接続する2つのモデルの名前をアルファベット順にテーブルに付け、2つのモデルIDをテーブルに配置する必要があります。次に、各モデルを相互に接続して、モデルに関連付けを作成します。

次に例を示します。

# in migration
def self.up
  create_table 'categories_products', :id => false do |t|
    t.column :category_id, :integer
    t.column :product_id, :integer
  end
end

# models/product.rb
has_and_belongs_to_many :categories

# models/category.rb
has_and_belongs_to_many :products

しかし、これはあまり柔軟ではないので、has_many:throughの使用を検討する必要があります。


6

一番上の答えは、オレンジからリンゴを検索するために使用されるとは思えない複合インデックスを示しています。

create_table :apples_oranges, :id => false do |t|
  t.references :apple, :null => false
  t.references :orange, :null => false
end

# Adding the index can massively speed up join tables.
# This enforces uniqueness and speeds up apple->oranges lookups.
add_index(:apples_oranges, [:apple_id, :orange_id], :unique => true)
# This speeds up orange->apple lookups
add_index(:apples_oranges, :orange_id)

私はこれが 'The Doctor What'に基づいているという答えを見つけ、議論も確かに役に立ちました。


4

Rails 4では、簡単に使用できます

create_join_table:table1s、:table2s

それがすべてです。

注意:テーブル1、テーブル2は英数字で構成する必要があります。


これは最新の優れたソリューションです。結合テーブルにはモデルとしてアクセスできませんが、結合された両方のテーブルに設定されているhas_and_belongs_to_manyリレーションを介してアクセスできることに注意してください。
テイラードWebサイト

1

私は好きです:

rails g migration CreateJoinedTable model1:references model2:references。このようにして、次のような移行を取得します。

class CreateJoinedTable < ActiveRecord::Migration
  def change
    create_table :joined_tables do |t|
      t.references :trip, index: true
      t.references :category, index: true
    end
    add_foreign_key :joined_tables, :trips
    add_foreign_key :joined_tables, :categories
  end
end

これらの列を使用してルックアップを行うことが多いため、これらの列にインデックスを付けるのが好きです。


add_foreign_keyテーブルを作成したのと同じ移行に配置すると失敗します。
Adib Saad
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.