Migracja szyn do tabeli łączenia has_and_belongs_to_many


Odpowiedzi:


228

Gdzie:

class Teacher < ActiveRecord::Base
  has_and_belongs_to_many :students
end

i

class Student < ActiveRecord::Base
  has_and_belongs_to_many :teachers
end

dla szyn 4:

rails generate migration CreateJoinTableStudentTeacher student teacher

dla szyn 3:

rails generate migration students_teachers student_id:integer teacher_id:integer

dla szyn <3

script/generate migration students_teachers student_id:integer teacher_id:integer

(zwróć uwagę, że nazwa tabeli zawiera obie tabele łączenia w kolejności alfabetycznej)

a następnie tylko dla szyn 3 i niższych, musisz edytować wygenerowaną migrację, aby pole identyfikatora nie zostało utworzone:

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

16
To jedyna odpowiedź, która faktycznie odpowiada na to pytanie.
pingu

8
@pingu: poza tym, że nie działa, przynajmniej w Railsach 3.2. Wygenerowany plik migracji jest pusty.
hoffmanc

7
Works for Rails 4.
Felipe Zavan

2
@hoffmanc Wygeneruje pusty plik migracji, jeśli nie określisz żadnych pól. Musisz określić pola, jeśli chcesz, aby Railsy automatycznie dodawały je do pliku migracji.
Andrew

1
cześć, próbuję rails generate migration CreateJoinTableTeacherStudent teacher studentzamiast rails generate migration CreateJoinTableStudentTeacher student teacher, czy to to samo? Czy S (tudent) musi przed T (eacher)?
zx1986

138

has_and_belongs_to_manyStół musi pasować ten format. Zakładam, że dwa modele, które mają zostać połączone, has_and_belongs_to_manysą już w bazie danych: applesi 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)

Jeśli używasz :unique => trueindeksu, powinieneś (w rails3) przejść :uniq => truedo has_and_belongs_to_many.

Więcej informacji: Rails Docs

ZAKTUALIZOWANO 2010-12-13 Zaktualizowałem go, aby usunąć identyfikator i znaczniki czasu ... Zasadniczo MattDiPasqualei nunopoloniasą one poprawne: nie może być identyfikatora i nie może być znaczników czasu ani szyn, które nie pozwolą has_and_belongs_to_manydziałać.


6
W rzeczywistości tabela łączenia powinna mieć tylko dwie kolumny odwołań i nie powinna mieć kolumn z identyfikatorami ani datownikami. Oto lepszy przykład migracji has_and_belongs_to_many z linku, który podałeś. Szukam sposobu na zrobienie tego z wiersza poleceń za pomocą script/generate migration...
ma11hew28,

Cóż, nie musi mieć sygnatur czasowych; Oznaczyłem to jako opcjonalne w moim przykładzie. Zalecałbym jednak dodanie identyfikatora. Istnieją przypadki, w których identyfikator lub znacznik czasu mogą być przydatne. Ale zdecydowanie polecam ID.
docwhat

Dobrze. W jakim przypadku identyfikator byłby przydatny?
ma11hew28

Jednym z przykładów jest sytuacja, w której związek jest na tyle ważny, że można go zobaczyć. Można go również użyć do przyspieszenia dostępu do baz danych, omijając plik Relations.id zamiast wielokrotnie go wyszukiwać. Ułatwia również rozwiązywanie problemów z bazą danych. Zwłaszcza jeśli identyfikatory innych kolumn są naprawdę wysokie. Łatwiej jest zapamiętać id: 12345 zamiast id: 54321-id: 67890 - Ale biorąc pod uwagę to, że jeśli tabela zrobi się naprawdę duża, możesz chcieć zaoszczędzić miejsce, nie przydzielając innego identyfikatora dla każdej relacji.
docwhat

2
Nie sądzę, aby indeks wielokolumnowy był w tym przypadku odpowiednim rozwiązaniem. Będzie działać w przypadku zapytań dotyczących konkretnych jabłek, aby znaleźć powiązane pomarańcze, ale nie na odwrót. Dwa indeksy jednokolumnowe umożliwiłyby efektywne odpytywanie w obu kierunkach, prawdopodobnie z niewielką stratą do sprawdzenia istnienia konkretnej kombinacji jabłka i pomarańczy).
Joseph Lord

14

Powinieneś nazwać tabelę nazwami 2 modeli, które chcesz połączyć w kolejności alfabetycznej i umieścić dwa identyfikatory modeli w tabeli. Następnie połącz każdy model ze sobą, tworząc w modelu skojarzenia.

Oto przykład:

# 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

Ale to nie jest zbyt elastyczne i powinieneś pomyśleć o użyciu has_many: through


6

Górna odpowiedź pokazuje złożony indeks, który, jak sądzę, nie będzie używany do wyszukiwania jabłek z pomarańczy.

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)

Uznałem, że odpowiedź, na podstawie której jest to oparte na „Doktorze What”, jest użyteczna i dyskusja z pewnością również.


4

W szynach 4 można łatwo używać

create_join_table: table1s,: table2s

to wszystko.

Uwaga: tabelę1, tabelę2 należy wyłączyć alfanumerycznie.


jest to dobre, aktualne rozwiązanie. Należy zauważyć, że tabela łączenia nie jest dostępna jako model, ale za pośrednictwem relacji has_and_belongs_to_many, które są skonfigurowane w obu połączonych tabelach.
Witryny internetowe Taylored

1

Lubię robić:

rails g migration CreateJoinedTable model1:references model2:references. W ten sposób otrzymuję migrację, która wygląda następująco:

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

Lubię mieć indeksy w tych kolumnach, ponieważ często będę wyszukiwać za pomocą tych kolumn.


add_foreign_keyzakończy się niepowodzeniem, jeśli zostanie umieszczony w tej samej migracji, co ta, która utworzyła tabele.
Adib Saad
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.