¿Cómo reemplazar a json en Rails?
Actualización:
Esta cuestión no fue explorada adecuadamente. El verdadero problema radica en render :json
.
El primer pegado de código en la pregunta original dará el resultado esperado. Sin embargo, todavía hay una advertencia. Ver este ejemplo:
render :json => current_user
Es NO lo mismo que
render :json => current_user.to_json
Es decir, render :json
no llamará automáticamente al método to_json
asociado con el objeto User. De hecho , si to_json
está siendo anulado en el User
modelo, render :json => @user
generará el ArgumentError
descrito a continuación.
Resumen
# works if User#to_json is not overridden
render :json => current_user
# If User#to_json is overridden, User requires explicit call
render :json => current_user.to_json
Todo esto me parece tonto. Esto parece estar diciéndome que render
no está llamando a Model#to_json
cuando se especifica type :json
. ¿Alguien puede explicar lo que realmente está pasando aquí?
Cualquier genii que pueda ayudarme con esto probablemente pueda responder a mi otra pregunta: Cómo construir una respuesta JSON combinando @foo. to_json (opciones) y @bars. to_json(opciones) en Rails
Pregunta original:
He visto algunos otros ejemplos en SO, pero no hago lo que estoy buscando.
Estoy tratando:
class User < ActiveRecord::Base
# this actually works! (see update summary above)
def to_json
super(:only => :username, :methods => [:foo, :bar])
end
end
Estoy recibiendo {[15] {} en[20]}
/usr/lib/ruby/gems/1.9.1/gems/activesupport-2.3.5/lib/active_support/json/encoders/object.rb:4:in `to_json
¿Alguna idea?
4 answers
Está obteniendo ArgumentError: wrong number of arguments (1 for 0)
porque to_json
necesita ser sobrescrito con un parámetro, el hash options
.
def to_json(options)
...
end
Explicación más larga de to_json
, as_json
, y la representación:
En ActiveSupport 2.3.3, se agregó as_json
para resolver problemas como el que ha encontrado. La creacióndel json debe estar separada de la representación del json.
Ahora, cada vez que to_json
se llama a un objeto, as_json
se invoca para crear los datos estructura, y luego ese hash se codifica como una cadena JSON usando ActiveSupport::json.encode
. Esto sucede para todos los tipos: objeto, numérico, fecha, cadena, etc. (consulte el código de ActiveSupport).
Los objetos ActiveRecord se comportan de la misma manera. Hay una implementación predeterminada as_json
que crea un hash que incluye todos los atributos del modelo. Debe reemplazar as_json
en su Modelo para crear la estructura JSON que desea. as_json
, al igual que el antiguo to_json
, toma un hash de opción donde puede especificar atributos y métodos para incluir declarativamente.
def as_json(options)
# this example ignores the user's options
super(:only => [:email, :handle])
end
En su controlador, render :json => o
puede aceptar una cadena o un objeto. Si es una cadena, se pasa a través como el cuerpo de respuesta, si es un objeto, se llama to_json
, lo que desencadena as_json
como se explicó anteriormente.
Por lo tanto, siempre y cuando sus modelos estén correctamente representados con as_json
anula (o no), su código de controlador para mostrar un modelo debe tener este aspecto:
format.json { render :json => @user }
La moraleja de la historia es: Evita llamar to_json
directamente, permita que render
haga eso por usted. Si necesita modificar la salida JSON, llame a as_json
.
format.json { render :json =>
@user.as_json(:only => [:username], :methods => [:avatar]) }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-04 15:23:27
Si tiene problemas con esto en Rails 3, anule serializable_hash
en lugar de as_json
. Esto también te dará el formato XML gratis:)
Esto me llevó una eternidad averiguarlo. Espero que eso ayude a alguien.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-09-02 18:46:45
Para las personas que no quieren ignorar las opciones de los usuarios, pero también agregar sus opciones:
def as_json(options)
# this example DOES NOT ignore the user's options
super({:only => [:email, :handle]}.merge(options))
end
Espero que esto ayude a alguien:)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-04 05:28:10
No sobrescriba to_json, sino as_json. Y de as_json llama a lo que quieras:
Prueba esto:
def as_json
{ :username => username, :foo => foo, :bar => bar }
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-03 19:25:16