Los helpers de ruby on rails. Content_for

Hoy toca hablar de los helpers de ruby on rails.

Si ruby on rails sigue la estructura modelo-vista-controlador (MVC), los helpers están un poco en tierra de nadie, pero casi siempre podríamos tenerlos en cuenta como parte de las vistas. En general, su objetivo es mantener tu código lo mas DRY posible encapsulando código repetitivo que se ejecuta en tus vistas.

Supongamos una situación bastante común, en que en un layout, queremos mostrar diferente contenido en función de en que controlador o acción nos encontremos. O en función de si el usuario está logeado o no. Si se codifica directamente en el layout, pueden (y suelen) quedar cosas tan feas como esta:

#links
  - if session[:user]
    =link_to "Logout", logout_user_path
    -# bla bla bla ...
  - else
    =link_to "Login", login_user_path
    -# bla bla bla ...

Las vistas deberían contener la menor cantidad de lógica posible ( tampoco hay que ser un talibán con esta norma, que nadie se rasgue las vestiduras por ver un if..else en una plantilla ). Está claro que tener esto en un layout no parece muy elegante. Y si tenemos más de un layout, haces un copie y pega lo es aun menos.
A nuestro rescate vienen los helpers, y especialmente, ese método muchas veces olvidado que es el content_for.
Content_for es la forma ideal de personalizar el contenido de una plantilla en función del estado interno de nuestra aplicación. En el esquema de funcionamiento de rails, la vista se genera “de adentro hacia afuera”, ejecutándose primero la acción del controller, después renderizándose la vista de ese método, y por ultimo insertándose ese contenido generado en el layout general allá donde se ha invocado a yield.
Al ir de dentro a fuera, podemos definir contenido para el layout mientras se está generando una vista. Eso en exactamente lo que hace yield. Si le pasamos un nombre como argumento, podemos tener tantas llamadas a yield como queramos, y referirnos a ellas individualmente.
Por ejemplo, podemos tener en el layout algo similar a esto:

#links
  =yield(:links)

Tras eso podemos crear un método en application_helper.rb

def setLinks
   content_for(:links) { session[:user] ? link_to("Logout", logout_user_path) : link_to("login", login_user_path) }
end

Este helper puede ser invocado tanto desde una acción de un controlador, como desde una vista, y dinámicamente creará contenido que será insertado donde escribimos yield :links.
Esto tiene utilidades tan practicas como poder personalizar la hoja de estilos o los archivos javascript que cargamos en cada acción de manera personalizada, así como el título.
Pongo un ejemplo real de unos helpers que no faltan nunca en ninguna aplicación.
Mi layout:

-# coding: utf-8
!!!
%html
  %head
    %meta{'http-equiv'=>"Content-Type", :content=>"text/html; charset=UTF-8"}
    %title= yield(:title) || 'Untitled'
    = stylesheet_link_tag 'compiled/genericos','compiled/application'
    = javascript_include_tag("jquery","json2","rails_para_jquery","application","jquery.easing.1.3" )
    = yield :head
    = csrf_meta_tag
  %body
    #header
      #headlogo
      #headlinks
        #leftside
          %li#enlace1
            %h3 Enlace1
          %li#enlace2
            %h3 Enlace2
          %li#enlace3
            %h3 Enlace3
        #rightside
 -#bla bla bla bla bla
    #main
      =yield
    #footer
      %p Soy el footer

Los helpers.

module ApplicationHelper
  # Este metodo lo llamo al principio de cada plantilla, dandole un titulo a la misma
  def title(page_title)
    content_for(:title) { page_title.to_s}
  end
  # Estos metodos, invocados en las vistas, definen las CSS y los JS que deben cargarse en cada pagina.
  def stylesheet(*args)
    content_for(:head) { stylesheet_link_tag(*args) }
  end
  def javascript(*args)
    content_for(:head) { javascript_include_tag(*args) }
  end

end

Y como los utilizo en una vista:

- title 'Welcome'
- stylesheet 'blue-theme'
- javascript 'markermanager','map','infobox','marker_show','canvas'
#actions
  -# Enlaces a otras webs
.mapContainer
  #filter_menu
    #content_div
        -# bla bla bla

Asi en pocas lineas puedo hacer que cada vista tenga su propio aspecto cargando una hoja de estilos específica, su propio comportamiento con archivos javascript, y le establezco el título a mi antojo.

La utilidad de content_for va más allá, pudiendo usarse para renderizar menús laterales, cabeceras o secciones enteras de la web. De hecho puede servir para tanto como ganas tengas de dividir tu vista en fragmentos independientes.

Anuncios

, , , ,

  1. #1 por Pablo G. el octubre 4, 2011 - 2:08 pm

    tengo una pregunta, cunado intente utilizar el , fue necesario primero llamar al metodo del helper , esto debo hacerlo en cada vista que utilice los contenidos edfinidos o puedo aplicar DRY y hacerlo una unica vez?https://masquerailes.wordpress.com/2010/10/15/los-helpers-de-ruby-on-rails-content_for/#comment-form-guest

    • #2 por miguelcamba el octubre 4, 2011 - 2:16 pm

      Mmm…. no estoy seguro de entender la pregunta.
      Los helpers realizan una tarea determinada, allá donde se les llame. Por norma general, se utilizan en cada vista.
      Si lo que deseas es que se llame en todas las vistas …. en ese caso lo suyo es ponerlo en un layout.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: