tutorial respond_to rails practices crear con best ruby-on-rails-3 json rest respond-to

ruby-on-rails-3 - practices - respond_to json rails 5



Rails respond_with: ¿por qué POST devuelve una URL en lugar de los datos? (3)

El "por qué" ha sido respondido excelentemente por @ david-james. Esto es solo un breve ''cómo'' para responder a través de respond_with :

class Api::V1::UsersController < ApplicationController respond_to :json def create @user = User.create(...) respond_with @user, location: url_for([:api, :v1, @user]) end end

Esta es una pregunta "por qué funciona de esta manera", no "cómo puedo hacer que esto funcione".

Mi aplicación está llamando a una API REST de terceros que devuelve JSON y está devolviendo el resultado como parte de mi propia API JSON.

Estaba usando los métodos respond_to y respond_with Rails 3; en el caso de las solicitudes GET , esto funciona como esperaba, solo pasando por el JSON.

En el caso de POST , hace más, incluso haciendo una URL desde el objeto devuelto para pasar en una opción de :location . Pero como mi objeto es solo JSON (no ActiveRecord), recibo un error.

Por ejemplo...

# POST /api/products.json with params id=:id def create query_string = "#{user_id}&id=#{params[:id]}" @products = third_party_api_wrapper.products(query_string, ''POST'') respond_with @products end

Mi envoltorio para la API de terceros hace una solicitud POST, que vuelve bien, luego Rails devuelve un error 500 que se registra de esta manera:

NoMethodError (undefined method `{"response":{"message":"product 4e1712d9ec0f257c510013f8 selected"}}_url'' for #<MyController>

Rails quiere que mi objeto @products sepa cómo crear una URL de ubicación.

ACLARACIÓN: el objeto @products devuelto por la API de terceros es JSON puro, una cadena, que puede ver incrustada en el mensaje de registro de errores anterior. Este error se está produciendo porque Rails parece querer que el objeto sea algo más: en el soporte de API interno de Rails, es un objeto ActiveRecord.

Si sustituyo el nuevo respond_with con sytax con el estilo antiguo

respond_to do |format| format.json { render :json => @products } # note, no :location or :status options end

entonces todo funciona. Y esto es lo que he hecho, así que no tengo un problema de "cómo", sino una pregunta de "por qué".

El post de Ryan Daigle en la introducción explica que se espera lo que está sucediendo.

Mi pregunta es: ¿por qué respond_with espera algo más que datos (y el estado HTTP?), Y aparentemente solo para POST .

No estoy diciendo que esté mal, solo estoy tratando de entender el fundamento de la implementación de Rails.


Para responder a esta pregunta: "¿por qué una API debe devolver algo que no sea datos (y el estado HTTP?). No estoy diciendo que esté mal, solo estoy tratando de entender el fundamento".

No se me ocurre ningún buen razonamiento. ¡Más importante aún, no puedo ver de ninguna manera que una API pueda devolver nada, excepto una estructura de datos! (Esta pregunta no tiene sentido para mí!)

Por definición, una llamada a la API debe devolver una estructura de datos. (Podría ser tan simple como una cadena. Podría ser JSON. Podría ser XML.) Puede usar la negociación de contenido para decidir el formato. Puede o no ser un esquema estricto, pero al menos una biblioteca cliente debe poder analizarlo. En cualquier caso, la documentación de la API debe aclarar esto y atenerse a ella. ¿De qué otra manera pueden las bibliotecas cliente esperar a interoperar?

Creo que me estoy perdiendo el punto aquí, esto parece demasiado obvio. (Sospecho que tiene otro problema en su código anterior).


Resumen: Rails obtiene su razón de ser de HTTP y REST.

(Gracias por su pregunta actualizada. Ahora entiendo su pregunta central: "No estoy diciendo que esté mal, solo estoy tratando de entender el fundamento de la implementación de Rails").

Ahora para la explicación. La justificación de cómo se comporta Rails está arraigada en abarcar las convenciones HTTP y REST.

Solo para pasar de lo que has leído a lo que voy a explicar, quiero mencionar las partes relevantes del artículo de Ryan Daigle sobre Representación de REST : Predeterminado :

Si se solicitó el formato html:

[texto eliminado]

  • [después de PUT o POST y sin errores de validación] se redirige a la ubicación del recurso (es decir, user_url)

(El texto [entre paréntesis] fue agregado por mí.)

Si se solicitó otro formato, (es decir, xml o: json)

[texto eliminado]

  • Si era una solicitud POST, invoque el método: to_format en el recurso y envíelo de vuelta con el estado: created y la ubicación: del nuevo recurso creado "

Permítame poner esto en mis palabras acerca de lo que Rails cree que es una buena práctica:

  • Para el contenido humano (por ejemplo, HTML), después de una POST o PUT, el servidor debe indicar al navegador que redireccione a través del 303 al recurso recién creado. Esta es una práctica común, algo muy útil porque un usuario desea ver las actualizaciones resultantes de sus ediciones.

  • Para el contenido de la máquina (p. Ej., JSON, XML), después de un PUT, el servidor solo debe representar un 201 . El cliente, en este caso, un programa que consume una API, puede decidir detenerse allí. (Después de todo, el cliente especificó la solicitud y obtuvo un 201, por lo que todo es honky dory). Por eso se usa 201 (éxito), no 303 (redirección). Si el cliente desea solicitar el recurso recién creado, puede buscarlo utilizando el encabezado de ubicación, pero no se debe forzar una redirección.

En cualquier caso, tenga en cuenta que la ubicación del recurso recién creado es obligatoria. Esta es la razón por la que @products en su ejemplo anterior debe contener tanto los datos como la ubicación.

Para el fondo, he compartido un poco de la página W3C en 201 creado :

10.2.2 201 creados

La solicitud se ha cumplido y se ha creado un nuevo recurso. Los recursos URI devueltos en la entidad de la respuesta pueden hacer referencia al recurso recién creado, con el URI más específico para el recurso dado por un campo de encabezado de ubicación. La respuesta DEBE incluir una entidad que contenga una lista de características de recursos y ubicación (es) desde la cual el usuario o agente de usuario puede elegir la más adecuada. El formato de la entidad está especificado por el tipo de medio dado en el campo de encabezado Content-Type. El servidor de origen DEBE crear el recurso antes de devolver el código de estado 201. Si la acción no se puede llevar a cabo de inmediato, el servidor DEBERÍA responder con 202 (Aceptado) en su lugar.

Espero que esto ayude a explicar el razonamiento. Es mi (¿ingenuo?) Entendimiento de que esta razón es bien aceptada en los marcos web. Históricamente, sospecho que Rails era el terreno de implementación ferviente (¡nueva palabra alerta!) Para muchos partidarios fervientes de REST y la Arquitectura Orientada a Recursos.