web-dev-qa-db-fra.com

Rails migration pour has_and_belongs_to_many table de jointure

Comment faire un script/generate migration pour créer une table de jointure pour un has_and_belongs_to_many relation?

L'application s'exécute sur Rails 2.3.2, mais j'ai aussi Rails 3.0.3 installé.

122
ma11hew28

Où:

class Teacher < ActiveRecord::Base
  has_and_belongs_to_many :students
end

et

class Student < ActiveRecord::Base
  has_and_belongs_to_many :teachers
end

pour Rails 4:

Rails generate migration CreateJoinTableStudentTeacher student teacher

pour Rails 3:

Rails generate migration students_teachers student_id:integer teacher_id:integer

pour Rails <

script/generate migration students_teachers student_id:integer teacher_id:integer

(notez que le nom de la table répertorie les deux tables de jointure par ordre alphabétique)

et ensuite pour Rails 3 et inférieurs uniquement, vous devez modifier votre migration générée afin qu'aucun champ d'identifiant ne soit créé:

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

UNE has_and_belongs_to_many table doit correspondre à ce format. Je suppose que les deux modèles seront rejoints par has_and_belongs_to_many sont déjà dans le DB: apples et 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)

Si vous utilisez le :unique => true sur l’index, alors vous devriez (dans Rails3) passer :uniq => true à has_and_belongs_to_many.

Plus d'informations: Rails Docs

MIS À JOUR LE 12/12/2010 Je l'ai mis à jour pour supprimer l'id et l'horodatage ... En gros MattDiPasquale et nunopolonia sont corrects: il ne doit pas y avoir d’identifiant, ni d’horodatage ni Rails ne permet pas has_and_belongs_to_many travailler.

138
docwhat

Vous devez nommer la table les noms des 2 modèles que vous souhaitez connecter par ordre alphabétique et placer les deux identifiants de modèle dans la table. Ensuite, connectez chaque modèle les uns aux autres en créant les associations dans le modèle.

Voici un exemple:

# 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

Mais ce n’est pas très flexible et vous devriez penser à utiliser has_many: à travers

14
nunopolonia

La réponse en haut montre un indice composite qui, à mon avis, ne sera pas utilisé pour rechercher des pommes dans des 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.
# 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)

J'ai trouvé la réponse à cela basée sur "Le Docteur Qu'est-ce que" est utile et la discussion l'est certainement aussi.

6
Joseph Lord

Dans Rails 4, vous pouvez utiliser simplement

create_join_table: table1s,: table2s

c'est tout.

Attention: vous devez offord table1, table2 avec alphanumérique.

4
zw963

J'aime faire:

Rails g migration CreateJoinedTable model1:references model2:references. De cette façon, je reçois une migration qui ressemble à ceci:

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

J'aime avoir des index sur ces colonnes car je vais souvent faire des recherches à l'aide de ces colonnes.

1
Jwan622