Rails: ¿Deshabilitar la raíz en JSON solo para acciones específicas del controlador?

Sé cómo deshabilitar el elemento raíz a nivel mundial, a la Rails 3.1 include_root_in_json o usando ActiveRecord::Base.include_root_in_json = false, pero solo quiero hacer esto para algunas solicitudes JSON (no globalmente).

Hasta ahora, lo he estado haciendo así:

@donuts = Donut.where(:jelly => true)
@coffees = Coffee.all
@breakfast_sandwiches = Sandwich.where(:breakfast => true)

dunkin_donuts_order = {}
dunkin_donuts_order[:donuts] = @donuts
dunkin_donuts_order[:libations] = @coffees
dunkin_donuts_order[:non_donut_food] = @breakfast_sandwiches

Donut.include_root_in_json = false
Coffee.include_root_in_json = false

render :json => dunkin_donuts_order

Donut.include_root_in_json = true
Coffee.include_root_in_json = true

Hay alrededor de 5 casos en los que tengo que hacer esto, a veces con más de un modelo, y no se siente nada limpio. Había intentado poner esto en around_filters, pero las excepciones estaban interrumpiendo el flujo, y eso también se estaba poniendo peludo.

¡Tiene que haber una mejor manera!

preguntado el 30 de agosto de 11 a las 23:08

Esto no responde directamente a su pregunta, pero responde a la que vine aquí buscando: PUEDE suprimir la raíz en llamadas individuales a to_json, p.ej Donut.to_json(root: false) -

2 Respuestas

La respuesta es, lamentablemente, sí y no.

Sí, podría decirse que lo que ha hecho anteriormente se puede hacer mejor. No, Rails no le permitirá agregar la raíz por acción. El renderizado JSON simplemente no se construyó con ese tipo de flexibilidad en mente.

Dicho esto, esto es lo que haría:

  1. Kit include_root_in_json a false para aquellos modelos que tienen root en función de la acción (como Donut y Coffee encima).
  2. Anular as_json para permitir una mayor flexibilidad. He aquí un ejemplo:

    # in model.rb
    def as_json(options = nil)
        hash = serializable_hash(options)
        if options && options[:root]
            hash = { options[:root] => hash }
        else
            hash = hash
        end
    end
    

    Este ejemplo lo hará para que, opcionalmente, pueda pasar una raíz, pero por defecto no tiene raíz. Alternativamente, podría escribirlo al revés.

  3. Desde que anulaste as_json, tendrá que modificar sus llamadas de procesamiento de forma adecuada. Entonces, para Donutlo harías render :json => @donut.to_json.

¡Espero que esto ayude!

respondido 13 mar '14, 22:03

Gracias. Dejé de dispararme en el pie y cambié a RABL y nunca he mirado atrás. ¡Mucho mejor! - neezer

Buena respuesta. pero no tiene que llamar a as_json (). to_json porque to_json llama automáticamente a su anulación de as_json. - Nada Aldahleh

Gracias, @NadaAldahleh. Lo he aclarado en mi respuesta. - Logan Leger

Puede establecer include_root_in_json por modelo ejemplo, y no afectará a la clase (ver class_attribute en la API de rieles para obtener una descripción de este comportamiento). Por lo tanto, puede establecer un valor predeterminado razonable en el nivel de clase y luego establecer un valor diferente en cada instancia en los controladores relevantes.

Ejemplo:

@donuts = Donut.where(:jelly => true).each {|d| d.include_root_in_json = false }

Para mayor comodidad, puede crear un método de utilidad que acepte una matriz de instancias de modelo y establezca el valor en todas ellas.

Respondido 07 Feb 13, 03:02

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.