2012-01-20 25 views
18

Tengo un hash de ruby ​​que me gustaría renderizar usando RABL. El hash es como la siguiente:Renderizar un simple hash Ruby con RABL

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

que estoy tratando de hacer esto con un poco de código RABL:

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

pero estoy recibiendo {"c":null}

¿Cómo puedo hacer esto con RABL?

Respuesta

22

Actualmente RABL no juega demasiado bien con los hashes. Pude solucionar esto al convertir mi hash a un formato OpenStruct (que usa una notación de puntos más compatible con RABL). Utilizando el ejemplo:

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 

resultados

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

Parece que no tiene que usar la notación de puntos si ajusta el hash en un OpenStruct. https://github.com/nesquena/rabl/wiki/Rendering-hash-objects-in-rabl – jmosesman

2

Al especificar un nodo como ese, tiene acceso al objeto @my_hash al que puede acceder a los atributos de. Así que me acaba de cambiar un poco su código para ser:

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

donde c_node es esencialmente el objeto @my_hash. Esto debe darle lo que usted está esperando (que se muestra aquí en JSON):

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

Desafortunadamente me sale este error 'método no definido 'd' para: c: Symbol' cuando se utiliza el código de seguridad. – SundayMonday

+0

¿Es '.d' un atributo válido de' @ my_hash'? Tiene que ser así, de lo contrario, lo que intentas hacer no es posible. Probé este código por mi cuenta y funcionó para un atributo válido del objeto. – iwasrobbed

2

Mi respuesta se basa parcialmente en el sitio enumeran a continuación:

Adaptado de este sitio:

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 

Definir esta tal vez en un inicializador y luego para cualquier picadillo sólo hay que poner to_openstruct y enviarla a través de a la plantilla rabl y básicamente hacer lo que jnunn muestra en la vista.

4

RABL realmente puede renderizar matrices y matrices de rubíes fácilmente, como atributos, simplemente no como el objeto raíz.Así, por ejemplo, si crea una OpenStruct así por el objeto raíz:

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

entonces se podría utilizar esta plantilla RABL:

object @my_object 

attributes :data 

Y hasta la inutilidad:

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

Alternativamente, si quiere que :c sea una propiedad de su objeto raíz, puede usar "nodo" para crear ese nodo y renderizar el hash dentro de ese 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"}} 

Por cierto, este es exactamente el mismo que acaba de usar render :json => @my_hash en los carriles, por lo RABL no es particularmente útil en este caso trivial;) Pero demuestra la mecánica de todos modos.

6

A veces es fácil de hacer demasiado imho.

¿Qué tal

render json: my_hash 

Y al igual que la magia se puede eliminar algo de código!

29

Esto funciona para valores hash arbitrarios.

object false 

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

trabajado para mí utilizando rieles 3.2.13 y Ruby 2.0.0-p195

+5

Esta es, de lejos, la respuesta más elegante, enterrada en la parte inferior. ¡Mucho mejor que forzarte a crear un 'OpenStruct'! – agmin

5

ofertas RABL en los objetos, pero no requiere un ORM en particular. Solo objetos que admiten notación de puntos. Si desea utilizar Rabl y todo lo que tienes es un hash:

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

entonces usted necesita para convertir primero el hash en un objeto que es compatible con la notación de puntos:

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

y luego dentro de una plantilla RABL tratar el OpenStruct como cualquier otro objeto:

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

considerar que si todo lo que está haciendo en su aplicación es sólo repartiendo en los hashes y no hay objetos o bases de datos implicadas, que puede ser mejor con un generador de JSON alternativo más personalizado como json_builder o jbuilder.

Pegado desde la página oficial wiki en github de RABL: https://github.com/nesquena/rabl/wiki/Rendering-hash-objects-in-rabl