ruby on rails - relaciones - Creando una relación de muchos a muchos en Rails
relaciones de modelos en rails (1)
Este es un ejemplo simplificado de lo que estoy tratando de lograr, soy relativamente nuevo en Rails y estoy luchando para entender las relaciones entre modelos.
Tengo dos modelos, el modelo de User
y el modelo de Category
. Un usuario puede asociarse con muchas categorías. Una categoría particular puede aparecer en la lista de categorías para muchos usuarios. Si se elimina una categoría en particular, esto debería reflejarse en la lista de categorías para un usuario.
En este ejemplo:
Mi tabla de Categories
contiene cinco categorías:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ID | Name | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 1 | Sports | | 2 | News | | 3 | Entertainment | | 4 | Technology | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Mi tabla de Users
contiene dos usuarios:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ID | Name | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 1 | UserA | | 2 | UserB | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
UsuarioA puede elegir Deportes y Tecnología como sus categorías
El usuario B puede elegir Noticias, Deportes y Entretenimiento
La categoría deportiva se elimina, las listas de categorías UserA y UserB reflejan la eliminación
He jugado con crear una tabla UserCategories
que contenga los ID de una categoría y un usuario. Este tipo de trabajo, pude buscar los nombres de las categorías, pero no pude hacer que funcionara una eliminación en cascada y toda la solución me pareció incorrecta.
Los ejemplos del uso de las funciones belongs_to y has_many que he encontrado parecen discutir el mapeo de una relación de uno a uno. Por ejemplo, comentarios en una publicación de blog.
- ¿Cómo se representa esta relación de muchos a muchos usando la funcionalidad incorporada de Rails?
- ¿Usar una tabla separada entre las dos es una solución viable cuando se usa Rails?
Quieres una relación has_and_belongs_to_many
. La guía hace un excelente trabajo al describir cómo funciona esto con gráficos y todo:
http://guides.rubyonrails.org/association_basics.html#the-has-and-belongs-to-many-association
Terminarás con algo como esto:
# app/models/category.rb
class Category < ActiveRecord::Base
has_and_belongs_to_many :users
end
# app/models/user.rb
class User < ActiveRecord::Base
has_and_belongs_to_many :categories
end
Ahora necesita crear una tabla de unión para que Rails la use. Rails no hará esto automáticamente por ti. Esto es efectivamente una tabla con una referencia a cada una de las Categorías y Usuarios, y no tiene una clave principal.
Genere una migración desde la CLI de esta manera:
bin/rails g migration CreateCategoriesUsersJoinTable`
A continuación, ábralo y edítelo para que coincida:
Para Rails 4.0.2+ (incluido Rails 5.1):
def change
# This is enough; you don''t need to worry about order
create_join_table :categories, :users
# If you want to add an index for faster querying through this join:
create_join_table :categories, :users do |t|
t.index :category_id
t.index :user_id
end
end
Rails <4.0.2:
def self.up
create_table :categories_users, :id => false do |t|
t.integer :category_id
t.integer :user_id
end
add_index :categories_users, [:category_id, :user_id]
end
def self.down
drop_table :categories_users
end
Con eso en su lugar, ejecute sus migraciones y puede conectar Categorías y Usuarios con todos los accesos convenientes a los que está acostumbrado:
User.categories #=> [<Category @name="Sports">, ...]
Category.users #=> [<User @name="UserA">, ...]
User.categories.empty?