10: ACTION VIEW: Action View - LPC-Ltda/Ruby-on-Rails GitHub Wiki
El muy poderoso y el muy estúpido tienen una cosa en común. En lugar de alterar sus puntos de vista para adaptarse a los hechos, si alteran los hechos para encajar sus puntos de vista ... lo que puede ser muy incómodo si quieres pasar a ser uno de los hechos que se debe alterar. -Doctor Who
Los controladores son el esqueleto y la musculatura de su aplicación Rails. En cuyo caso, los modelos forman el corazón y la mente, y sus templates de view (basados en Action View, el tercer mayor componente de Rails) es la piel de su aplicación -la parte visible para el mundo exterior.
Action View es la API de Rails para reunir los componentes visuales de su aplicación -a saber, el HTML y contenido asociado que será rendereado en el browser de web cuando quiera que alguien use su aplicación Rails. Realmente, en este bravo nuevo mundo de recursos REST, Action View esta involucrado en generar casi cualquier tipo de salida que usted genere.
Action View contiene un sistema completo de templates basado en una librería de Ruby llamada ERb. Toma data preparada por el nivel de controlador y la intercala con el código de la vista para crear un nivel de presentación para el usuario final. Esta es una de las primeras cosas que usted aprende de Rails y parte de la librería estándar de Ruby. Yo prefiero mucho más una solución de templates llamada Haml la que he usado en este libro para los ejemplos. Yo pienso que Haml es mucho más superior que Erb por ello no cubre ERb para nada.
En este capítulo cubrimos los fundamentos del framework Action View, desde el uso efectivo de parciales a la carga al aumento significativo de rendimiento via el uso del almacenamiento en cache. Si usted necesita aprender Haml, lo cubrimos en detalle en el Capítulo 12, "Haml".
##10.1 Layouts y Templates
Rails tiene convenciones simples para el uso de templates relacionada con la ubicación de templates en los directorios de proyecto de Rails.
El directorio app/views
contiene subdirectorios correspondientes al nombre del controlador en su aplicación. Dentro de cada subdirectorio de vista de controlador, usted pone un template cuyo nombre debe coincidir con su acción correspondiente.
El directorio especial app/views/layout
contiene templates layout destinado a ser contenedores reusables para sus vistas. De nuevo, convenciones de nombre son usadas para determinar cuales templates renderear, except que esta vez es el nombre del controlador el que es usado para la coincidencia.
###10.1.1 Convenciones de nombres de archivo de templates
El nombre de archivo de un template en Rails trae consigo mucho significado. Sus partes, delimitadas por puntos, corresponden a la siguiente información:
- Nombre (usualmente mapeados a la acción)
- Locale (opcional)
- Tipo de contenido
- Template engine(s)
- Variant (opcional, nuevo en Rails 4.1)
###10.1.2 Layouts
Action View decide que layout renderear basado en la herencia jerárquica de los controladores que están siendo ejecutados. La mayoría de las aplicaciones Rails tienen un archivo application.html.haml
en su directorio layout. Este comparte su nombre con el ApplicationController
, el cual es típicamente extendido por todos los otros controladores en la aplicación; por lo tanto, es elegido como el layout por defecto para todas las vistas.
Es elegido, a menos, por supuesto, que un template de layout más específico este en el lugar, pero frecuentemente usar sólo un template para toda la aplicación, como el simple mostrado en el Listado 10.1.
!!! 5
%html
%head
%meta{ charset: 'utf-8' }
%title TRW4 Time and Expenses Sample Application
= csrf_meta_tag
= stylesheet_link_tag 'application', media: 'all'
%body
= yield
###10.1.3 Contenido producido
La palabra clave del lenguaje Ruby yield
es puesta para la colaborar en la construcción de templates de layout y acción. Note el uso de yield
al final del template de layout:
%body
= yield
En este caso, yield
por si mismo es un mensaje especial al sistema de rendereo. Marca el lugar donde insertar la salida del rendereo de la acción, la cual es generalmente el template correspondiente a la acción.
Usted puede agregar lugares extras en su layout donde usted desea poder hacer un yield de contenido para incluir invocaciones de yield adicionales -sólo asegúrese que usted pasa un único identificador como argumento. Un buen ejemplo es un layout que tiene contenido lateral a la derecha e izqueirda (simplificado por supuesto):
%body
.left.sidebar
=yield :left
.content
= yield
.right.sidebar
= yield :right
El div .content
recibe el template marcado principal generado. Pero cómo obtiene Rails contenido para los laterales de la derecha e izquierda? Es fácil: sólo use el método content_for
donde quiera en el código de su template. Yo usualmente lo pongo en la cima del template así esto obvio.
- content_for :left do
%h2 Navigation
%ul
%li ...
- content_for :right do
%h2 Help
%p Lorem ipsum dolor sit amet, consectetur adipisicing elit...
%h1 Page Heading
%p ...
Junto a los laterales y otros tipos de bloques visibles de contenido, Sugiero hacer un yield del contenido adicional agregado al elemento HEAD
de su página, como se muestra en el Listado 10.2.
Listado 10.2 Produciendo contenido adicional de Head
!!! 5
%html
%head
%meta{ charset: 'utf-8' }
%title TRW4 Time and Expenses Sample Application
= csrf_meta_tag
= stylesheet_link_tag 'application', media: 'all'
= yield :head
%body
= yield
Un yield en el
HEAD
es también una buena técnica para incluir tagsmeta
específicos de una página, como los requeridos por Facebook Open Graph.
###10.1.4 Salida condicional
Uno de los idiomas más comunes que usará cuando codifique vistas Rails es la salida de contenido condicional a la vista. La forma más elemental de controlar salidas condicionales es usar la instrucción if
.
- if show_subtitle?
%h2= article.subtitle
Muchas veces usted puede usar la condición if
en línea para abreviar su código, ya que el =
de salida no se preocupa si usted lo alimenta con un valor nil. Solo agregue una condición if
al final de la instrucción:
%h2= article.subtitle if show_subtitle?
Por supuesto, hay un problema con el ejemplo anterior. La instrucción if en una línea separada eliminará completamente el tag <h2>
pero el segundo ejemplo en línea no.
Hay un par de formas de tratar con el problema y mantenerlo en una línea. Primero, hay una solución fea que ocasionalmente veo en las aplicaciones Rails, la cual es la única razón por la cual la menciono aqui!
= "<h2>#{h(article.subtitle)}</h2>".html_safe if show_subtitle?
Una solución más elegante involucra el método helper content_tag
de Rails, pero admitimos que la solución en una línea es probablemente infereior a la equivalente en dos líneas en este caso.
content_tag('h2', article.subtitle) if show_subtitle?
Los métodos helper, tanto los incluidos en Rails como content_tag
como los que puede escribir por usted mismo, son su herramienta principal para construir templates de vistas elegantes. Los helpers serán cubiertos en extenso el en Capítulo 11, "Todo acerca de los Helpers".
###10.1.5 Decent Exposure
Hemos visto como los layouts y los bloques de producción (yield) de contenido funcionan, pero aparte de esto, cómo puede la data ir desde el nivel del controlador a la vista? Durante la preparación del template, las variables de instancias seteadas durante la ejecución de la acción del controlador, serán copiadas como variables de instancia del contexto del tamplate. Aunque esta es la forma estándar expuesta en la documentación Rails, compartir el estado via variables de instancia en los controladores promueve una estrecha emparejamiento con las vistas. La Decent Exposure gem1 de Stephen Caudill provee una manera declarativa de exponer una interface del estado que los controladores contienen, de este modo decrece el emparejamiento y mejora la posibilidad de probar y el diseño general.
Cuando se invoca, la macro expose
crea un método con un nombre dado, evalúa el bloque provisto y memoriza el resultado. Este método es entonces declarado como un helper_method
para que las vistas tengan acceso a él y se hace no ruteable como acción. Cuando ningún bloque es proporcionado, expose
intenta intuir que recurso usted desea adquirir.
# Timesheet.find(params[:timesheet_id] || params[:id])
expose(:timesheet)
Como el ejemplo muestra, el símbolo pasado es usado para adivinar el nombre de la clase del objeto que usted desea encontrar -útil ya que casi todos los controladores usan este tipo de código en las acciones show, edit, y destroy.
En un escenario un poco más complicado, usted puede necesitar encontrar una instancia de un objeto que no se mapea limpiamente a un método find
simple.
expose(:timesheet) { client.timesheets.find(params[:id]) }
En el paradigma del controlador REST, usted se encuentra usando esto mismo el las acciones show, update y destroy de los recursos anidados.
Cuando el código se ha hecho lo suficientemente largo para sobrepasar una única línea (pero aún no es apropiado extraerlo dentro de un método de modelo), use un estilo de block `do... end, como en el siguiente ejemplo que usa los tres estilos:
expose(:client)
expose(:timesheet) { client.timesheet.find(params[:id]) }
expose(:timesheet_approval_presenter) do
TimesheetApprovalPresenter.new(timesheet, current_user)
end
El ejemplo previo también muestra cómo las declaraciones expose
pueden depender la una de la otra. De hecho, el uso apropiado de expose
debe eliminar la mayoría del código que mira el modelo desde las acciones de controlador actual.
En Hashrocket, el uso de Decent Exposure ha provisto tanto beneficio que ha reemplazado el uso directo da variables de instancia en controladores y vistas. Los métodos helper creados por la macro expose
se refieren directamente en la vista.
###10.1.6 Variables de instancia estándar
Más que sólo variables de instancia desde el controlador son copiadas sobre el template. No es una buena idea depender de algunos de los siguientes objetos directamente, y especialmente no los use para operaciones de data. Otros son una parte estándar de la mayoría de las aplicaciones Rails.
10.1.6.1 assigns
Desea ver todo lo que viene desde el borde controlador-vista? Throw = debug(assign)
dentro de su template y heche una mirada a su salida. El atributo assigns
es escencialmente interno de Rails, y usted no debe usarlo directamente en su código de producción.
10.1.6.2 base_path
Ruta del sistema de archivos local que apunta al directorio base de su aplicación donde los templates han sido puestos.
10.1.6.3 controller
La instancia de controlador actual se hace disponible vía controller
, antes que se salga del ámbito final del proceso de requerimientos. Usted puede tomar ventaja del conocimiento del controlador de su nombre (vía el atributo controller_name
) y la acción que ha sido recién realizada (vía el atributo action_name
) con el fin de estructurar su CSS más eficazmente.
%body{ class: "#{controller.controller_name} #{controller.action_name}" }
Esto puede resultar en un tag BODY
que luce como este, dependiendo de la acción ejecutada:
<body class="timesheet index">
Nota: Usted puede replicar la funcionalidad en el ejemplo previo usando el método helper de Haml
page_class
.
%body{ class: page_class }
Tenemos la esperanza que usted ya sepa que la C en CSS está por cascading, lo cual se refiere al hecho de que los nombres de clase caen en cascada hacia abalo del árbol de elementos en su código etiquetado (markup) y están disponibles para la creación de reglas. El truco es incluir automáticamente los nombres de controlador y acción como nombres de clase de su elemento body
para que usted pueda usarlos para personalizar el look and feel de la página muy flexiblemente al final de su ciclo de desarrollo. Por ejemplo, aquí está el cómo usted debe usar la técnica de variar el background de los elementos encabezados dependiendo de la ruta del controlador en CSS:
body {
.timesheet .header {
background: image_url(timesheet-bg.png) no-repeat left top;
}
.expense_reports .header {
background: image_url(expense-report-bg.png) no-repeat left top;
}
}
10.1.6.4 cookies
La variable cookie
es un hash que contiene las cookies del usuario. Puede haber situaciones donde estará OK halar valores para afectar el rendereo, pero la mayoría del tiempo usted usará las cookies en el controlador, no en la vista.
10.1.6.5 flash
El flash ha aparecido en ejemplos de código más grandes en todo el libro hasta el momento cada vez que desea enviar al usuario un mensaje desde la capa del controlador, pero sólo por la duración de la siguiente solicitud.
def create
if user.try(:authorize, params[:user][:password])
flash[:notice] = "Welcome, #{user.first_name}!"
redirect_to home_url
else
flash[:alert] = "Login invalid"
redirect_to :new
end
end
Es una práctica común en Rails usar flash[:notice]
ara contener mensajes de noticias benignas y flash[:alert]
para la comunicación de naturaleza más seria.
Nota: Es también común setear noticias
flash
y mensajes dealert
sobre los redireccionamientos que Rails le permite setear en el métodoredirect_to
como parámetros opcionales.
def create
if user.try(:authorize, params[:user][:password])
redirect_to home_url, notice: "Welcome, #{user.first_name}!"
else
redirect_to home_url, alert: "Bad login"
end
end
Accessors especiales para noticias y alertas son incluidos como métodos helper en el objeto flash mismo, ya que su uso es muy común.
def create
if user.try(:authorize, params[:user][:password])
flash.notice = "Welcome, #{user.first_name}!"
redirect_to home_url
else
flash.alert = "Login invalid"
redirect_to action: "new"
end
end
###10.1.7 Desplegando mensajes flash
Personalmente, me gusta condicionar tanto la salida de los mensajes notice
como de los mensajes alert
en un elemento div
, en la cima de mi layout, y uso CSS para definir su estilo, como muestro en el Listado 10.3:
Listado 10.3 Ubicación estandarizada de noticias y errores flash en
application.html.haml
%html
...
%body
- if flash.notice
.notice= flash.notice
- if flash.alert
.notice.alert= flash.alert
= yield
El CSS para .notice
define la mayoría del estilo para el elemento, y .alert
sobre escribe sólo el aspecto que es diferente para las alertas.
###10.1.8 flash.now
Algunas veces usted desea darle un mensaje flash al usuario pero sólo por el requerimiento actual. De hecho, un error de principiante común es setear una noticia flash y no redireccionar, de este modo mostramos incorrectamente un mensaje en el requerimiento siguiente.
Es posible hacer que flash coopere con un render usando el método flash.now
.
class ReportController < ActiveRecord::Base
def create
if report.save
flash.notice = "#{report.title} has been created."
redirect_to report_path(report)
else
flash.now.alert = "#{@post.title} could not be created."
render :new
end
end
end
El objeto flash.now
también tiene accessors notice
y alert
, como su contraparte tradicional.
10.1.8.1 logger
Usted tiene algo que grabar para la posteridad en el logs mientras usted está rendereando la vista? Use el método logger
para obtener la instancia Logger
de la vista -igual que Rails.logger
, a menos que usted lo haya cambiado.
10.1.8.2 params
Este es el mismo hash params
que está disponible en su controlador, conteniendo los pares llave/valor de su requerimiento. Yo ocasionalmente use un valor desde el hash params
directamente en la vista, particularmente cuando estoy tratando con páginas que tema de filtrado u ordenamiento de filas.
%p
Filter by month:
= select_tag(:month_filter, options_for_select(@month_options, params[:month_filter]))
Es muy dañino desde la perspectiva de la seguridad, data de parámetros sin filtrar dentro del stream de salida de su template. El Capítulo 15, "seguridad" cubre este tópico en profundidad.
10.1.8.3 request
y response
Los objetos HTTP request
y response
son expuestos a la vista, pero sólo con propósitos de debugg, no puedo imaginar otra razón para usarlos directamente desde su template.
10.1.8.4 session
La variable session
es el hash de sesión del usuario. Puede haber situaciones donde estará bien sacar de ahí valores para afectar el rendereado, pero me estremezco al pensar de que usted pueda tratar de setear valores en la sessión desde la capa de vistas. Úselo con cuidado y principalemente para debugging, igual que con request
y response
.
##10.2 Parciales
Un parcial es un fragmento de código de template. La forma de Rails de usar parciales para factorizar código de vistas dentro de pedazos modulares que pueden ser ensamblados en layouts con la menor repetición posible. En antiguas versiones de Rails, la sintaxis para incluir un parcial dentro de un template comenzaba con render :partial
, pero ahora pasar un string a render
dentro de su vista puede ser interpretado como que usted desea renderear un parcial. Los nombres de templates parciales deben comenzar con un underscore, lo cual sirve para separarlos visualmente dentro de un directorio de templates de vistas. Sin embargo, usted puede omitir el underscore cuando se refiere a ellos.
%h1 Details
= render 'details'
###10.2.1 Casos de uso simples
El caso de uso más simple de un parcial es simplemente extraer una porción de código template. Algunos desarrolladores dividen sus templates en partes lógicas al usar la extracción de parciales.Algunas veces es más simple de entender una estructura de una pantalla si las partes significantes son factorizadas fuera de ellas. Por ejemplo, el Listado 10.4 es una pantalla simple de registro de usuario que tiene sus partes factorizadas en parciales.
Listado 10.4 Formulario de registro de usuario simple con parciales
%h1 User Registration
= error_messages_for :user
= form_for :user, url: user_path do
.registration
.details.demographic
= render 'details'
= render 'demographics'
.location
= render 0location'
.opt_in
= render 'opt_in'
.terms
= render 'terms'
%p= submit_tag 'Register'
Mientras estamos en ello, dejeme abrirle uno de esos parciales. Para consevar espacio, miraremos uno de los más pequeños, el parcial que contiene los check-boxes opt-in de esta aplicación particular. La fuente esta en el Listado 10.5; note que el nombre comienza con un underscore.
Listado 10.5 El parcial Opt-in en el archivo
app/views/users/_opt_in.html.haml
%fieldset#opt_in
%legend Spam Opt In
%p
= check_box :user, :send_event_updates
Send me updates about events!
%br
= check_box :user, :send_site_updates
Notify me about new services
Personalmente, me gustan los parciales contenidos enteramente en un contenedor etiquetado semánticamente significativo. En el caso del parcial en el Listado 10.5, ambos controles check box están contenidos dentro de un único elemento fieldset
, al cual le he dado un atributo id
. Siguiendo la regla, más como una guía aislada que cualquier otra cosa, me ayuda a identificar mentalmente a identificar cómo los contenidos de este parcial van a encajar dentro del template padre. Si hemos lideado con otras etiquetas, quizá fuera de un formulario, puedo elegir envolver el markup del parcial dentro de un contenedor div
bien identificado en lugar de un fieldset
.
Porque no incluir una etiqueta td
dentro del template parcial? Es cosa de estilo - a mí me gusta poder ver el esqueleto de etiquetas completo en una pieza. En este caso, el esqueleto es la estructura de la tabla que usted ve en el listado 10.4. Si porciones de la tabla fueran insertadas en templates parciales, complicaría el layout de la página. Tengo que admitir que esta es una de esas áreas donde el estilo y preferencias personales debe tener precedencia, y yo sólo puedo aconsejarle lo que ha funcionado para mi, personalmente.
###10.2.2 Reutilización de parciales
Ya que el formulario de registro esta púlcramente factorizado en sus partes componentes, es fácil crear un formulario de edición simple usando algunos de sus parciales, como en el Listado 10.6.
Listado 10.6 Formulario de edición de usuario simple reutilizando algunos de los mismos parciales
%h1 Edit User
= form_for :user, url: user_path(@user), method: :put do
.settings
.details
= render 'details'
.demographic
= render 'demographics'
.location
= render 0location'
.opt_in
= render 'opt_in'
%p= submit_tag 'Save Settings'
Si usted compara los Listados 10.4 y 10.6, notará que la estructura de la tabla cambió un poco en el formulario de edición, y tiene menos contenido que el formulario de registro. Quizá la "location" es manejada en mayor detalle en otra pantalla, y ciertamente usted no necesita aceptar los términos cada vez que cambia su seteo.
###10.2.3 Parciales compartidos
Hasta ahora hemos considerado el uso de parciales que residen en el mismo directorio que sus templates padres. Sin ambargo, usted puede fácilmete referirse a paciales que están en otros directorios sólo prefijando el nombre del directorio. Usted aún debe obviar el underscore, que siempre se ha sentido un poco raro.
Agreguemos un parcial captcha
abajo del formulario de registro del LIstado 10.4 para ayudarnos a prevenir que los spammers invadan nuestra aplicación web:
...
.terms
= render 'terms'
.captcha
= render 'shared/captcha'
%p= submit_tag ?Register'
Ya que el parcial captcha
es usado en diferentes partes de la aplicación, hace sentido que resida en una carpeta shared en lugar de un carpeta de una vista particular. Sin embargo debe tener un poco de cuidado cuando mueva código de un template existente a un parcial compartido, Es muy posible que inadvertidamente separe un parcial que depende implícitamente de donde es rendereado.
Por ejemplo, tome el caso del miembro de la lista de correos Rails-talk con un parcial molesto definido en login/_login.html.haml
:
= form_tag do
%fieldset
%label
Username:
= text_field_tag :username, params[:username]
%br
%label
Password
= password_field_tag :password, params[:password]
%br
= submit_tag "Login"
El envío del formulario login trabaja cuando él rendereo su parcial como parte del login acción login
del controlador ("la página login") pero no cuando fue incluido como parte de la vista para cualquier otra sección de su website. El problema es que form_tag
(cubierto en el próximo capítulo) normalmente toma un parámetro de acción opcional contándole donde postear su información. Si usted deja fuera la opción, el formulario posteará de vuelta a su URL actual, lo cual puede variar para parciales compartidos, dependiendo de donde sea usado el formulario.
###10.2.4 Pasando variables a un parcial
Los parciales heredan el método expuesto a sus templates padres implícitamente. Por esto es que los helpers de formulario usados en los parciales de los listados 10.4 y 10.6 funcionan: Ellos confían implícitamente que un método user
esta en scope. Me parece bien usar este compartir implícito en algunos casos, particularmente cuando los parciales están herméticamente unidos a sus templates padres. Esto puede ser especialmente verdadero en casos donde la única razón para romper en un parcial es en primer lugar reducir el tamaño y complejidad de un template particularmente largo.
Sin embargo, una vez que usted adquiere la práctica de romper en templates parciales para su reutilización, dependiendo del contexto implícito se hace mucho más arriesgado. Esta es la razón por la que Rails soporta el paso de variables de alcance local a los templates parciales, como en el siguiente fragmento:
= render 'shared/address', form: form
Los valores del hash opcional son convertidos a variables de alcance local (sin signo @) en el parcial. El Listado 10.7 es una variación sobre el template de registro. Esta vez estamos usando la versión de form_for
que produce un parámetro bloque representando el formulario a sus métodos helpers de formulario. Pasaremos el parámetro form también.
%h1 User Registration
= form_for :user, url: users_path do |form|
.registration
.details.address.demographic
= render 'details', form: form
= render 'shared/address', form: form
%p= form.submit 'Register'
Y finalmente, en el Listado 10.8 tenemos el formulario de address compartido.
Listado 10.8 Un parcial Address simple compartido usando variable local
%fieldset.address
%legend.Address
%p
%label Street
%br
= form.text_area :street, rows: 2, cols: 40
%p
%label City
=form.text_field :city
%p
%label State
%br
= form.text_field :state, size: 2
%p
%label Zip
%br
= form.text_field :zip, size: 15
Los métodos helper form, los cuales son cubiertos en el Capítulo 11, "Todo acerca de los Helpers" tienen una variación en la cual son llamados sobre la variable form
producida por el método form_for
. Esto es exactamente lo qeu hemos pasado a estos parciales.
10.2.4.1 El hash local_assigns
Si usted necesita chequear la presencia de cierta variable local en un parcial, usted necesita hacerlo chequeando el hash local_assigns
que es parte de todo template. Usar defined? variable
no funciona debido a las limitaciones del sistema de rendereado.
- if local_assigns.has_key? :special
= special
###10.2.5 Rendereando un objeto
El método render
también provee una sintaxis abreviada pra renderear un objeto dentro de un parcial, lo cual depende estrictamente de la convención de nombres de Rails.
render entry
El parcial correspondiente al último fragmento de código es nombrado _entry.html.haml
y toma una variable local llamada entry
. Esto es equivalente a lo siguiente:
= render partial: 'entry', object: entry
Para setear el nombre de una variable local diferente a la del nombre del parcial, uno puede usar la hash locals
como vimos antes en el capítulo o especificar el nombre deseado a través de la opción :as
.
= render partial: 'entry', object: some_entry, as: :item
###10.2.6 Rendereando colecciones
Uno de los mejores usos de los parciales es renderear colecciones. Una vez que usted tenga el habito de renderear colecciones con parciales, usted no deseará volver a fealdad de saturar sus templates con loops for
y each
. Cuando el método render
toma un Enumerable
como su primer argumento, asume que usted desea renderear una colección de parciales.
render entries
Es simple y muy dependiente de la convención de nombres. El objeto que es rendereado es expuesto al template parcial como una variable local llamada exáctamente como el template parcial mismo. Sucesivamente, el template debe ser nombrado de acuerdo a la clase del objeto que está siendo rendereado.
El parcial correspondiente al último fragmento de código es llamado _entry.html.haml
y obtiene la variable local llamada entry
.
= div_for(entry) do
= entry.description
#(distance_of_time_in_words_to_now entry.created_at) ago
Si la colección pasada dentro del método
render
está vacía, retornanil
. Usando este conocimiento, usted puede escribir código como el siguiente para proveer contenido de vuelta:
= render(entries) || "No entries exist"
Ya que el template parcial usado está basado en la clase de cada ítem, usted puede fácilmente renderear una colección heterogénea de objetos. Esta técnica es particularmente útil en conjunción con colecciones de subclases STI.
Si usted desea sobre escribir este comportamiento, entonces vuelva a la antigua sintaxis de parciales y especifique las opciones :partial
y collection
explícitamente, como sigue:
partial: 'entry', collection: @entries
**10.2.6.1 la variable partial_counter
Hay otro conjunto de variable para parciales de rendereo de colecciones al que no prestan mucha atención. Es una variable contador indexado en cero que da seguimiento al número de veces que un parcial ha sido rendereado. Es útil para renderear listas numeradas de cosas. El nombre de la variable es el nombre del parcial más _counter
.
= div_for(entry) do
"#{entry_counter}:#{entry.description}
#{distance_of_time_in_words_to_now entry.created_at} ago"
10.2.6.2 Compartiendo parciales de colecciones
Si usted busca usar el mismo parcial que usted usa con una colección, pero con un único objeto entry, usted tiene que pasar esa instancia única vía el hash locals descrito en la sección precedente, así:
render 'entry', entry: some_entry
###10.2.7 Logging
Si usted hecha una mirada a su log de desarrollo, notará que muestra que parciales ha rendreado y cuanto tiempo le tomó.
Rendering template within layouts/application
Rendering listings/index
Rendered listings/_listing 0.6ms)
Rendered listings/_listing 0.3ms)
Rendered listings/_listing 0.2ms)
Rendered listings/_listing 0.2ms)
Rendered listings/_listing 0.2ms)
Rendered layouts/_login 2.4ms)
Rendered layouts/_header 3.3ms)
Rendered layouts/_footer 0.1ms)