2012-03-30 10 views
8

Uso ancestry para hacer un árbol de objetivos. Me gustaría enviar el contenido de ese árbol al navegador usando json.Cómo generar json tree de ascendencia

Mi controlador es así:

@goals = Goal.arrange 
respond_to do |format| 
    format.html # index.html.erb 
    format.xml { render :xml => @goals } 
    format.json { render :json => @goals} 
end 

Al abrir el archivo JSON, consigo esta salida:

{"#<Goal:0x7f8664332088>":{"#<Goal:0x7f86643313b8>":{"#<Goal:0x7f8664331048>":{"#<Goal:0x7f8664330c10>":{}},"#<Goal:0x7f8664330e68>":{}},"#<Goal:0x7f86643311b0>":{}},"#<Goal:0x7f8664331f70>":{},"#<Goal:0x7f8664331d18>":{},"#<Goal:0x7f8664331bd8>":{},"#<Goal:0x7f8664331a20>":{},"#<Goal:0x7f86643318e0>":{},"#<Goal:0x7f8664331750>":{},"#<Goal:0x7f8664331548>":{"#<Goal:0x7f8664330aa8>":{}}} 

¿Cómo puedo hacer que el contenido de la meta-objetos en el JSON ¿archivo?

He intentado esto:

@goals.map! {|goal| {:id => goal.id.to_s} 

pero no funciona, ya que es un hash @goals ordenada.

+1

Si código de formato como el código (guión por 4 espacios, o se rodea con acentos abiertos [ '\' ']) que no tienen que eliminar al azar' '<' and '> s. http://stackoverflow.com/editing-help –

+0

Gracias. Arreglado. –

Respuesta

10

Recibí ayuda del usuario tejo en https://github.com/stefankroes/ancestry/issues/82.

La solución es poner este método en el modelo objetivo:

def self.json_tree(nodes) 
    nodes.map do |node, sub_nodes| 
     {:name => node.name, :id => node.id, :children => Goal.json_tree(sub_nodes).compact} 
    end 
end 

y luego hacer que el controlador de la siguiente manera:

@goals = Goal.arrange 
respond_to do |format| 
    format.html # index.html.erb 
    format.xml { render :xml => @goals } 
    format.json { render :json => Goal.json_tree(@goals)} 
end 
+2

Parece que no necesita ascendencia entonces – SET

+1

¿Soy el único que recibe el mensaje en los registros? 'N + 1 Query detected Directory => [: children] Agregue a su buscador:: includes => [: children] N + 1 Método de consulta call stack' Estoy usando' closure_tree'. – cantonic

2

Inspirado en este https://github.com/stefankroes/ancestry/wiki/arrange_as_array

def self.arrange_as_json(options={}, hash=nil) 
    hash ||= arrange(options) 
    arr = [] 
    hash.each do |node, children| 
    branch = {id: node.id, name: node.name} 
    branch[:children] = arrange_as_json(options, children) unless children.empty? 
    arr << branch 
    end 
    arr 
end 
0

Me encontré con este problema el otro día (ascendencia 2.0.0). Modifiqué la respuesta de Johan para mis necesidades. Tengo tres modelos que usan ascendencia, así que tiene sentido extender OrderedHash para agregar un método as_json en lugar de agregar json_tree a tres modelos.

Dado que este hilo fue tan útil, pensé en compartir esta modificación.

instalar esto como un módulo o mono parche para ActiveSupport :: OrderedHash

def as_json(options = {}) 
    self.map do |k,v| 
     x = k.as_json(options) 
     x["children"] = v.as_json(options) 
     x 
    end 
end 

que llamamos el modelo y el uso de su comportamiento por defecto JSON. No estoy seguro si debo llamar al a _json o como _json. He usado as_json aquí y funciona en mi código.

En el controlador

... 
format.json { render :json => @goal.arrange} 
...