Rails tiene y pertenece a muchas migraciones


Tengo dos modelos restaurant y user que quiero realizar una has_and_belongs_to_many relación.

Ya he entrado en los archivos del modelo y he añadido los has_and_belongs_to_many :restaurants y has_and_belongs_to_many :users

Asumo que en este punto debería ser capaz de hacer algo como con Rails 3:

rails generate migration ....

Pero todo lo que he intentado parece fallar. Estoy seguro de que esto es algo muy simple Soy nuevo en rails, así que todavía estoy aprendiendo.

Author: dbslone, 2011-07-03

4 answers

Necesita agregar una tabla de unión separada con solo restaurant_id y user_id (sin clave primaria), en orden alfabético .

Primero ejecute sus migraciones y, a continuación, edite el archivo de migración generado.

Carriles 3

rails g migration create_restaurants_users_table

Rieles 4:

rails g migration create_restaurants_users

Carriles 5

rails g migration CreateJoinTableRestaurantUser restaurants users

De los documentos :

También hay un generador que producirá tablas de unión si JoinTable es parte de la nombre:


Su archivo de migración (tenga en cuenta el :id => false; es lo que impide la creación de una clave primaria):

Carriles 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

Carriles 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 creará automáticamente los índices necesarios. def change detectará automáticamente una migración hacia adelante o hacia atrás, sin necesidad de subir/bajar.

Carriles 5

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

Nota: También hay una opción para un nombre de tabla personalizado que se puede pasar como parámetro a create_join_table called table_name. De los documentos

De forma predeterminada, el nombre de la tabla join proviene de la unión de los dos primeros argumentos proporcionados a create_join_table, en orden alfabético orden. Para personalizar el nombre de la tabla, proporcione un: table_name opción:

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-13 09:21:26

Las respuestas aquí son bastante anticuadas. A partir de Rails 4.0.2, tus migraciones hacen uso de create_join_table.

Para crear la migración, ejecute:

rails g migration CreateJoinTableRestaurantsUsers restaurant user

Esto generará lo siguiente:

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

Si desea indexar estas columnas, descomente las líneas respectivas y ¡listo!

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-16 03:57:05

Al crear la tabla de unión, preste mucha atención al requisito de que las dos tablas deben enumerarse en orden alfabético en el nombre/clase de migración. Esto puede morderte fácilmente si los nombres de tus modelos son similares, por ejemplo, "abc" y "abb". Si tuvieras que correr

rails g migration create_abc_abb_table

Tus relaciones no funcionarán como se esperaba. Debe utilizar

rails g migration create_abb_abc_table

En su lugar.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-27 06:52:39

Para las relaciones HABTM, es necesario crear una tabla de unión. Solo hay tabla de unión y esa tabla no debe tener una columna id. Prueba esta migración.

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

Debe comprobar esta relación rails guía tutoriales

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-28 09:26:01