2012-01-20 15 views
18

Ho un hash rubino che mi piacerebbe renderizzare usando RABL. L'hash simile a questa:Rendering di un semplice hash di Ruby con RABL

@my_hash = { 
    :c => { 
     :d => "e" 
    } 
} 

Sto cercando di rendere questo con un certo codice Rabl:

object @my_hash => :some_object 
attributes :d 
node(:c) { |n| n[:d] } 

ma sto ricevendo {"c":null}

Come posso rendere questo con Rabl?

risposta

22

Attualmente Rabl non gioca troppo bene con hash. Sono stato in grado di aggirarlo convertendo il mio hash in un formato OpenStruct (che utilizza una notazione a punti più RABL-friendly). Uso tuo esempio:

your_controller.rb

require 'ostruct' 
@my_hash = OpenStruct.new 
@my_hash.d = 'e' 

your_view.rabl

object false 
child @my_hash => :c do 
    attributes :d 
end 

risultati

{ 
    "c":{ 
    "d":"e" 
    } 
} 
+0

Sembra che non sia necessario utilizzare la notazione a punti se si avvolge l'hash in un OpenStruct. https://github.com/nesquena/rabl/wiki/Rendering-hash-objects-in-rabl – jmosesman

2

Specificando un nodo come questo, è possibile accedere all'oggetto @my_hash a cui è possibile accedere agli attributi di. Quindi, vorrei solo leggermente modificare il codice per essere:

object @my_hash 
node(:c) do |c_node| 
    {:d => c_node.d} 
end 

dove c_node è essenzialmente l'oggetto @my_hash. Questo dovrebbe dare quello che ci si aspetta (mostrato qui in JSON):

{ 
    "my_hash":{ 
     "c":{ 
     "d":"e" 
     } 
    } 
} 
+1

Purtroppo ottengo questo errore 'metodo non definito 'd' di: c: Symbol' quando si utilizza il codice di cui sopra. – SundayMonday

+0

'.d' è un attributo valido di' @ my_hash'? Deve esserlo, altrimenti quello che stai cercando di fare non è possibile. Ho testato questo codice per conto mio e ha funzionato per un attributo valido dell'oggetto. – iwasrobbed

2

La mia risposta si basa in parte sul sito di seguito elencati:

Adattato da questo sito:

http://www.rubyquiz.com/quiz81.html

require "ostruct" 

    class Object 
    def to_openstruct 
     self 
    end 
    end 

    class Array 
    def to_openstruct 
     map{ |el| el.to_openstruct } 
    end 
    end 

    class Hash 
    def to_openstruct 
     mapped = {} 
     each{ |key,value| mapped[key] = value.to_openstruct } 
     OpenStruct.new(mapped) 
    end 
    end 

Definisci questa forse in un inizializzatore e allora per ogni hash appena messo to_openstruct e inviare che oltre al modello rabl e fondamentalmente fai ciò che jnunn mostra nella vista.

4

RABL può effettivamente rendere facilmente gli hash e gli array di ruby, come attributi, ma non come oggetto radice.Così, per esempio, se si crea un OpenStruct come questo per l'oggetto root:

@my_object = OpenStruct.new 
@my_object.data = {:c => {:d => 'e'}} 

allora si potrebbe utilizzare questo modello Rabl:

object @my_object 

attributes :data 

E questo renderebbe:

{"data": {"c":{"d":"e"}} } 

In alternativa, se si desidera che :c sia una proprietà dell'oggetto radice, è possibile utilizzare "nodo" per creare quel nodo e rendere l'hash all'interno di tale nodo:

# -- rails controller or whatever -- 
@my_hash = {:c => {:d => :e}} 

# -- RABL file -- 
object @my_hash 
# Create a node with a block which receives @my_hash as an argument: 
node { |my_hash| 
    # The hash returned from this unnamed node will be merged into the parent, so we 
    # just return the hash we want to be represented in the root of the response. 
    # RABL will render anything inside this hash as JSON (nested hashes, arrays, etc) 
    # Note: we could also return a new hash of specific keys and values if we didn't 
    # want the whole hash 
    my_hash 
end 

# renders: 
{"c": {"d": "e"}} 

Incidentalmente, questo è esattamente lo stesso come usando solo render :json => @my_hash a rotaie, quindi Rabl non è particolarmente utile in questo caso banale;) ma dimostra comunque la meccanica.

6

A volte è facile fare troppo imho.

Come circa appena

render json: my_hash 

E proprio come per magia siamo in grado di cancellare alcuni codice!

29

Questo funziona per valori hash arbitrari.

object false 

@values.keys.each do |key| 
    node(key){ @values[key] } 
end 

lavorato per me usando Rails 3.2.13 e Ruby 2.0.0-P195

+5

Questa è di gran lunga la risposta più elegante, sepolta in fondo. Molto più bello che costringerti a creare un 'OpenStruct'! – agmin

5

offerte Rabl a oggetti, ma non richiede una particolare ORM. Solo oggetti che supportano la notazione dei punti. Se si desidera utilizzare Rabl e tutto quello che è un hash:

@user = { :name => "Bob", :age => 27, :year => 1976 } 

allora avete bisogno di girare prima l'hash in un oggetto che supporta la notazione punto:

@user = OpenStruct.new({ :name => "Bob", :age => 27, :year => 1976 }) 

e poi all'interno di un modello Rabl trattare l'OpenStruct come qualsiasi altro oggetto:

object @user 
attributes :name, :age, :year 

si consideri che se tutto ciò che si sta facendo nel vostro app è solo occupa di hash e non ci sono oggetti o database coinvolti, si può essere meglio con un generatore JSON alternativo più personalizzato come json_builder o jbuilder.

incollato dalla pagina ufficiale wiki su github di Rabl: https://github.com/nesquena/rabl/wiki/Rendering-hash-objects-in-rabl

Problemi correlati