ruby-on-rails - serializers - serializer new rails
por defecto para to_json en Rails con: include (5)
Digamos que tengo una publicación modelo que pertenece a un usuario. Para convertir a json, hago algo como esto.
@reply.to_json(:include => {:user => {:only => [:email, :id]},
:only => [:title, :id])
Sin embargo, quiero establecer algunos valores predeterminados para esto, así que no tengo que especificar: solo cada vez. Estoy tratando de anular as_json para lograr esto. Cuando agrego as_json en el modelo de usuario, se llama cuando hago @ user.to_json, pero cuando el usuario se incluye en @ reply.to_json, se omite my overriden as_json para User.
¿Cómo hago este trabajo?
Gracias
Así que descubrí que el problema es que for incluye, en lugar de llamar a as_json para generar el json, Rails llama directamente serializable_hash. El parche del mono soluciona el problema. Pon esto en un inicializador
module ActiveRecord #:nodoc:
module Serialization
def serializable_hash(options = nil)
options = options.try(:clone) || {}
options[:except] = Array.wrap(options[:except]).map { |n| n.to_s }
options[:except] |= Array.wrap(self.class.inheritance_column)
hash = super(options)
#serializable_add_includes(options) do |association, records, opts|
#hash[association] = records.is_a?(Enumerable) ?
#records.map { |r| r.serializable_hash(opts) } :
#records.serializable_hash(opts)
#end
serializable_add_includes(options) do |association, records, opts|
hash[association] = records.is_a?(Enumerable) ?
records.map { |r| r.as_json(opts.merge(:no_root => true)) } :
records.as_json(opts.merge(:no_root => true))
end
hash
end
end
end
module ActiveModel
# == Active Model JSON Serializer
module Serializers
module JSON
def as_json(options = nil)
hash = serializable_hash(options)
if include_root_in_json and !options[:no_root]
custom_root = options && options[:root]
hash = { custom_root || self.class.model_name.element => hash }
end
hash
end
end
end
end
Observe cómo la llamada serializable_hash se reemplaza con as_json (con un parámetro adicional para suprimir la adición de root in includes). Ahora, si tiene as_json en su modelo, se llamará incluso en caso de que se incluya
Como las opciones en circunstancias pueden ser nulas, debemos ser conscientes de ello:
module ActiveModel
# == Active Model JSON Serializer
module Serializers
module JSON
def as_json(options)
options ||= {}
hash = serializable_hash(options)
if include_root_in_json and !options[:no_root]
custom_root = options && options[:root]
hash = { custom_root || self.class.model_name.element => hash }
end
hash
end
end
end
end
En el modelo de respuesta:
def as_json(options = {})
super options.merge(:methods => [:user], :only => [:id, :title])
end
Y en el modelo de usuario:
def as_json(options = {})
super options.merge(:only => [:id, :email])
end
Cuando la asociación se incluye como un método y no como una inclusión, ejecutará el .to_json en él.
Podría agregar otro método a ActiveRecord :: Base, como self.to_minimal_json (* only_fields) y crear su llamada .to_json allí.
poco espectacular, pero puede funcionar.
Puede hacer esto anulando serializable_hash
en su modelo, así:
class Reply < ActiveRecord::Base
def serializable_hash(options={})
options = {
:include => {:user => {:only => [:email, :id]},
:only => [:title, :id]
}.update(options)
super(options)
end
end
Esto afectará a todos los métodos serializables, incluyendo serializable_hash
, to_json
y to_xml
.