2011-02-24 17 views
17

Tengo categorías que están en una estructura de árbol. Estoy tratando de vincularlos mediante la definición de un padre para cada uno. (No pude encontrar la forma de llamar a la propiedad parent por lo que es solo category por ahora, pero significa que el padre).Creando un modelo que tiene una estructura de árbol

class Category < ActiveRecord::Base 

    has_one :category # the parent category 

end 

Pero la relación termina en el camino equivocado.

función El captador está en la categoría infantil (correctamente) pero el category_id se almacena en la matriz:

parent = Category.create(:name => "parent") 
child = Category.create(:name => "child", :category => parent) 

parent.id # 1 
child.id # 2 

child.category_id # nil 
parent.category_id # 2 

child.category.name # "parent" (!!) 

El padre tiene que ser capaz de tener varios hijos para que esto no se va a trabajar.

Respuesta

34

Lo que estás buscando es autoinscribirse. Compruebe esta sección de los rieles de guía a cabo: http://guides.rubyonrails.org/association_basics.html#self-joins

class Category < ActiveRecord::Base 
  has_many :children, class_name: "Category", foreign_key: "parent_id" 
  belongs_to :parent, class_name: "Category" 
end 

Cada categoría se belong_to un padre, incluso sus categorías padre. Puede crear un padre de una sola categoría al que pertenecen sus categorías de más alto nivel, luego puede ignorar esa información en su aplicación.

+0

Estoy de acuerdo con Adriano, esto no funciona. Cuando hago algo como 'obj.parent', la consulta que se ejecuta es algo así como' select objs. * From objs where objs.parent_id = 3' Look right? Bueno, el obj.parent_id no es 3, pero es id. El método 'children' sí funciona. – DJTripleThreat

+0

Pude corregir tu respuesta haciendo esto en su lugar: 'belongs_to: parent,: class_name =>" Category ",: foreign_key =>: id,: primary_key =>: parent_id' – DJTripleThreat

+0

@DJTripleThreat Estás seguro de que no lo hiciste t tiene un 'foreign_key' en su asociación' belongs_to' o pone la clave externa ('belongs_to') en el padre? La información crucial aquí es que está haciendo referencia al objeto padre de una clave en el objeto hijo, por lo tanto, cuando llame a 'child.parent' obtendrá una consulta como' SELECT model. * FROM models WHERE id = child.parent_id LIMIT 1'. – coreyward

2

La categoría debe tener muchas categorías, y la clave externa de cada categoría debe ser parent_id. Por lo tanto, cuando lo haga parent.children enumera todas las categorías que tienen parent_id=parent.id.

¿Has leído sobre Herencia de tabla única?

3

Puede usar la gema acts_as_tree para lograr esto, consulte el siguiente ejemplo y enlace.

https://github.com/amerine/acts_as_tree/tree/master

class Category < ActiveRecord::Base 
    include ActsAsTree 

    acts_as_tree order: "name" 
end 

root  = Category.create("name" => "root") 
child1 = root.children.create("name" => "child1") 
subchild1 = child1.children.create("name" => "subchild1") 

root.parent # => nil 
child1.parent # => root 
root.children # => [child1] 
root.children.first.children.first # => subchild1 
+1

También la gema [Ancestry] (https://github.com/stefankroes/ancestry). –

+0

Sí, también es interesante. –

2

Usted debe echar un vistazo a la gema ascendencia: https://github.com/stefankroes/ancestry

Se proporciona toda la funcionalidad que necesita y es capaz de obtener todos los descendientes, hermanos, padres, etc con un único Consulta SQL mediante una variante de rutas materializadas, por lo que tendrá un mejor rendimiento que las respuestas self-joins y acts_as_tree anteriores.

Cuestiones relacionadas