2012-04-26 11 views
10

Me encuentro con un problema donde estoy trabajando con el método as_json, y cómo devolver el objeto eficientemente en JSON Y es también un objeto como JSON, donde el objeto belongs_to tiene su propio objeto belongs_to. El código probablemente lo explicaría mejor.Rails as_json issue - Cómo incluir objetos anidados de manera eficiente?

El No-Trabajo Camino clase

Alerta

class Alert < ActiveRecord::Base 
    belongs_to :message 
    # for json rendering 
    def as_json(options={}) 
     super(:include => :message) 
    end 
end 

clase Message

def as_json(options={}) 
    super(methods: [:timestamp, :num_photos, :first_photo_url, :tag_names], 
      include: { camera: { only: [:id, :name] }, 
         position: { only: [:id, :name, :address, :default_threat_level ]}, 
         images: { only: [:id, :photo_url, :is_hidden]} }) 
    end 

El problema con esta configurar primero es que cuando tengo un objeto Alerta y llame al

alert.as_json() 

me sale todos los atributos de Alerta y todos los atributos de mensaje, pero ninguno de los otros atributos de mensaje que yo quiero, al igual que la cámara, posición, etc.

Aquí está la "Está funcionando, pero probablemente no es correcto diseño Way"

Alerta Clase

class Alert < ActiveRecord::Base 

    belongs_to :message 

    # for json rendering 
    def as_json(options={}) 
     super().merge(:message => message.as_json) 
    end 
end 

Mensajes Clase

# for json rendering 
    def as_json(options={}) 
    super(methods: [:timestamp, :num_photos, :first_photo_url, :tag_names]) 
      .merge(:camera => camera.as_json) 
      .merge(:position => position.as_json) 
      .merge(:images => images.as_json) 
    end 

En esta segunda configuración, obtengo todos los atributos anidados de Messages como yo quiero.

Mi pregunta, ¿me falta alguna Convención de Rails para hacer esto correctamente? Parece que debería/debería haber una manera más fácil.

Respuesta

3

¿Qué versión de Rails estás usando? Este es un error conocido en versiones anteriores de Rails, supuestamente corregido con this pull request. Tu sintaxis me parece correcta, ¿entonces tal vez este es tu problema?

Como acotación al margen, es posible que también desee obtener de la nueva active_model_serializers de José Valim (rieles miembro de núcleo). Al menos puede permitirle solucionar su problema de una manera más elegante.

+0

Bueno, parece que lo arreglaron con la solicitud de extracción, pero nunca sacaron en una versión.Gracias por el enlace, aclaro algunos problemas. – bluedevil2k

+1

Para el registro, lo que obtuve de esa RP es: 1) trato de usar una gema específica para la api json (prefiero los serializadores de modelo activo) 2) Si no quiere/no puede hacer eso, anule 'serialized_hash 'en lugar de' as_json' en todos sus modelos. Simplemente reemplace 'as_json' por' serialized_hash'. Sus modelos generarán correctamente las dependencias incluidas. – kikito

+0

gracias kikito, corrección menor, es 'serializable_hash' – trans1t

1

Le recomendaría echar un vistazo a la gema RABL (siglas en inglés de Ruby API Builder Language) (railscast, github). Le ofrece una DSL para definir la estructura de su respuesta JSON (y también XML) en plantillas (como Haml o CoffeeScript). También es compatible con parciales.

7

La mejor respuesta para mí fue usar serializable_hash. @kikito tocó esto en su comentario, pero hubo un error tipográfico que le impidió trabajar. No es , es serializable_hash.

Literalmente acaba de encontrar + reemplazar as_json con serializable_hash y este error desaparece. (Todavía no está solucionado en Rails 4.0.2 de hoy). También obtendrá el beneficio de tener más facilidad para implementar API XML más tarde (¡algunas personas aún usan eso!).

+1

gracias, funcionó para mí – toby

Cuestiones relacionadas