Saltar al contenido

Rails: ¿Cómo funciona el bloque respond_to?

Solución:

Soy nuevo en Ruby y me quedé atascado en este mismo código. Las partes en las que me obsesioné fueron un poco más fundamentales que algunas de las respuestas que encontré aquí. Esto puede ayudar o no a alguien.

  • respond_to es un método en la superclase ActionController.
  • se necesita un bloque, que es como un delegado. El bloque es de do Hasta que end, con |format| como argumento para el bloque.
  • respond_to ejecuta su bloque, pasando un Responder al format argumento.

http://api.rubyonrails.org/v4.1/classes/ActionController/Responder.html

  • los Responder NO contiene un método para .html o .json, ¡pero llamamos a estos métodos de todos modos! Esta parte me dejó perplejo.
  • Ruby tiene una función llamada method_missing. Si llamas a un método que no existe (como json o html), Ruby llama al method_missing método en su lugar.

http://ruby-metaprogramming.rubylearning.com/html/ruby_metaprogramming_2.html

  • los Responder la clase usa su method_missing como una especie de registro. Cuando llamamos a ‘json’, le estamos diciendo que responda a las solicitudes con la extensión .json serializando a json. Tenemos que llamar html sin argumentos para decirle que maneje las solicitudes .html de la manera predeterminada (usando convenciones y vistas).

Podría escribirse así (usando un pseudocódigo similar a JS):

// get an instance to a responder from the base class
var format = get_responder()

// register html to render in the default way
// (by way of the views and conventions)
format.register('html')

// register json as well. the argument to .json is the second
// argument to method_missing ('json' is the first), which contains
// optional ways to configure the response. In this case, serialize as json.
format.register('json', renderOptions)

Esta parte me confundió muchísimo. Todavía lo encuentro poco intuitivo. Ruby parece usar bastante esta técnica. Toda la clase (responder) se convierte en la implementación del método. Para aprovechar method_missing, necesitamos una instancia de la clase, por lo que estamos obligados a pasar una devolución de llamada a la que pasan el objeto similar al método. Para alguien que ha codificado en lenguajes similares a C durante 20 años, esto es muy al revés y poco intuitivo para mí. ¡No es que sea malo! Pero es algo que mucha gente con ese tipo de experiencia necesita entender, y creo que podría ser lo que buscaba el OP.

ps tenga en cuenta que en RoR 4.2 respond_to se extrajo en gema de respondedores.

Este es un bloque de código Ruby que aprovecha un método auxiliar de Rails. Si aún no está familiarizado con los bloques, los verá mucho en Ruby.

respond_to es un método auxiliar de Rails que se adjunta a la clase Controller (o más bien, a su superclase). Hace referencia a la respuesta que se enviará a la Vista (que va al navegador).

El bloque en su ejemplo está formateando datos, pasando un parámetro de ‘formato’ en el bloque, para ser enviados desde el controlador a la vista cada vez que un navegador realiza una solicitud de datos html o json.

Si está en su máquina local y tiene configurado su andamio Post, puede ir a http://localhost:3000/posts y verá todas sus publicaciones en formato html. Pero, si escribe esto: http://localhost:3000/posts.json, luego verá todas sus publicaciones en un objeto json enviado desde el servidor.

Esto es muy útil para hacer aplicaciones javascript pesadas que necesitan pasar json desde y hacia el servidor. Si lo desea, puede crear fácilmente una api json en el back-end de sus rieles y solo pasar una vista, como la vista de índice de su controlador de publicación. Luego, podría usar una biblioteca de JavaScript como Jquery o Backbone (o ambas) para manipular datos y crear su propia interfaz. Estos se llaman IU asincrónicas y se están volviendo realmente populares (Gmail es uno). Son muy rápidos y brindan al usuario final una experiencia más similar a la de un escritorio en la web. Por supuesto, esta es solo una de las ventajas de formatear sus datos.

La forma de Rails 3 de escribir esto sería la siguiente:

    class PostsController < ApplicationController
      # GET /posts
      # GET /posts.xml


      respond_to :html, :xml, :json

      def index
        @posts = Post.all

        respond_with(@posts)
      end

#
# All your other REST methods
#

end

Poniendo respond_to :html, :xml, :json en la parte superior de la clase, puede declarar todos los formatos que desea que su controlador envíe a sus vistas.

Luego, en el método del controlador, todo lo que tienes que hacer es responder_con (@whatever_object_you_have)

Simplemente simplifica su código un poco más de lo que Rails genera automáticamente.

Si desea conocer el funcionamiento interno de este

Por lo que tengo entendido, Rails hace una introspección de los objetos para determinar cuál será el formato real. El valor de las variables de ‘formato’ se basa en esta introspección. Los rieles pueden hacer mucho con un poco de información. Se sorprenderá de lo lejos que llegará un simple @post o: post.

Por ejemplo, si tuviera un archivo parcial _user.html.erb que luciera así:

_user.html.erb

<li>    
    <%= link_to user.name, user %>
</li>

Entonces, esto solo en mi vista de índice le permitiría a Rails saber que necesitaba encontrar el parcial de ‘usuarios’ e iterar a través de todos los objetos de ‘usuarios’:

index.html.erb

 <ul class="users">
   <%= render @users %>     
 </ul>

le haría saber a Rails que necesitaba encontrar el ‘usuario’ parcial e iterar a través de todos los objetos de los ‘usuarios’:

Puede encontrar útil esta publicación de blog: http://archives.ryandaigle.com/articles/2009/8/6/what-s-new-in-edge-rails-cleaner-restful-controllers-w-respond_with

También puede leer detenidamente la fuente: https://github.com/rails/rails

Por lo que sé, respond_to es un método adjunto al ActionController, por lo que puede usarlo en cada controlador, porque todos heredan del ActionController. Aquí está el método Responde_to de Rails:

def respond_to(&block)
  responder = Responder.new(self)
  block.call(responder)
  responder.respond
end

Lo estás pasando un bloque, como muestro aquí:

respond_to <<**BEGINNING OF THE BLOCK**>> do |format|
  format.html
  format.xml  { render :xml => @whatever }
end <<**END OF THE BLOCK**>>

los | formato | parte es el argumento que espera el bloque, así que dentro del método respond_to podemos usarlo. ¿Cómo?

Bueno, si notas que pasamos el bloque con un prefijo & en el método respond_to, y lo hacemos para tratar ese bloque como un Proc. Dado que el argumento tiene el “.xml”, “.html”, podemos usarlo como métodos para ser llamado.

Lo que hacemos básicamente en la clase respond_to es llamar a los métodos “.html, .xml, .json” a una instancia de una clase Responder.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *