En Rails, hay dos maneras principales de crear relaciones muchos-a-muchos entre modelos:
- usando una asociación has_and_belongs_to_many
- usando una asociación has_many :through
Esto es Truquitos, así que vamos al grano.
Usando has_and_belongs_to_many
Esta es la manera más fácil de establecer una relación muchos-a-muchos. Creará una tabla de base de datos para relacionar los dos modelos (pero no un tercer modelo para representar la relación).
Supón que tienes dos modelos que necesitan tener una relación muchos-a-muchos:
- instruments (instrumentos)
- musicians (músicos)
El primer paso es escribir una migración, que (para este ejemplo) se vería así:
class AddHABTMForInstrumentsAndmusicians < ActiveRecord::Migration[6.0]
def change
create_table :instruments_musicians, id: false do |t|
t.belongs_to :instrument
t.belongs_to :musician
end
end
end
Si ejecutas esta migración generará la siguiente descripción de tabla en schema.rb:
create_table "instruments_musicians", id: false, force: :cascade do |t|
t.bigint "instrument_id"
t.bigint "musician_id"
t.index ["instrument_id"], name: "index_instruments_musicians_on_instrument_id"
t.index ["musician_id"], name: "index_instruments_musicians_on_musician_id"
end
Ahora lo único que necesitas es agregar la línea has_and_belongs_to_many a cada modelo, así:
class Instrument < ApplicationRecord
has_and_belongs_to_many :musicians
end
class Musician < ApplicationRecord
has_and_belongs_to_many :instruments
end
Y hemos terminado, eso es todo lo que necesitas para crear una relación has_and_belongs_to_many.
Usando has_many :through
La diferencia principal entre esta opción y la primera es que ahora se crea un tercer modelo. Tal modelo puede contener cosas como comportamiento personalizado o validaciones, y puede ser útil en muchos casos.
Volviendo a nuestro ejemplo, para crear una asociación has_many :through necesitamos escribir una migración que cree un modelo que lógicamente conecte músicos e instrumentos, algo como un cancionero:
create_table :songbooks do |t|
t.belongs_to :instrument
t.belongs_to :musician
t.string :title #podemos agregar atributos extra si queremos
t.timestamps
end
Ahora, podemos agregar las asociaciones a los modelos:
class Songbook < ApplicationRecord
belongs_to :instrument
belongs_to :musician
end
class Instrument < ApplicationRecord
has_many :songbooks
has_many :musicians, through: :songbooks
end
class Musician < ApplicationRecord
has_many :songbooks
has_many :instruments, through: :songbooks
end
Y así es como creas una asociación has_many :through.
¿Cuál debería usar?
Mi regla general es la siguiente: Si necesito validaciones o cualquier forma de comportamiento personalizado en la relación, voy con has_many :through. De otra manera (la mayoría de casos) voy con has_and_belongs_to_many.
¡Gracias por leer!
Qué hacer después
- Comparte este artículo con amigos y colegas. Gracias por ayudarme a llegar a personas que podrían encontrar útil esta información.
- Puedes revisar la documentación oficial de Rails para asociaciones aquí.
- Si quieres aprender más sobre Rails puedes revisar RoR Tutorial (Hartl).
- Envíame un email con preguntas, comentarios o sugerencias (está en la página Autor)