2012-03-30 7 views
8

Io uso l'antenato per fare un albero di obiettivi. Vorrei inviare il contenuto di quell'albero al browser usando json.Come generare json tree da ancestry

mio controller è simile a questo:

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

Quando apro il file JSON, ottengo questo output:

{"#<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>":{}}} 

Come faccio a rendere il contenuto della meta-oggetti in JSON file?

Ho provato questo:

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

ma non funziona, dal momento che @goals è un hash ordinata.

+1

Se codice del formato come codice (trattino da 4 spazi, o surround con apici inversi [ '\' ']) Non è necessario rimuovere in modo casuale' <' and '> 's. http://stackoverflow.com/editing-help –

+0

Grazie. Aggiustato. –

risposta

10

Ho ricevuto aiuto dall'utente tejo allo https://github.com/stefankroes/ancestry/issues/82.

La soluzione è quella di mettere questo metodo nel modello obiettivo:

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 

e poi fare l'aspetto di controllo in questo modo:

@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

Sembra che tu non abbia bisogno di antenati, quindi – SET

+1

sono l'unico a ricevere il messaggio nei log? 'N + 1 Ricerca rilevata Directory => [: children] Aggiungi al tuo finder:: includes => [: children] N + 1 Stack di chiamate con metodo di query' Sto usando 'closure_tree'. – cantonic

2

Ispirato da questo 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

Mi sono imbattuto in questo problema l'altro giorno (ascendenza 2.0.0). Ho modificato la risposta di Johan per i miei bisogni. Ho tre modelli che usano ancestry, quindi aveva senso estendere OrderedHash per aggiungere un metodo as_json invece di aggiungere json_tree a tre modelli.

Poiché questo thread è stato di grande aiuto, ho pensato di condividere questa modifica.

installare questo come una patch modulo o scimmia per 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 

Chiamiamo il modello e utilizzare il suo comportamento JSON predefinito. Non sono sicuro Se dovrei chiamare a _json o come _json. Ho usato as_json qui e funziona nel mio codice.

Nel controllore

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