Rails ma i należy do wielu migracji

Mam dwa modele restaurant i user, które chcę wykonać relację has_and_belongs_to_many.

Weszłam już do plików modelu i dodałam has_and_belongs_to_many :restaurants i has_and_belongs_to_many :users

Zakładam, że w tym momencie powinienem być w stanie zrobić coś takiego jak z Rails 3:

rails generate migration ....
Ale wszystko, czego próbowałem, wydaje się nie udać. Jestem pewien, że jest to coś naprawdę prostego, jestem nowy w rails, więc wciąż się uczę.
Author: dbslone, 2011-07-03

4 answers

Należy dodać oddzielną tabelę join zawierającą tylko restaurant_id i user_id (bez klucza głównego), w porządku alfabetycznym .

Najpierw uruchom Migracje, a następnie Edytuj wygenerowany plik migracji.

Rails 3

rails g migration create_restaurants_users_table

Szyny 4:

rails g migration create_restaurants_users

Rails 5

rails g migration CreateJoinTableRestaurantUser restaurants users

Z docs :

Istnieje również generator, który wytworzy tabele join, jeśli JoinTable jest częścią nazwa:


Twój plik migracji (zwróć uwagę na :id => false; to zapobiega tworzeniu klucza podstawowego):

Rails 3

class CreateRestaurantsUsers < ActiveRecord::Migration
  def self.up
    create_table :restaurants_users, :id => false do |t|
        t.references :restaurant
        t.references :user
    end
    add_index :restaurants_users, [:restaurant_id, :user_id]
    add_index :restaurants_users, :user_id
  end

  def self.down
    drop_table :restaurants_users
  end
end

Rails 4

class CreateRestaurantsUsers < ActiveRecord::Migration
  def change
    create_table :restaurants_users, id: false do |t|
      t.belongs_to :restaurant
      t.belongs_to :user
    end
  end
end

t.belongs_to automatycznie utworzy niezbędne indeksy. def change automatycznie wykryje migrację do przodu lub do tyłu, bez potrzeby góra/dół.

Rails 5

create_join_table :restaurants, :users do |t|
  t.index [:restaurant_id, :user_id]
end

Uwaga: Istnieje również opcja niestandardowej nazwy tabeli, którą można przekazać jako parametr do create_join_table wywołane table_name. Z docs

Domyślnie nazwa tabeli join pochodzi od Związku pierwsze dwa argumenty podane do create_join_table, Alfabetycznie spokój. Aby dostosować nazwę tabeli, podaj :nazwa_ tabeli wariant:

 215
Author: Dex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-13 09:21:26

Odpowiedzi tutaj są dość przestarzałe. Od Rails 4.0.2, Twoje migracje używają create_join_table.

Aby utworzyć migrację, Uruchom:

rails g migration CreateJoinTableRestaurantsUsers restaurant user

Wygeneruje to:

class CreateJoinTableRestaurantsUsers < ActiveRecord::Migration
  def change
    create_join_table :restaurants, :users do |t|
      # t.index [:restaurant_id, :user_id]
      # t.index [:user_id, :restaurant_id]
    end
  end
end

Jeśli chcesz indeksować te kolumny, odkomentuj odpowiednie linie i możesz zaczynać!

 28
Author: Jan Klimo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-16 03:57:05

Podczas tworzenia tabeli join należy zwrócić szczególną uwagę na wymóg, aby obie tabele były wymienione w porządku alfabetycznym w nazwie/klasie migracji. To może łatwo cię ugryźć, jeśli Twoje nazwy modeli są podobne ,np. " abc " i "abb". If you were to run

rails g migration create_abc_abb_table

Twoje relacje będąNIE działać zgodnie z oczekiwaniami. Musisz użyć

rails g migration create_abb_abc_table
Zamiast tego.
 24
Author: shacker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-27 06:52:39

Dla relacji HABTM, musisz utworzyć tabelę join. Istnieje tylko join table I Ta tabela nie powinna mieć kolumny id. Spróbuj tej migracji.

def self.up
  create_table :restaurants_users, :id => false do |t|
    t.integer :restaurant_id
    t.integer :user_id
  end
end

def self.down
  drop_table :restaurants_users
end

Musisz sprawdzić ten poradnik relacji rails guide

 6
Author: Mohit Jain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-28 09:26:01