Estoy revisando la guía Comenzando con Rails y me confundí con la sección 6.7. Después de generar un andamio, encuentro el siguiente bloque autogenerado en mi controlador:
def index
@posts = Post.all
respond_to do |format|
format.html # index.html.erb
format.json { render :json => @posts }
end
end
Me gustaría entender cómo funciona realmente el bloque respond_to. ¿Qué tipo de variable es el formato? ¿Son los métodos .html y .json del objeto de formato? La documentación para
ActionController::MimeResponds::ClassMethods::respond_to
no responde la pregunta
ruby-on-rails
Col
fuente
fuente
format.html
sin argumento), usará convenciones (basadas en el verbo URL y HTTP) para elegir una vista (que se espera sea HTML). El respondedor (formato) se instruye aquí para representar las URL que terminan en .json serializando a json, en lugar de usar vistas y convenciones.Respuestas:
Soy nuevo en Ruby y me quedé atrapado en este mismo código. Las partes en las que me colgué fueron un poco más fundamentales que algunas de las respuestas que encontré aquí. Esto puede o no ayudar a alguien.
respond_to
es un método en la superclaseActionController
.do
hastaend
, con|format|
un argumento para el bloque.format
argumento.http://api.rubyonrails.org/v4.1/classes/ActionController/Responder.html
Responder
NO contiene un método para.html
o.json
, pero de todos modos llamamos a estos métodos! Esta parte me lanzó a un bucle.method_missing
. Si llama a un método que no existe (comojson
ohtml
), Ruby llama almethod_missing
método en su lugar.http://ruby-metaprogramming.rubylearning.com/html/ruby_metaprogramming_2.html
Responder
clase usa sumethod_missing
como una especie de registro. Cuando llamamos 'json', le estamos diciendo que responda a las solicitudes con la extensión .json serializando a json. Necesitamos llamarhtml
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):
Esta parte me confundió muchísimo. Todavía lo encuentro poco intuitivo. Ruby parece usar esta técnica bastante. Toda la clase (
responder
) se convierte en la implementación del método. Para aprovecharmethod_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 tipo método. Para alguien que ha codificado en lenguajes tipo C durante 20 años, esto es muy atrasado 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 nota que en RoR 4.2
respond_to
se extrajo en gema respondedores .fuente
method_missing
, ¡considerando que puedes pasarle argumentos y un bloque!respond_to
los controladores, sin la gema de respuesta presente en el Gemfile. ¿Quizásrespond_to
ha cambiado la parte de ser extraído en la gema del respondedor?Este es un bloque de código Ruby que aprovecha el método auxiliar de Rails. Si aún no estás familiarizado con los bloques, los verás mucho en Ruby.
respond_to
es un método auxiliar de Rails que se adjunta a la clase Controller (o mejor dicho, su superclase). Hace referencia a la respuesta que se enviará a la Vista (que se dirige 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 solicita datos html o json.
Si está en su máquina local y tiene configurado el 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
verá todas sus publicaciones en un objeto json enviado desde el servidor.Esto es muy útil para hacer aplicaciones pesadas de JavaScript que necesiten pasar json de un lado a otro desde 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 Post. 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 asíncronas y se están volviendo muy populares (Gmail es uno). Son muy rápidos y le dan al usuario final una experiencia más similar a la de un escritorio en la web. Por supuesto, esta es solo una ventaja de formatear sus datos.
La forma de escribir Rails 3 sería:
Al colocarse
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 tiene 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 quieres saber sobre el funcionamiento interno de esto ...
Por lo que entiendo, Rails introspectiva los objetos para determinar cuál será el formato real. El valor de las variables 'formato' se basa en esta introspección. Los rieles pueden hacer mucho con un poco de información. Te sorprendería hasta dónde llegará un simple @post o: post.
Por ejemplo, si tuviera un archivo parcial _user.html.erb con el siguiente aspecto:
_user.html.erb
Entonces, esto solo en mi vista de índice le permitiría a Rails saber que necesitaba encontrar los 'usuarios' parciales e iterar a través de todos los objetos de 'usuarios':
index.html.erb
le haría saber a Rails que necesitaba encontrar el 'usuario' parcial e iterar a través de todos los objetos '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
fuente
respond_to
erespond_with
introducido? Estoy usando rails 2.3.5 y estoy obteniendoNoMethodError (undefined method respond_to)
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 Rails respond_to:
Lo estás pasando un bloque , como lo muestro aquí:
El | formato | parte es el argumento que el bloque está esperando, por lo que dentro del método respond_to podemos usar eso. ¿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. Como el argumento tiene el ".xml", ".html", podemos usarlo como métodos para llamar.
Lo que básicamente hacemos en la clase respond_to es llamar a los métodos ".html, .xml, .json" a una instancia de una clase Respondedor.
fuente
Para entender qué
format
es, primero puede buscar la fuenterespond_to
, pero rápidamente encontrará que lo que realmente necesita es el código para retrieve_response_from_mimes .A partir de aquí, verá que el bloque que se pasó
respond_to
(en su código), en realidad se llama y se pasa con una instancia de Collector (que dentro del bloque se hace referencia comoformat
). El recopilador básicamente genera métodos (creo que en el inicio de Rails) en función de los tipos mime que conoce rails.Entonces, sí, los métodos
.html
y.json
son definidos (en tiempo de ejecución) en laformat
clase Collector (aka ).fuente
La metaprogramación detrás del registro del respondedor (ver la respuesta de Parched Squid) también te permite hacer cosas ingeniosas como esta:
La línea csv hará que se llame a to_csv en cada publicación cuando visite /posts.csv. Esto facilita la exportación de datos como CSV (o cualquier otro formato) desde su sitio de rieles.
La línea js hará que se procese / ejecute un archivo javascript /posts.js (o /posts.js.coffee). He descubierto que es una forma ligera de crear un sitio habilitado para Ajax utilizando las ventanas emergentes de jQuery UI.
fuente
Desde un punto de vista de Java, el formato es una implementación de una interfaz anónima. Esta interfaz tiene un método nombrado para cada tipo mime. Cuando invocas uno de esos métodos (pasando un bloque), entonces si rails siente que el usuario quiere ese tipo de contenido, invocará tu bloque.
El giro, por supuesto, es que este objeto anónimo de pegamento en realidad no implementa una interfaz: captura las llamadas de método dinámicamente y determina si es el nombre de un tipo MIME que conoce.
Personalmente, creo que se ve raro: el bloque que pasas se ejecuta . Tendría más sentido para mí pasar un hash de etiquetas y bloques de formato. Pero, así es como se hace en RoR, parece.
fuente
Esto está un poco desactualizado, por Ryan Bigg hace un gran trabajo explicando esto aquí:
http://ryanbigg.com/2009/04/how-rails-works-2-mime-types-respond_to
De hecho, podría ser un poco más de detalle de lo que estaba buscando. Resulta que están sucediendo muchas cosas detrás de escena, incluida la necesidad de comprender cómo se cargan los tipos MIME.
fuente
"Formato" es su tipo de respuesta. Podría ser json o html, por ejemplo. Es el formato de la salida que recibirá su visitante.
fuente
Hay una cosa más que debes tener en cuenta: MIME.
Si necesita usar un tipo MIME y no es compatible de forma predeterminada, puede registrar sus propios controladores en config / initializers / mime_types.rb:
Mime::Type.register "text/markdown", :markdown
fuente