Rails: helpers con bloques

Visita este artí­culo en http://www.estadobeta.com/2007/06/11/rails-helpers-con-bloques/

Por Ismael en Ruby & Rails, artículos, tips

Pongamos un ejemplo. Estas haciendo una aplicación Rails donde los usuarios autorizados (”logueados”) puedes ver algunas cosas en las páginas que el resto de los usuarios no pueden. Hay varias formas de solucionarlo. Supongamos que en tu controlador base defines un objeto @user que estará presente en todas las páginas. Al Usuario le defines un método is_logged? para saber si hay un usuario registrado. Así es fácil agregar secciones de HTML dependiendo del estado del usuario.

Code (ruby)
  1.  
  2. < % if @user.is_logged? %>
  3. <div class="admin_area"

Bloques

Pero claro, cada vez que queramos agregar esta “admin_area” a nuestras vistas tendremos que duplicar esa condición. La cosa se pone pero aún si en el futuro queremos extender el sistema de permisos.

Ruby y sus Bloques al rescate. ¿Han visto el nuevo helper para formularios de Rails 1.2?

Code (ruby)
  1.  
  2. < % form_tag :action=>’/una/accion’ do %>
  3.     <input type="text" name="nombre" />
  4.     <input type="submit" value="Guardar" />
  5. < % end %>
  6.  

El helper recibe RHTML dentro de un bloque, y lo rodea con las etiquetas <form action="/una/accion" method="post"> y </form>.

Resulta que podemos usar la misma metodología para nuestros fragmentos de administración; algo como así:

Code (ruby)
  1.  

Este Helper no sólo evaluaría si el Usuario (@user) está registrado sino que podría rodear el bloque con una etiqueta HTML común a todos los fragmentos de administración, en este caso <div clas="admin_area"> y </div>.

Veamos la implementación (normalmente en /app/helpers/application.rb o otro Helper).

Code (ruby)
  1.  
  2. def admin_area(&block)
  3.     returnunless @user and @user.is_logged?
  4.     concat( ‘<div class="admin_area">’, block.binding )
  5.     yield
  6.     concat( "</div>", block.binding )
  7. end
  8.  

Ahí está- Nuestro helper admin_area recibe un bloque (en este caso un fragmento de RHTML). Si no existe un usuario registrado, retorna un string vacío. Si el usuario está registrado, retorna el fragmento de RHTML rodeado de un DIV u otros fragmentos comunes (cuando un método Ruby recibe un bloque como parámetro, yield invoca y retorna ese bloque). concat concatena nuestro DIV con el contenido del bloque (quien quiera explicar esto con más detalle, sientase libre de hacerlo en los comentarios).

Más usuarios

Pero ahora nuestro sistema de usuarios soporta varios niveles. En el objeto @user definimos un atributo “nivel” que nos dice si el usuario es “administrador”, “editor” o “invitado”. La idea es usar nuestro Helper de la siguiente manera:

Code (ruby)
  1.  

Ahora el Helper recibe un símbolo que representa el nivel de administración del usuario registrado. Nuestro Helper se encarga de revisar que el usuario tenga el nivel apropiado.

Code (ruby)
  1.  
  2. def admin_area(nivel=:administrador, &block)
  3.     returnunless @user and @user.is_logged? and @user.nivel = nivel.to_s
  4.    #
  5.  
  6.     concat( ‘<div class="admin_area">’, block.binding )
  7.     yield
  8.     concat( "</div>", block.binding )
  9. end
  10.  

Por supuesto, el ejemplo se puede seguir elaborando o extender a otros usos.

Fuente: “Blocks in views“, en RailsCasts.

7 comentarios para “Rails: helpers con bloques”

  1. GravatarNico Orellana Dice:

    Que buena, estaba “cabeceando” el manejo de niveles de usuarios y esto ayuda muchisimo.

    Por otro lado, RailsCasts idea mia o cada vez mejora mas sus entregas?… se ha convertido sin duda en “must visit if you want to learn rails”.

  2. GravatarIsmael Dice:

    Si, hoy le dediqué 30 hora a ver todos los pendientes y en verdad es un gran aporte.

  3. Gravatarbedomax Dice:

    Hola Ismael ,alguna documentación o libro de ruby on rails en Español que recomiendes para desarrollar.

  4. GravatarIsmael Dice:

    Bedomax
    No, aunque no he buscado en español tpco. Si te animas con el inglés el libro “oficial” de Rails es ultra-recomendable. Rails está escrito en Ruby, así que es buena idea empezar aprendiendo Ruby primero. Otra cosa que es útil para entender la arquitectura de Rails (y MVC en general) es leer cualquier cosa sobre Patrones de Diseño, no necesariamente sobre Ruby o Rails. PHP 5 Objects, Patterns and Practice me sirvió muchísimo a mi que, como muchos venía desde el mundo de PHP.
    Por último, una vez que manejas lo básico de Rails te puede interesar aprender un par de recetas para condimentar tu estilo de desarrollo. En síntesis: lo mejor que se puede hacer para aprender Rails es entender los conceptos que lo sustentan (Orientación a Objectos, MVC) y la terminología (COntroladores, Modelos, Vistas, Helpers) antes de perderse en los detalles.

  5. GravatarRodrigo Dice:

    En sobrerailes.com hay un articulo introductorio de Ruby on Rails traducido al español.

    El original es este articulo de oreilly.

  6. Gravataremilio Dice:

    Buscando en la api de rails, consegui una manera un poco mas intuitiva de hacer las cosas, por ejemplo:

    Supongamos un generador de formularios con estilo basado en tablas.

    def app_form_table1(&block)
    code = ”
    code << capture(&block)
    code << ”
    concat(code, block.binding)
    end

    capture atrapa el codigo del bloque en una variable y por supuesto ejecuta el codigo de ruby contenido en el, y concat permite mostrar en la vista el codigo generado, que en este caso remplazara al bloque.

    Para mayor informacion ver la api de rails.

    Saludos

  7. Gravataremilio Dice:

    Buscando en la api de rails, consegui una manera un poco mas intuitiva de hacer las cosas, por ejemplo:

    Supongamos un generador de formularios con estilo basado en tablas.

    def app_form_table1(&block)
    code = ‘….codigo….’
    code << capture(&block)
    code << ‘….codigo….’
    concat(code, block.binding)
    end

    capture atrapa el codigo del bloque en una variable y por supuesto ejecuta el codigo de ruby contenido en el, y concat permite mostrar en la vista el codigo generado, que en este caso remplazara al bloque.
    Para mayor informacion ver la api de rails.
    Saludos

Deja un comentario

XHTML: puedes usar estas etiquetas: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>