with tutorial simple restful rails creating create crear ruby-on-rails json actioncontroller

ruby on rails - tutorial - cómo manejar excepciones en el código RESTful basado en JSON?



rails api tutorial (4)

(Encontré la respuesta justo antes de presionar [Publicar su pregunta]. Pero esto podría ayudar a otra persona también ...)

La respuesta es usar rescue_from de ActionController, como se describe en esta guía y documentado here . En particular, puede reemplazar la representación predeterminada de los archivos 404.html y 500.html predeterminados a lo largo de estas líneas:

class ApplicationController < ActionController::Base rescue_from ActiveRecord::RecordNotFound, :with => :record_not_found private def record_not_found(error) render :json => {:error => error.message}, :status => :not_found end end

Tengo una aplicación de "software como servicio" que usa JSON comunicada a través de una API RESTful.

En pocas palabras: ¿cuáles son las mejores prácticas para capturar e informar excepciones cuando se utiliza una API RESTful con intercambio de datos JSON?

Mi primer pensamiento fue ver qué hace Rails al generar un andamio, pero eso claramente no es correcto. Aquí hay un extracto:

class MumblesController < ApplicationController # GET /mumbles/1 # GET /mumbles/1.json def show @mumble = Mumble.find(params[:id]) respond_to do |format| format.html # show.html.erb format.json { render json: @mumble } end end end

En este caso, si el código JSON envía una identificación inexistente, por ejemplo

http://www.myhost.com/mumbles/99999.json

entonces Mumble.find () levantará ActiveRecord :: RecordNotFound. ActionController captará eso y presentará una página de error en HTML. Pero HTML es inútil para el cliente que está esperando JSON.

Podría solucionar esto envolviendo el Mumble.find () en un begin ... rescue RuntimeError bloque begin ... rescue RuntimeError y renderizar un estado JSON =>: unaprocessable_entity o algo así.

Pero ¿qué pasa si la aplicación del cliente envía una ruta no válida, por ejemplo:

http://www.myhost.com/badtypo/1.json

¿Se supone que una aplicación basada en JSON detecta eso y devuelve un error en JSON? Si es así, ¿dónde capturo eso sin profundizar en ActionDispatch?

Entonces, en general, ¿punt y dejo que ActionController genere HTML si hay un error? Eso no se siente bien ...


Como desarrollador, también querrá ver rastros (preferiblemente con líneas útiles, filtrando las gemas). Y hacer los rastros invisibles para la producción:

rescue_from StandardError do |exception| # Handle only JSON requests raise unless request.format.json? err = {error: exception.message} err[:backtrace] = exception.backtrace.select do |line| # filter out non-significant lines: %w(/gems/ /rubygems/ /lib/ruby/).all? do |litter| not line.include?(litter) end end if Rails.env.development? and exception.is_a? Exception # duplicate exception output to console: STDERR.puts [''ERROR:'', err[:error], ''''] .concat(err[:backtrace] || []).join "/n" render :json => err, :status => 500 end


No existe un consenso claro sobre cómo mantener un estándar consistente para escribir el código API de JSON, pero este es un poco de lo que practico (más de lo que usted solicitó):

  1. Mantenlo simple: trata de mantenerte tranquilo. Los métodos personalizados pueden hacer que las cosas sean más complejas rápidamente.
  2. Haga que el servidor devuelva códigos de error nativos, y use ''rescue_from'' para capturar, y
  3. en otros casos, renderiza los códigos de respuesta HTTP de Rails, que pueden ser dirigidos específicamente por la aplicación cliente.

En su caso, es posible que los Rails respondan a y respondan con la ayuda de html / json / otras respuestas con gracia. E incluso en su solución, seguirá representando efectivamente el HTML, pero eso no es lo que interpretará su aplicación cliente, que en su lugar leerá el encabezado HTTP y obtendrá el código de respuesta HTTP, que es lo que está desencadenando su ''rescue_from'' .


Si ayuda a alguien, esto es lo que hice como atrapar todo para mi API puramente json:

En su ApplicationController que hereda cada controlador específico, agregue

# app/controllers/api/v1/application_controller.rb # ... rescue_from StandardError do |exception| render json: { :error => exception.message }, :status => 500 end # ...

  • basado principalmente en la respuesta de fearless_fool