web-dev-qa-db-ja.com

Rails has_and_belongs_to_many結合テーブルの移行

script/generate migration関係の結合テーブルを作成するためにhas_and_belongs_to_manyを実行するにはどうすればよいですか?

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

122
ma11hew28

どこ:

class Teacher < ActiveRecord::Base
  has_and_belongs_to_many :students
end

そして

class Student < ActiveRecord::Base
  has_and_belongs_to_many :teachers
end

for Rails 4 ::

Rails generate migration CreateJoinTableStudentTeacher student teacher

for Rails 3:

Rails generate migration students_teachers student_id:integer teacher_id:integer

for Rails <

script/generate migration students_teachers student_id:integer teacher_id:integer

(テーブル名には両方の結合テーブルがアルファベット順にリストされています)

そして、Rails 3以下の場合のみ、idフィールドが作成されないように、生成された移行を編集する必要があります。

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

has_and_belongs_to_manyテーブルはこの形式と一致する必要があります。 has_and_belongs_to_manyで結合される2つのモデルがすでにDBにあると想定しています:applesoranges

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 => truehas_and_belongs_to_manyに渡す必要があります。

詳細: Rails Docs

更新2010-12-13IDとタイムスタンプを削除するように更新しました...基本的にMattDiPasqualenunopoloniaが正しい:IDがなく、タイムスタンプがないこと、またはRailsがhas_and_belongs_to_manyの動作を許可しません。

138
docwhat

接続する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の使用を検討する必要があります。

14
nunopolonia

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

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」による有用な答えであり、議論も確かにそうだと思いました。

6
Joseph Lord

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

create_join_table:table1s、:table2s

すべてです。

注意:table1、table2には英数字を使用する必要があります。

4
zw963

するのが好きです:

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

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

1
Jwan622