2009-03-03 13 views
18

Estoy tratando de presentar un índice de todos los artículos junto con un artículo completo a través de JSON en mi aplicación de rieles, pero me cuesta un poco encontrar la manera de hacerlo.Ruby on Rails Serialización avanzada de JSON

Aquí está mi controlador de ahora:

if params[:id] 
    @article = Article.find(params[:id]) 
else 
    @article = Article.published.not_draft.by_recent.first 
end 

respond_to do |format| 

format.js { render :json => @article.to_json(
:except => [ :created_at, :updated_at, :draft, :id, :publish ], 
:include => { 
    :comments => { 
     :only => [:body] 
    } 
}), 
:callback => params[:callback]} 
end 

Lo que me gustaría hacer en la respuesta es añadir un índice de todos los artículos, así:

@index = Article.find(:all, :select => 'id, title') 

La única manera que' He podido hacerlo, coloca tanto el índice como el artículo en un hash o matriz y luego lo puse en JSON.

@response = { :item => @article, :index => @index } 

código completo con ambos:

@index = Article.find(:all, :select => 'id, title') 

if params[:id] 
    @article = Article.find(params[:id]) 
else 
    @article = Article.published.not_draft.by_recent.first 
end 

@response = { :item => @article, :index => @index } 

respond_to do |format| 

format.js { render :json => @response.to_json(), :callback => params[:callback]} 

end 

Esto estaría bien, excepto que ahora no puedo especificar :include o :except y conseguir que se muestra correctamente.

Respuesta

1

usted debería ser capaz de anidar el :include, :except, etc., así:

:except => {:item => [ :created_at, :updated_at, :draft, :id, :publish ]}... 

Si eso no funciona, lo convierten en un objeto (por ejemplo, un OpenStruct) en lugar de un hash.

- Markus

2

Para que quede claro que el código anterior funciona con el: incluir y: excepción. Y con las obras quiero decir que no arroja un error. El problema es que incluye comentarios para cada artículo en el índice. Solo estoy buscando incluir comentarios para el elemento: y no ninguno de los artículos enumerados en el índice.

No pude obtener el anidamiento para que funcionara como hash o como objeto de OpenStruct.

Anidando en: incluye arroja un error, anidando en: excepto no arroja un error, pero no se filtra nada,: created_at, etc. siguen apareciendo.

... 

@response = { :item => @article, :index => @index } 

format.js { render :json => @response.to_json(
:except => {:item => [ :created_at, :updated_at, :draft, :id, :publish ]}, 
:include => { :item => { 
     :comments => { 
       :only => [:body] 
     } 
}}), 
:callback => params[:callback]} 
end 
1

a_json tiene la opción: método que incluye el resultado de cualquier método que se nombra, se podría definir un método en el que el modelo que devuelve los datos adicionales que desee en su JSON.

28

Indique la solución a su pregunta. Lo más probable es que desee crear un hash para procesar en JSON. La forma preferida de hacer esto ahora es proporcionando una implementación para el método as_json. as_json proporciona un medio formal para personalizar la salida de json construyendo un hash que contiene los datos que desea codificar.

Un tratamiento más completo de cómo as_json y to_json interactúan se puede encontrar en Jonathan Julian's weblog.

1

(Por favor, acepte una respuesta)

creo que el vínculo que mantiene nirvdrum dio su respuesta. Solo respondo porque nadie ha mencionado encode_json.

En su caso, usted solo debe tratar con as_json.Ya sea construyendo un hash (con varias llamadas al as_json) y enviándolo a render :json => ... (sin la llamada al to_json) o simplemente implementando as_json en su modelo y dejando que los rieles hagan todo el trabajo. (Pero sospecho que necesitará la primera.)

Si realmente necesita algunos js extravagantes en su respuesta representada, puede implementar encode_json en sus clases (nuevamente, no to_json). Por ejemplo:

class JsEmptyClosure 
    def encode_json(*args) 
    "jQuery[\"noop\"] || function(){}" 
    end 
    def as_json(*args) self end 
end 

Esto ahora responderá a to_json con js válidos (pero tenga en cuenta que no es en realidad JSON).

0

Gracias por la pregunta, puedo personalizar mi formato json para un modelo con varias asociaciones.

render json: @ posts.to_json (

: excepto => [: created_at,: updated_at,: user_id],

: include => {

: user => {: only => [: email,: phone]},

: location => {: only => [: title,: lat,: lon,: street,: city,: state, : zipcode] },

: archivos => {: only => [: Imagen]}

}
)

0

recomendaría sobrecargar el método de atributos para devolver un hash alternat que se utilizará de forma automática en la producción a_json .

class Article 
    def attributes 
    { ... } # define your hash that you want to return at the '...' 
    end 
end 

Para mí, esto parece mucho más simple que perder el tiempo con to_json directamente.