En Rails, ¿cómo se procesa JSON usando una vista?

125

Supongamos que está en el controlador de su usuario y desea obtener una respuesta json para una solicitud de presentación, sería bueno si pudiera crear un archivo en sus vistas / usuarios / directorio, llamado show.json y después de que sus usuarios # show se completa la acción, representa el archivo.

Actualmente necesita hacer algo en la línea de:

def show
  @user = User.find( params[:id] )
  respond_to do |format|
    format.html
    format.json{
      render :json => @user.to_json
    }
  end
end

Pero sería bueno si pudieras crear un archivo show.json que automáticamente se procesa así:

def show
  @user = User.find( params[:id] )
  respond_to do |format|
    format.html
    format.json
  end
end

Esto me ahorraría toneladas de dolor y eliminaría esa sensación horriblemente sucia que tengo cuando renderizo mi json en el controlador

Mateo
fuente
Mirando esta publicación ahora, parece que esto no me ahorraría mucho, pero tengo casos más complicados, créanme cuando digo que esto me está causando dolores de cabeza
Matthew
1
En Rails 3, solo puede llamar format.jsoncon un show.json.erbarchivo. Mira mi respuesta.
James Lim

Respuestas:

64

Debería poder hacer algo como esto en su respond_tobloque:

respond_to do |format|
    format.json 
    render :partial => "users/show.json"
end

que representará la plantilla en app/views/users/_show.json.erb.

Alex Reisner
fuente
55
Esto es bueno, pero rápidamente encontrará que erb es una forma dolorosa de generar json. Mira mi respuesta para algunas alternativas.
tybro0103
1
¿Hay alguna manera de hacerlo sin usar un parcial?
Wylliam Judd
55

Intente agregar una vista. users/show.json.erbEsto se debe representar cuando realiza una solicitud para el formato JSON, y obtiene el beneficio adicional de que también lo representa erb, por lo que su archivo podría verse así

{
    "first_name": "<%= @user.first_name.to_json %>",
    "last_name": "<%= @user.last_name.to_json %>"
}
erik
fuente
9
Es posible que desee utilizar en @user.first_name.to_jsonlugar de escape_javascript. Hay algunas diferencias sutiles entre lo que JS permite y lo que es estrictamente JSON. (Y esas diferencias se están volviendo importantes a medida que los navegadores implementan sus propios analizadores JSON.)
James A. Rosen
1
Probablemente debería cambiar las comillas simples a comillas dobles, ya que JSON (a diferencia de JS) solo acepta cadenas de comillas dobles.
Abe Voelker
1
Esto es bueno, pero rápidamente encontrará que erb es una forma dolorosa de generar json. Mira mi respuesta para algunas alternativas.
tybro0103
Sé que esta es una respuesta antigua, pero está completamente equivocada. to_json devolverá una cadena json formateada "", por lo que el json resultante nunca será válido con comillas adicionales ("" valor ""). Además, si el nombre de usuario es nulo, el json resultante tendrá la cadena "nulo" como valor. Además, <% = utiliza el escape html, que alterará los caracteres html en los datos de entrada.
d4n3
Creo que también debes eliminar las comillas, de lo <%= xyz.to_json %>contrario te quedarán comillas adicionales.
akostadinov
32

Como otros han mencionado, necesita una vista users / show.json, pero hay opciones a considerar para el lenguaje de plantillas ...

ERB

Funciona fuera de la caja. Excelente para HTML, pero rápidamente encontrará que es horrible para JSON.

RABL

Buena solución. Tiene que agregar una dependencia y aprender su DSL.

JSON Builder

Mismo trato que RABL: buena solución. Tiene que agregar una dependencia y aprender su DSL.

Rubí liso

Ruby es increíble para generar JSON y no hay nada nuevo que aprender, ya que puedes invocar to_jsonun Hash o un objeto AR. Simplemente registre la extensión .rb para plantillas (en un inicializador):

ActionView::Template.register_template_handler(:rb, :source.to_proc)

Luego cree la vista users / show.json.rb:

@user.to_json

Para obtener más información sobre este enfoque, visite http://railscasts.com/episodes/379-template-handlers

tybro0103
fuente
77
Tenga en cuenta que en los rieles 4, el controlador de plantilla .ruby está registrado de forma predeterminada github.com/rails/rails/commit/de1060f4e02925c12004f2 para que pueda omitir el registro de .rb y nombrar a sus usuarios de archivo / show.json.ruby.
Tim Diggins
1
Además, para actualizar esto aún más, json_builder ha sido reemplazado por github.com/rails/jbuilder .
Tim Diggins
27

RABL es probablemente la mejor solución para esto que he visto si está buscando una alternativa más limpia a la sintaxis de ERb. json_builder y argonaut, que son otras soluciones, parecen algo obsoletos y no funcionarán con Rails 3.1 sin algunos parches.

RABL está disponible a través de una gema o consulte el repositorio de GitHub; buenos ejemplos también

https://github.com/nesquena/rabl

zapnap
fuente
21

Solo para actualizar esta respuesta por el bien de otros que terminan en esta página.

En Rails 3, solo necesita crear un archivo en views/users/show.json.erb. El @userobjeto estará disponible para la vista (al igual que lo estaría para html). Ya ni siquiera lo necesita to_json.

Para resumir, es solo

# users contoller
def show
  @user = User.find( params[:id] )
  respond_to do |format|
    format.html
    format.json
  end
end

y

/* views/users/show.json.erb */
{
    "name" : "<%= @user.name %>"
}
James Lim
fuente
1
Respondí esto hace 1,5 años. Hoy en día solo uso respond_with cada vez que necesito JSON, por ejemplo respond_with @user, only: [:name]. Consulte este tutorial para obtener más información.
James Lim
1
Solo para agregar a esta respuesta, esto es realmente peligroso por dos razones: permite la inyección de datos del usuario porque no escapa a las nuevas líneas y las barras invertidas, y también <% = html escapa a los datos, por lo que Sean O'Connor tendrá su nombre destrozado a Sean O & apos; Connor.
d4n3
10

Simplemente agregue el show.json.erbarchivo con el contenido

<%= @user.to_json %>

A veces es útil cuando necesita algunos métodos auxiliares adicionales que no están disponibles en el controlador, es decir, image_path(@user.avatar)o algo para generar propiedades adicionales en JSON:

<%= @user.attributes.merge(:avatar => image_path(@user.avatar)).to_json %>
Priit
fuente
8
Tendría que ser <%= raw(@user.to_json) %>para evitar el escape de HTML. Lo que hago es confiar en to_json siempre que me dé lo que quiero, pero cuando quiero hacer algo más, lo moldeo con lo que generalmente es a { :blah => @user.the_blah }.to_json.
clacke
0

Soy nuevo en RoR, esto es lo que descubrí. puedes renderizar directamente un formato json

def YOUR_METHOD_HERE
  users = User.all
  render json: {allUsers: users} # ! rendering all users
END
aRtoo
fuente