2011-01-30 14 views
34

Tengo un modelo con datos que nunca deberían incluirse cuando se representa como json. Así que implementé el método de clase 'as_json' para comportarme adecuadamente. El problema es que cuando otros modelos con asociaciones con este modelo hacen json, mi costumbre as_json no se está llamando.as_json no está llamando a as_json en asociaciones

class Owner < ActiveRecord::Base 
    has_one :dog 

    def as_json(options={}) 
    puts "Owner::as_json" 
    super(options) 
    end 
end 

class Dog < ActiveRecord::Base 
    belongs_to :owner 

    def as_json(options={}) 
    puts "Dog::as_json" 
    options[:except] = :secret 
    super(options) 
    end 
end 

entorno de desarrollo de carga (Rails 3.0.3)
ruby-1.9.2-p136: 001> d = Dog.first
=>#<Dog id: 1, owner_id: 1, name: "Scooby", secret: "I enjoy crapping everwhere">
ruby-1.9.2-p136 : 002> d.as_json
perro :: as_json
=> { "perro" => { "id" => 1, "nombre" => "Scooby", "OWNER_ID" => 1}}
rubí -1.9.2-p136: 004> d.owner.as_json (: include =>: dog)
Propietario :: as_json
=> {"owner" => {"id" => 1, "name" => "Shaggy",: dog => {"id" => 1, "nombre" => "Scooby", "owner_id" "=> 1, "secreto"=>" me gusta crapping a todas partes "}}}

Gracias por la ayuda

+0

tengo este problema, así, durante el uso de Mongoid on Rails 3.0.9. – arbales

Respuesta

21

Esto es known bug en Rails. (El problema está marcado como cerrado debido a la migración a problemas de Github del rastreador de errores anterior, pero sigue siendo un problema desde Rails 3.1.)

+0

Hmm - enlace roto. – arbales

+1

Sí, la migración a problemas de Github rompió todos los enlaces existentes. :(Fixed. – John

+1

Ah, la solución es: https://github.com/rails/rails/pull/2200 – arbales

2

me encontré con el mismo problema. Yo quería que esto funcione:

render :json => @favorites.as_json(:include => :location) 

pero no lo hizo, así que acabé añadiendo un index.json.erb con lo siguiente:

<% favs = @favorites.as_json.each do |fav| %> 
    <% fav["location"] = Location.find(fav["location_id"]).as_json %> 
<% end %> 
<%= favs.to_json.html_safe %> 

no una solución - sólo un trabajo alrededor. Me imagino que hiciste lo mismo.

1

Actualización @John señaló que este es un error conocido en Rails. Un parche para arreglarlo parece ser: en https://github.com/rails/rails/pull/2200. Sin embargo, puedes probar RABL, porque es dulce.

Siempre he estado frustrado al pasar un conjunto complejo de opciones para crear las vistas JSON que quiero. Tu problema, que experimenté con Mongoid en Rails 3.0.9, me impulsó a escribir plantillas JSON. Pero en realidad, si se trata de relaciones o propiedades api personalizadas, resulta que las plantillas son mucho mejores.

Además, tratar con diferentes productos me parece la capa Ver, así que Me decidí por usar RABL, el lenguaje de plantillas API. Hace que sea muy fácil construir JSON válido e incluir cualquier asociación o campo.

No es una solución al problema, pero es una solución mejor para el caso de uso.

8

Como se reconoció anteriormente, este es un problema con la base de Rails. El parche de rieles here aún no se aplicó y parece al menos un poco controvertido, por lo que dudo en aplicarlo localmente. Incluso si se aplica como un parche de mono, podría complicar futuras actualizaciones de rieles.

Todavía estoy pensando en RABL sugerido anteriormente, parece útil. Por el momento, prefiero no agregar otro lenguaje de plantillas de visualización en mi aplicación. Mis necesidades actuales son muy pequeñas.

Así que aquí hay una solución que no requiere un parche y funciona para la mayoría de los casos simples. Esto funciona en el método de la asociación as_json que le gustaría haber llamado parece

def as_json(options={}) 
    super(<... custom options ...>) 
end 

En mi caso tengo Schedule modelo que tiene muchas Events

class Event < ActiveRecord::Base 

    # define json options as constant, or you could return them from a method 
    EVENT_JSON_OPTS = { :include => { :locations => { :only => [:id], :methods => [:name] } } } 

    def as_json(options={}) 
    super(EVENT_JSON_OPTS) 
    end 
end 

class Schedule < ActiveRecord::Base 
    has_many :events 

    def as_json(options={}) 
    super(:include => { :events => { Event::EVENT_JSON_OPTS } }) 
    end 
end 

Si ha seguido la pauta de que en cualquier momento :include una asociación en sus métodos as_json(), define las opciones que necesita como una constante en el modelo que se va a referenciar, esto funcionaría para niveles arbitrarios de asociaciones. NOTA Solo necesitaba el primer nivel de asociación personalizado en el ejemplo anterior.

1

He encontrado que serializable_hash funciona como era de esperar as_json al trabajo, y siempre se llama:

def serializable_hash(options = {}) 
    result = super(options) 
    result[:url] = "http://.." 
    result 
    end 
+0

Esta es la solución real al problema. El error/'función' todavía está allí en Rails 5.1 y no parece que será arreglado. –

Cuestiones relacionadas