2012-01-20 10 views
10

Parece que al devolver un objeto que contiene un atributo "tipo" como JSON desde una aplicación Rails 3.1, el atributo "tipo" no está incluido. Supongamos que tengo lo siguiente:Incluyendo el atributo "tipo" en json reply_with Rails 3.1

Un modelo con la correspondiente tabla STI Animal. Modelos Cat, Dog y Fish que heredan Animal.

Al devolver un animal a través de JSON, deseo incluir la columna "tipo", pero esto no está ocurriendo:

jQuery.ajax("http://localhost:3001/animals/1", {dataType: "json"}); 

rendimientos:

responseText: "{"can_swim":false,"created_at":"2012-01-20T17:55:16Z","id":1,"name":"Fluffy","updated_at":"2012-01-20T17:55:16Z","weight":9.0}" 

Parece que este es un problema con to_json:

bash-3.2$ rails runner 'p Animal.first.to_yaml' 
"--- !ruby/object:Cat\nattributes:\n id: 1\n type: Cat\n weight: 9.0\n name: Fluffy\n can_swim: false\n created_at: 2012-01-20 17:55:16.090646000 Z\n updated_at: 2012-01-20 17:55:16.090646000 Z\n" 

bash-3.2$ rails runner 'p Animal.first.to_json' 
"{\"can_swim\":false,\"created_at\":\"2012-01-20T17:55:16Z\",\"id\":1,\"name\":\"Fluffy\",\"updated_at\":\"2012-01-20T17:55:16Z\",\"weight\":9.0}" 

¿Alguien conoce el razonamiento detrás de este comportamiento y cómo anularlo?

Respuesta

6

Anule el método as_json. Es usado por to_json para producir la salida. Puede hacer algo como:

def as_json options={} 
{ 
    id: id, 
    can_swim: can_swim, 
    type: type 
} 
end 
+0

Excelente, gracias - ¡esto parece hacer el truco! – cyrusd

+5

Esto parece un buen compromiso para reducir la redundancia: def as_json (opciones = {}) {tipo: tipo} .merge super final – cyrusd

+0

De nada. Me gusta sobrescribir as_json porque sé cómo estoy convirtiendo mis objetos a JSON y solo estoy convirtiendo lo que realmente necesito convertir. – lucapette

0

Para mí, en Rails 2.3.12, lo anterior no funciona.

puedo (en mi modelo, por supuesto) hacer algo como esto:

class Registration < ActiveRecord::Base 

    def as_json(options={}) 
    super(options.merge(:include => [:type])) 
    end 

end 

Pero que causa a_json para lanzar un error como este:

NoMethodError: undefined method `serializable_hash' for "Registration":String 

He trabajado con alrededor de este esto, que perfora este método en el objeto que quiero exportar

class Registration < ActiveRecord::Base 

    def as_json(options={}) 
    super(options.merge(:include => [:type])) 
    end 

    def type 
    r = self.attributes["type"] 
    def r.serializable_hash(arg) 
     self 
    end 
    r 
    end 
end 

Así que en mi aplicación, he puesto esto en una mixin:

module RailsStiModel 
    # The following two methods add the "type" parameter to the to_json output. 
    # see also: 
    # http://stackoverflow.com/questions/8945846/including-type-attribute-in-json-respond-with-rails-3-1/15293715#15293715 
    def as_json(options={}) 
    super(options.merge(:include => [:type])) 
    end 

    def type 
    r = self.attributes["type"] 
    def r.serializable_hash(arg) 
     self 
    end 
    r 
    end 
end 

Y ahora en mi clase del modelo (s), añado:

include RailsStiModel 
0

Aquí está mi solución que puede mantener la función original de as_json.

def as_json(options={}) 
    options = options.try(:clone) || {} 
    options[:methods] = Array(options[:methods]).map { |n| n.to_sym } 
    options[:methods] |= [:type] 

    super(options) 
end 
14

Esto es lo que hice. Simplemente agrega el type faltante al conjunto de resultados

def as_json(options={}) 
    super(options.merge({:methods => :type})) 
    end 
Cuestiones relacionadas