to_json serializers rails new active ruby-on-rails json

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 .