¿Asociación de muchos a muchos al mismo modelo con ActiveRecord?
-
06-07-2019 - |
Pregunta
Estoy siguiendo este tutorial que funciona espléndidamente para has_many: a través de las relaciones. Tengo cosas normales como category_product trabajando.
Sin embargo, no puedo conceptualizar esta situación (ni hacer que funcione): tengo una categoría que tiene categorías relacionadas. Dado que cada categoría puede tener N categorías ... en primer lugar, ¿es realmente una situación de muchos a muchos (estoy bastante seguro de que lo es)? En segundo lugar, ¿cómo sería esto? Mi migración se ve así:
create_table :categories do |t|
t.string :name
t.timestamps
end
create_table :related_categories, :id => false do |t|
t.integer :category_a_id
t.integer :category_b_id
end
y las agallas de mi modelo son
has_many :related_categories, :foreign_key=>"category_a_id"
has_many :categories, :through => :related_categories, :source=>:category_a
Obviamente, esto no está bien, aunque está llegando allí (es decir, está 100% roto). ¿Cómo puedo hacer esto?
Editar: olvidé esto, pero solo aquí en SO (lo que significa que no es la respuesta):
class RelatedCategory < ActiveRecord::Base
belongs_to :category_a, :class_name=>"Category"
belongs_to :category_b, :class_name=>"Category"
end
Solución
Deberías probar : source = > : category_b
en su declaración has_many.
Ya usó category_a_id
como su clave externa para la tabla de categorías relacionadas. Básicamente, esto le dice a ActiveRecord que haga coincidir el campo category_a_id
en la tabla related_categories
con el ID del objeto de categoría actual al buscar todos los registros relacionados con las categorías relacionadas con él. El parámetro fuente de esta declaración has_many: through
especifica qué campo se debe considerar para encontrar (o escribir, de hecho) los objetos relacionados al completar la colección de categorías.
Otros consejos
Aquí está la respuesta, pero no es bonita.
has_many :related_categories, :foreign_key=>"category_a_id"
has_many :related_categories2, :class_name=>"RelatedCategory", :foreign_key=>"category_b_id"
has_many :categories, :through => :related_categories, :source=>:category_b
has_many :categories_backwards, :through => :related_categories2, :source=>:category_a
has_many :category_products
entonces tendrías que hacer algo tonto que combine las categorías + categories_backwards, o algo así.
Editar [2 minutos después]: ¡Guau, con el captador casi parece perfecto! Por supuesto, el problema es que tienes que pasar a categorías y no a lo que obtienes del captador.