Tengo tres tablas Productos, Tags y productos_tags. Los Tags pueden
tener
hijos y necesito hacer una consulta que devuelva los productos de un
Tags o
de los descendientes de dicho Tag.
Mis tablas:
create_table :productos do |t|
t.integer :activo
t.string :nombre
t.timestamps
end
create_table :tags do |t|
t.string :nombre
t.integer :parent_id
t.timestamps
end
create_table :productos_tags do |t|
t.integer :producto_id
t.integer :tag_id
t.timestamps
end
Mis Modelos:
class Producto < ActiveRecord::Base
has_and_belongs_to_many :tags
end
class Tag < ActiveRecord::Base
acts_as_adjacency_list :foreign_key => ‘parent_id’
has_and_belongs_to_many :productos
end
No quiero usar find_by_sql
Tendria que hacer 3 modelos y usar has many :through? Agradecere
cualquier
idea o indicación de tema para buscar más información
Tengo tres tablas Productos, Tags y productos_tags. Los Tags pueden
tener hijos y necesito hacer una consulta que devuelva los productos
de un Tags o de los descendientes de dicho Tag.
si sólo tienes un par de niveles (padre/hijo) puedes conseguirlo de
forma fácil con un include y una condición. Si tienes varios niveles, no
hay forma portable de hacerlo sin utilizar varias queries con la
estructura que propones (aunque algunas bases de datos sí traen
extensiones para navegar por un árbol)
lo que sí podrías hacer es no utilizar un árbol, sino un nested set.
Tiempo ha en rails estaba incluída el componente “acts_as_nested_set”
que de forma transparente te permitía este tipo de cosas. Hoy en día es
un plugin separado en
si sólo tienes un par de niveles (padre/hijo) puedes conseguirlo de
forma fácil con un include y una condición. Si tienes varios niveles, no
hay forma portable de hacerlo sin utilizar varias queries con la
estructura que propones (aunque algunas bases de datos sí traen
extensiones para navegar por un árbol)
Tengo varios niveles. A que te refieres con utilizar varias queries?
la BBDD es MySql
Me miro lo del acts_as_nested_set, aunque Necesito que sea usando el
acts_as_adjacency_list
en ese caso estás condenado a la ineficiencia… acts as adjacency list
es como acts as tree. Cada vez que quieres consultar información de los
hijos de un padre determinado (o del padre de un elemento) tienes que
ejecutar una query contra la base de datos… y así hasta llegar al
último nivel.
precisamente un nested set te evita esto, pero si tienes que usar
adjacency no vas a poder hacerlo en una única consulta, que pensaba que
era lo que pedías en tu mail inicial
¿de donde sale acts_as_adjacency_list? Lo único que encuentro con
Google es un commit al source code de Spree en GitHub. Sin README, sin
documentación (la poca que tiene parece copiada de Acts As Tree).
En un repaso rápido del código no está optimizado para casi nada. Lo
único que proporciona por encima de Acts As Tree es el orden de los
nodos hijos. Y tampoco dirÃa que lo hace muy eficientemente. Además
por lo que veo de tu código no utilizas el orden de los hijos para
nada (y por cierto, no es necesario que indiques la opción
:foreing_key si se va a llamar “parent_id”, que es el nombre por
defecto).
Si lo de usarlo era para poder acceder a todos los descendientes de un
elemento puedo con acts_as_adjacency_list
poder puedes, pero a costa de lanzar muchas consultas
Tag.find(:first).descendents.collect{|p| productos << p }
ese inocente “descendents” te lanza una query por cada nivel de hijos
que tengas. A eso me refería con el tema de que con nested_set podías
sacar todos los hijos de una sola vez en un único find