4 Trabes

Obtener n registros aleatorios (Oracle,MySQL+Hibernate) utilizando HQL

Publicado por el Miércoles, 27 de Febrero de 2008

Este problema me ha dado la lata un buen rato. Me animo con este post porque no he encontrado prácticamente ninguna información sobre cómo hacer esto. El problema que queremos solucionar es sencillo de explicar:

Tenemos una entidad llamada FooData. Queremos recuperar n objetos fooData aleatorios.

Suponiendo que la tabla correspondiente a FooData es foo, en mysql podemos resolver nuestro problema con una query tal que así:

select  * from foo order by rand()  limit n;

En Oracle 9 la query es un poco más compleja, sobre todo por la parte de limitar el número de registros a devolver, que se resuelve con una subquery:

select * from (
  select * from rolleruser order by dbms_random.value) 
where rownum < n

Una vez que sabemos resolver nuestro problema en SQL y que ya hemos visto que no hay una solución estándar, vamos a tratar de implementarlo mediante HQL.

La parte de obtener únicamente n resultados es trivial, ya que disponemos del método org.hibernate.Query.setMaxResults(int arg0). El esqueleto de nuestro código sería parecido a:

Session session =
	((HibernatePersistenceStrategy)this.strategy).getSession();
Dialect currentDialect = 
	((SessionFactoryImplementor) session.getSessionFactory()).getDialect();

String queryString = null;

if (currentDialect instanceof Oracle9Dialect) {
 	// Oracle 9 specific
    	queryString = "CUSTOM_QUERY_ORACLE";
}
else {
	// MYSQL specific
    	queryString = "CUSTOM_QUERY_MYSQL";
}

Query query = session.createQuery(queryString);
query.setMaxResults(amount);

Donde será necesario sustituir CUSTOM_QUERY_ORACLE y CUSTOM_QUERY_MYSQL por los valores adecuados en cada una de las ramas del if.

HQL para obtener n registros aleatorios con MySQL

Para hacer esta consulta con HQL "sobre" mysql, la traducción es casi directa. Eliminamos el limit, pues ya limitamos el número de resultados con setMaxResults() y cambiamos el nombre de la tabla por el nombre de la entidad, de modo que en el ejemplo anterior donde teníamos CUSTOM_QUERY_MYSQL, ahora tendremos:.

from FooEntry foo order by rand();

HQL para obtener n registros aleatorios con Oracle 9

Esta traducción es casi tan trivial como la anterior, pero con matices. Utilizando la misma lógica que en el apartado anterior llegamos a una query más o menos así:

from FooEntry foo order by dbms_random.value;

Esta query no funciona, pues nuestro amigo Hibernate trata de buscar el atributo value de la entidad dbms_random. Y no encuentra el mapping, porque no lo hay. Solo tenemos que buscar la manera de que la BD reciba la query adecuada. Tras un buen rato de ensayo-error, llegamos a la siguiente solución:

from FooEntry foo order by dbms_random.random()

Ahora nuestro driver si que es capaz de "saber" que dbms_random.random() no es cosa suya y que lo único que tiene que hacer es dejar pasar ese trocito de query para que Oracle juegue con el.

Sustituyendo CUSTOM_QUERY_ORACLE por esta última query, ya tendremos el puzzle completo.

Atajos de teclado (shortcuts) vitales para sobrevivir a Eclipse (I)

Publicado por el Lunes, 25 de Febrero de 2008

En algún post anterior david o asis, no recuerdo cual de los dos, habló acerca de algunas cosas básicas para sobrevivir a Netbeans. En este post voy a hacer un breve repaso de algunos shortcuts absolutamente imprescindibles para sobrevivir a Eclipse. Como ando un poco apretado de tiempo, incluiré solo 3 shortcuts en este post, los pata negra.

ctrl+shift+r: Open Resource

Básico entre los básicos. Nos permite abrir cualquier recurso que tengamos en nuestro workspace. No me gusta nada la palabra recurso, pero parece que está asentada, así que habrá que asumirla :(. Un recurso es básicamente cualquier fichero que viva en nuestro workspace. Es un sistema de búsqueda rápido y eficaz, se pueden utilizar comodines y ahorra muchísimo tiempo con respecto a buscar por el árbol de clases. Utilidad creciente con el tamaño de los proyectos. Cuando el proyecto es grande puede experimentarse algún episodio de apreciación distorsionada de la velocidad de esta herramienta (ver post sobre velocidad psicológica).

ctrl+shift+t: Open Type

Nos permite abrir un tipo. En un contexto Java, que es donde suelo utilizar Ecipse, nos permite abrir rápidamente cualquier clase o interface definida en nuestro workspace. Personalmente lo utilizo bastante menos que el anterior, pero también es imprescindible. Aglutina las mismas virtudes que el anterior y se muestra como un arma de precisión a la hora de localizar esa inner class que se resiste a ser localizada

F4: Jerarquía

Mi atajo favorito cuando aterrizo en un interface. F4 nos muestra la jerarquía de clases asociada al elemento activo. Además de la utilidad obvia, para mi esta vista tiene una utilidad extra bastante interesante. En el menú contextual que aparece al pulsar el botón derecho del ratón sobre cualquier elemento de la jerarquía, tenemos la opción "Copy Qualified name", que resulta bastante cómoda para cosas como modificar tu log4j.properties.

Algún día editaré una segunda parte con otro puñado de ellos. Mientras tanto, podéis hacer vuestras contribuciones en forma de comentarios :D

Grandes descubrimientos de nuestro tiempo: Si true entonces true, sino false

Publicado por el Jueves, 21 de Febrero de 2008

var isIE  = (navigator.appVersion.indexOf("MSIE") != -1) ? true : false;

Pero qué co…

Zed's so fucking awesome

Publicado por el Domingo, 17 de Febrero de 2008

No sé si Zed es tan “awesome”, pero “funny” lo es sin duda. Que cachondo el papá de mongrel.

PD: No os perdáis el post Rails is a ghetto que lo ha convertido en “infame”.

Velocidad psicológica

Publicado por el Jueves, 14 de Febrero de 2008

Mi ordenador no se mueve. Va lento. ¿Cómo es posible? Si apenas tienes 5 meses. Si es una máquina de matar.

Tranquilo. Tu ordenador está en perfecto estado y va tan rápido como siempre. Es un problema de velocidad psicológica. Cuanto más trabajo tienes y más rápido quieres ir, más lento te parece tu equipo. Y no, lo siento, trabajar menos o más despacio no es la solución al problema.

Utilizar dos códigos de seguimiento de Google Analytics en una misma página

Publicado por el Jueves, 14 de Febrero de 2008

Siguiendo el ejemplo de david y asis, retomo la labor divulgativa- o divagativa - después de una larga temporada de inactividad bloguera. El tema de hoy puede resultar de interés para todos aquellos que necesitáis llevar seguimiento de las visitas a vuestros sitios y utilizáis Google Analytics. Vamos a ver cómo es posible utilizar varios códigos de seguimiento para una misma página.

Todos sabemos que Analytics es muy flexible: permite hacer filtros, dar acceso a distintas cuentas a distintos datos, etc. ¿Qué necesidad puede haber de utilizar dos códigos de seguimiento en una misma página? Se me ocurren varios casos, pero el más frecuente es que las estructuras de las empresas frecuentemente son más rígidas que la tecnología y puede ser más dificil conseguir que te den acceso a los datos de una cuenta de analytics que poner un nuevo código. Posiblemente tampoco haríamos reescrituras en tomcat si pudiésemos tocar el Apache. Ya sé que son temas muy distintos, pero el origen es parecido: un entorno controlado obliga a hacer las cosas buscando tocar en el menor número de sitios posible.

La teoría para este proceso viene directamente de los señores de Google, que en un howto de migración de urchin.js a ga.js nos dicen que para utilizar dos códigos en una página tenemos que hacer lo siguiente:

Como vemos, el proceso es muy sencillo, simplemente incializar un flag e introducir el nuevo código...pero no funciona. Parece lógico pensar que pueda faltar una llamada a urchinTracker() después de reiniciar el flag y establecer el nuevo código. Una vez hechas las pruebas oportunas se comprueba que efectivamente falta la susodicha llamada, siendo el código correcto para lo que pretendemos hacer algo como lo siguiente:

<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
  _uacct = "UA-12345-1";
  urchinTracker();
  _uff = 0; // Reset flag to allow for second account
  _uacct = "UA-67890-1";
  urchinTracker();
</script>

Sencillo y bastante útil. Eso si, es necesario acordarse de fijar el dominio adecuado para evitarnos problemas a la hora de recibir los datos. En mi caso la primera de las cuentas fija un dominio, algo así como:

_udn="dominio_cliente.com";

y para la segunda cuenta me viene mejor con un escueto:

_udn = "none";

Todos aquellos que no tengáis filtros en vuestras cuentas, podéis hacer como que no habéis leído esta última parte :D.

¿Por qué lo llaman Firebug? (cuando quieren decir... Firebug)

Publicado por el Miércoles, 13 de Febrero de 2008

Imagino que conoceréis Firebug. Es una maravillosa extensión del Firefox que permite desarrollar páginas web de una manera antes jamás soñada :D.

Con el Firebug podemos inspeccionar los valores de las propiedades CSS, los valores calculados por el navegador, depurar Javascript… vamos, que es una herramienta indispensable para desarrollar.

Por otro lado, no sé si sólo nos pasa a nosotros, pero últimamente (me refiero a un últimamente largo, algo así como ¿un año?), el Firefox se está convirtiendo en una especie de monstruo tragamemoria un tanto inestable (es posible que se deba a que lo estamos ejecutando en una Fedora de 64 bits… o a que esté cargado de extensiones… o a muchas otras cosas, es posible). La cuestión es que a veces abres una página y el Firefox decide cerrarse, y lo hace cada vez que intentas visitar esa página (¿tal vez algún plugin quisquilloso o una extensión remilgada?). Y otras veces dice que sí, que ha cargado con éxito una página, pero sigue enseñando la página anterior…

Este último comportamiento es especialmente odioso cuando estás desarrollando una aplicación web: “cambio esto aquí, toco allí, y debería salir esto… a ver a ver, F5… ¿no sale? mmm Claro, claro, toco aquí, le doy allí, un poco más por acá… F5… ¿ein? background: red; color: lime;... F5… ¬_¬U”. En ese momento caes en la cuenta de que, ¡oh!, ¡pero si la acción se ejecuta en el servidor! ¡Los valores cambian en base de datos! ¡Es el Firefox que no te quiere enseñar la página! Así que lo cierras, lo vuelves a abrir, y ahora sí: los cambios están ahí. Después de todo sabías lo que hacías.

Pues bien, parece que este comportamiento se debe al Firebug (al menos en nuestros equipos), y hay otra solución además de cerrar y ejecutar de nuevo el Firefox: si tienes activo el Firebug, lo minimizas y lo vuelves a mostrar (o al revés) y ¡la página con todos los cambios aparece por arte de birlibirloque! (en este momento no sabría decir qué sucede cuando lo desactivas directamente…).

Ahora entiendo que lo llamen Firebug.

Excel no puede ser una fuente de datos normalizada

Publicado por el Domingo, 10 de Febrero de 2008

Sergio, te acompaño en el sentimiento.

Trabe, Ruby, Rails y el hip-hop

Publicado por el Domingo, 10 de Febrero de 2008

Este post va dedicado: al hombre detrás de Jasypt para que no me diga que lee el blog pero no entiende nada.

Ya casi llevamos dos años de Trabe, así que los balances, las miradas atrás, las lecciones aprendidas, etc. comienzan a cobrar un poco de sentido. Todavía somos una empresa joven (muy joven, dirán algunos) pero el tiempo es inexorable y ya ha transcurrido suficiente como para que empiecen a notarse los “posos” que la experiencia va dejando acumulados.

Creo que lo que más ha marcado estos dos años a nivel tecnológico ha sido el uso de Rails como framework de desarrollo web. Como ya hemos dicho otras veces (creo recordar), y como siempre decimos en nuestras escasas charlas y ponencias, somos muy poco dogmáticos a la hora de utilizar tecnologías, de modo que todo lo que diga a continuación no se debería interpretar como una loa a Rails, ni mucho menos como una muestra de desprecio hacia otros frameworks. Son sólo una serie de pensamientos, incluso no demasiado meditados :P, pero aquí los dejo de todas formas.

Trabe y Rails

Lo primero que pensé cuando vi por primera vez código Rails (es decir, Ruby), antes de que montaramos la empresa, fue algo así como “¿qué demonios…?”. Por aquel entonces estaba trabajando con las primeras versiones de Monorail y quería saber de donde había sacado el amigo Hammet su inspiración. Lo vi y me volví rápidamente al confortable mundo de los lenguajes compilados (aunque fuese un mundo .NET), eso sí, con la sensación de que, aunque por aquel entonces no entendiese nada, algo bueno tenía que haber en todo eso de Rails, porque Monorail era realmente bueno.

Cuando montamos la empresa todos teníamos experiencia en el desarrollo de aplicaciones web con frameworks “tradicionales” como Struts o ASP.NET y sabíamos, porque los habíamos sufrido en nuestras carnes, cuáles eran sus problemas; así que decidimos darle una oportunidad a Rails. Empezamos desarrollando nuestra propia Intranet y un pequeño proyecto de comercio electrónico, y una vez comprobamos que realmente era posible utilizar Rails (y que éramos capaces, que es algo que hay que comprobar y demostrarse a uno mismo, y que mucha gente parece obviar) empezamos a ofrecerlo como solución a nuestros clientes.

Desde esos inicios hemos montado desde pequeñas webs casi estáticas hasta una completa (y compleja) solución de comercio electrónico, sufriendo las carencias y problemas de Rails (aquí nadie se libra, amigos) y disfrutando de sus muchas ventajas.

Rails y Ruby

Y es que, si bien Rails es un framework al que se puede acusar de muchas cosas, cuenta con una ventaja sobre muchos de sus competidores: está escrito en Ruby. Y es que Ruby es un lenguaje realmente peculiar (supongo que en realidad es muy parecido a muchos otros, pero mi experiencia con lenguajes dinámicos no es muy amplia, así que tendréis que disculparme). Es peculiar, decía, porque, aunque al principio resulta complicado de entender, una vez te acostumbras permite escribir de manera terriblemente compacta pero a un tiempo perfectamente clara algunas construcciones que en otros lenguajes necesitan diez veces más líneas y cinco veces más llaves, paréntesis y puntos y coma.

Así, lo compacto de Ruby, unido a las buenas ideas que el señor DHH aplicó en Rails, dan como resultado un framework que permite desarrollar realmente rápido, sin la sensación de pesadez, lentitud y “mamotretismo” (disculpas por la palabrilla) que son inherentes a otras opciones (léase en este caso, si así se desea, Struts).

Rails, Ruby y el hip-hop

Este es un símil que surgió hace un par de semanas por Trabe:

RubyOnRails es como el hip-hop

No sé muy bien a cuento de qué venía, pero sí sé cuál es su sentido: muchas veces, la sensación al desarrollar con Rails es la de estar encadenando rimas. La base del tema son esas tareas repetitivas a las que al final se reduce el 80% de cada aplicación, ese continuo leer datos, mostrar datos, modificar datos, repetido una y otra vez. Y sobre esa base, Rails – gracias principalmente a Ruby – permite escribir código con flow. Mientras que con otros frameworks tienes la sensación de estar en un monasterio entonando un canto gregoriano (que no digo que no sea bonito, pero a veces se hace lento, repetitivo y pesado), con Rails tienes la sensación de estar rimando, fluyendo sobre la base, buscando la estructura que mejor se ajusta a cada nuevo problema. Y, como en el rap, dices mucho en poco espacio, mientras que hace falta mucho tiempo de canto gregoriano para cantar unas pocas frases.

Y es que puede que el hip-hop no tenga la solera del canto gregoriano, pero no se puede negar que tiene ritmo :D.

Trabe, Ruby, Rails y el hip-hop

Resumiendo, que en Trabe nos gusta Rails (a unos más que a otros, eso sí), que nos gusta el estilo que imprime al desarrollo. Y que también nos gusta el hip-hop (de nuevo, a unos más que a otros :).

Y termino, como no podía ser de otra manera, con una cita de SFDK, extraída del tema Mi nombre es rap, de su nuevo álbum Los Veteranos:

La lengua se me afila
ve y cuéntale a tus amigas que has conocido al rap
que ya conoces mi nombre de pila

Listo.

La gemela malvada

Publicado por el Sábado, 09 de Febrero de 2008

Hoy os recomiendo que le echéis un vistazo a la entrada Evil Twin Plugin en err the blog donde comentan una técnica muy sencilla para modificar el comportamiento de los plugins que uséis sin tener que modificar su código (cosa mala, caca, no tocar).

Consiste, resumiendo mucho, en crear un plugin con el nombre ”#{nombre_del_plugin_a_modificar}_{override|extensions|tu_palabra_favorita}” que se inicializará después del original (ya que Rails carga los plugins en orden alfabético) para poder modificarlo al gusto.

Nosotros lo habíamos hecho alguna vez, pero no lo había visto antes por escrito y bien explicado. Así que, gracias y ahí queda eso.

Y ya que últimamente es costumbre en este blog, una cita… El orgullo y la debilidad son hermanos gemelos (James Russell Lowell)

NetBeans 6.0: plantillas de código

Publicado por el Sábado, 09 de Febrero de 2008

Las plantillas de código (code templates en inglés) son pequeños snippets de código fuente que se expanden automáticamente permitiéndonos modificar determinadas partes, mientras que otras partes se mantienen fijas. Aunque son una funcionalidad disponible en todo editor que se precie, no todo el mundo parece darse cuenta de su potencial: las plantillas de código son a los editores / IDEs lo que el DRY es a la programación.

Las plantillas se invocan normalmente escribiendo una pequeña palabra en el editor y pulsando una tecla o una combinación de teclas para “dispararlas”. Para quien no conozca el mecanismo, las dos siguientes imágenes sirven como ejemplo: al escribir en el editor del NetBeans la palabra def y pulsar a continuación la tecla tab (primera imagen), obtenemos la expansión de una definición de un método en Ruby (segunda imagen).

Netbeans code templates
Netbeans code templates

El cursor queda situado automáticamente en method_name, permitiéndonos escribir el nombre que queramos, y una vez pulsamos enter o bien tab de nuevo, el cursor pasa al cuerpo del método, para que podamos seguir codificando.

NetBeans trae una serie de plantillas definidas por defecto, pero a través del menú Tools > Options > Editor > Code templates podemos acceder a un panel en el que, además de poder ver todas esas plantillas predefinidas, podemos crear las nuestras propias. Hay bastantes opciones a la hora de controlar cómo se expande la plantilla; para una descripción más exhaustiva de todas ellas, aquí está la página del wiki de NetBeans dedicada a las RubyCodeTemplates.

Aquí sólo vamos a mostrar la definición de la plantilla def tal y como viene “de serie” con el NetBeans:

Netbeans code templates

La sintaxis es sencilla:

  • El código (Ruby, RHTML, CSS, Java, etc.) se escribe tal cual y quedará así al expandir la plantilla.
  • Los valores “plantillados” se definen mediante ${nombre default=”valor_por_defecto”}; estos valores se expandirán al valor default, pero podremos modificarlos cambiando ese valor por defecto por lo que nosotros queramos. Además, al poder nombrarlos, podremos hacer referencia a ellos en varias partes de la plantilla (ver ejemplo más adelante).
  • A mayores, existen una serie de valores predefinidos que nos permiten: situar el cursor al terminar la expansión (${cursor}); incrustar el código seleccionado (${selection}); incrustar el nombre del fichero en el que se está realizando la expansión (${file}) etc.

Las posibilidades son muchas (no tantas como en el TextMate, quizás, pero muchas al fin y al cabo :P). Como ejemplo, sirvan un par de plantillas que utilizamos muy a menudo en nuestros editores:

Plantilla b

  <% ${0 default="block"} do %>
    ${selection}${cursor}
  <% end %>

Con esta plantilla definimos bloques en Erb, algo que hacemos muy a menudo ya que normalmente usamos helpers de este tipo para capturar las distintas partes de nuestro layout.

Una cosa que hemos aprendido con la experiencia: algunas plantillas, se utilizan tanto para rodear código ya existente como para generar código desde cero. En esos casos el truco de poner ${selection}${cursor} permite utilizar la plantilla para ambos fines. ¡Y otra cosa importante! Las plantillas que incluyen el parámetro ${selection} se pueden invocar de dos maneras: utilizando una tecla (p.e. tab), en cuyo caso contarán con una selección vacía, o utilizando la combinación Alt+Enter. En funcionamiento:

Netbeans code template expansion Netbeans code template expansion

Plantilla t

  <${0 default="div"} id="${1 default=""}">${selection}${cursor}</${0}>

Netbeans code template expansion

Esta plantilla la utilizamos para generar tags HTML con un id. En este caso el parámetro 0 se sustituye con el nombre del tag, tanto en la apertura como en el cierre. El parámetro 1 se sustituye por el id del elemento. Y de nuevo utilizamos el truquillo de la selección para poder rodear HTML si lo deseamos.

Son sólo dos ejemplos, pero en nuestro trabajo diario utilizamos un buen puñado de plantillas que nos permiten acelerar las tareas de codificación y evitar errores al teclear. Pensad en el código que repetís constantemente y definid vuestras propias plantillas para facilitaros la tarea; una vez lo hagáis no podréis vivir sin ellas.

¿Qué fuente es esa?

Publicado por el Lunes, 04 de Febrero de 2008

Consolas on Netbeans

david: ¿Qué fuente es esa?
asís: Es consolas
david: ... me gusta…

NetBeans 6.0: "IDEal de la muerte"

Publicado por el Lunes, 04 de Febrero de 2008

Por si el título no lo deja claro, lo repito aquí: NetBeans se ha convertido desde hace unos meses en la opción a la hora de elegir un IDE para desarrollar aplicaciones Rails. Al menos ha sido nuestra elección y, por lo que puedo decir tras varios meses de trabajo, primero con las versiones beta y ahora con la release definitiva, creo que hemos acertado de pleno al abandonar nuestro querido Aptana RadRails y pasarnos a la “competencia”.

NetBeans proporciona un entorno de trabajo muy cómodo, manejable y potente, del que me gustaría destacar las siguientes características:

  • Integración con SVN de serie
  • Syntax highlight
  • Autocompleción de tipos, variables, funciones, parámetros, columnas de BD, etc.
  • plantillas inline à la Textmate (o casi, vale)
  • Hints sobre posibles errores en el código
  • Control de los generadores Rails y las tareas Rake desde el propio IDE
  • Depuración de código Rails

Es una pequeña lista. Para obtener información más detallada sobre NetBeans podéis echarle un ojo a su propia página (el enlace está ahí atrás, donde dice “netbeans” :-P) o bien googlear un rato: hay un montón de gente ahí fuera encantados con este magnífico IDE para Rails.

De todos modos, por aquello de dejar salir mi lado negativo a pasear, antes de despedirme voy a comentar lo que menos me gusta de NetBeans en comparación con RadRails (es decir, Eclipse)

  • La vista de sincronización de SVN. Prefiero la vista de los Eclipse, me da una noción más clara de qué ha cambiado (NetBeans muestra un listado plano de los ficheros con cambios, mientras que el plugin de Eclipse permite ver los ficheros en un árbol, colgando de sus carpetas padre)
  • La gestión de las preferencias. En Eclipse se puede controlar casi cualquier aspecto del IDE, y encontrar cada preferencia es muy sencillo gracias al maravilloso sistema de búsqueda integrado en los diálogos de configuración. Por contra, encontrar en el NetBeans un determinado parámetro es una tarea de rastreo casi lineal hasta dar con ella que puede llegar a desesperar (por ejemplo, cambiar los atajos de teclado se convierte en un infierno)
  • Por último, falta una opción (al menos yo no he conseguido encontrarla) que permita enlazar el editor de código con el árbol del proyecto. Se puede seleccionar el fichero que se está editando en el árbol del proyecto utilizando una combinación de teclas (ctrl+shift+1 si mal no recuerdo), pero a veces se hace tedioso. Aquí de nuevo gana el Eclipse, al permitir enlazar o desenlazar el editor y el árbol al libre albedrío del desarrollador, como debe ser.

Efectivamente, son tres pijadas. Y por eso mismo recomendamos NetBeans como IDE para Rails: porque los únicos argumentos que tenemos en contra no son argumentos, son pijadas.

(Y ya para terminar, una cita de la introducción a La lucha contra el demonio, de Stefan Zweig, a cuento de las comparaciones) [...] la comparación enriquece, pues realza los valores, dando una serie de reflejos que, alrededor de las figuras, forman como un marco de profundidad en el espacio.

Si Rails no es multihilo entonces...

Publicado por el Sábado, 02 de Febrero de 2008

...podemos olvidarnos de algunas costumbres adquiridas con otras plataformas (léase J2EE o .NET) y aprovechar ciertas construcciones de Ruby que en un entorno multihilo sería problemático usar libremente. ¿A qué me refiero?, a variables de clase.

Las amigables variables de clase almacenan valores compartidos por todas las instancias de dicha clase, y a estas alturas todos deberíamos saber que si más de un hilo puede leer/modificar una de estas variables, tenemos que gestionar la concurrencia. No obstante, el caso de Rails es diferente. Podemos asegurar que cada instancia de nuestro servidor (normalmente un mongrel) sólo va a ejecutar un hilo por cada petición y por tanto podemos utilizar las variables de clase impunemente.

Supongamos, como ejemplo, una página que muestra varios valores monetarios sujetos a tipo de cambio. Supongamos el siguiente código que gestiona ésto (sin entrar a discutir si es adecuado o 100% correcto, que no lo es, ya lo sé, pero para ilustrar la idea vale).

class Currency
  TYPES = %w(euro dollar)

  attr_accessor :value

  def initialize(value)
    self.value = value
  end

  def to
    Exchange.new self
  end

  alias :in :to  
end

class Dollar < Currency
  def to_s
    "#{value}$" 
  end  
end

class Euro < Currency
  def to_s
    "#{value}€" 
  end
end

class Exchange
  cattr_accessor :rates

  def initialize(currency)
    @currency = currency
  end 

  for currency in Currency::TYPES
    class_eval %{
      def #{currency}        
        rate = self.class.rates[:#{currency}][@currency.class.name.downcase]
        #{currency.classify}.new @currency.value * rate
      end

      alias :#{currency.pluralize} :#{currency}
    }
  end
end

class Fixnum
  for currency in Currency::TYPES
    class_eval %{
      def #{currency}
        #{currency.capitalize}.new self
      end

      alias :#{currency.pluralize} :#{currency}
    }
  end
end

De tal modo que, para cada petición sólo es necesario fijar una vez las tipos de cambio, usando para ello un before_filter ...

def exchange_rates_set_before_filter

  # ... Lógica real para obtener los tipos de cambio ...

  Exchange.rates = HashWithIndifferentAccess.new({ 
    :dollar => { 
      :dollar => 1, 
      :euro => 1.49 
    }, 
    :euro => { 
      :euro => 1, 
      :dollar => 0.67
    }
})

Y así poder escribir en nuestras vistas cosas sencillas y elegantes como:

1.dollar.in.euros #=> 0.67€
2.euros.in.dollars #=> 2.98$