SQLite, booleanos y buenas prácticas
Hace unas semanas estuve implementando un sencillo sistema de votaciones con la ayuda del plugin acts_as_voteable, para un proyecto con Rails, donde me surgió un problemilla que gracias a los tests resultó menos doloroso.
Tras tener ya prácticamente escrita la acción para votar, implementé el test para el controlador con sus diferentes contextos(que sí, que TDD, pero uno todavía está en la fase de acostumbrarse :P). Cuando ejecuté el test por primera vez, esperando que me diera algunos fallos en mi código, me llevé la sopresa de un error SQL con origen en el plugin, que no existía la columna TRUE ¿¿en el where vote = TRUE??.
Lo primero fue pensar que no era posible, con ActiveRecord de por medio eso era un poco raro, por lo que las sospechas fueron para SQLite, que era el gestor de bases de datos en el entorno de tests. Probando a ejecutar los tests con una base de datos MySQL, fallaba mi código y no el del plugin, se confirmó la sospecha.
Una vez implementada completamente la funcionalidad y los tests pasando, tocó perder unos minutos para ver qué estaba pasando y google contesta rápido. Resulta que para utilizar booleanos en queries con SQLite debe utilizarse 'true' y 'false', al mirar el código del plugin se confirmaba el problema:
votes = Vote.find(:all, :conditions => [
"voteable_id = ? AND voteable_type = ? AND vote = TRUE",
id, self.type.name
])
El valor de vote estaba hardcoded, pues como tocaba cambiar el código, aproveché a cambiar self.type que está deprecated, por self.class:
votes = Vote.find(:all, :conditions => [
"voteable_id = ? AND voteable_type = ? AND vote = ?",
id, self.class.name, true
])
Y al ejecutar los tests con SQLite, los pasó. Pero luego resulta que había alguien que ya había solucionado el problema, como era de esperar en la comunidad Rails, en el plugin vote_fu (llegando a combinar funcionalidades complementarias de tres plugins distintos).
Después de crear la migración para eliminar la tabla de acts_as_voteable y crear la de vote_fu, ejecuté los tests del controlador para ver si tocaba cambiar algo, pero pasaban correctamente.
Conclusiones, además de lo aprendido con los booleanos de SQLite:
- Aprovechar (en la medida de lo posible) la independencia de bases de datos que aportan ActiveRecord u otros ORMs, sobre todo si estamos desarrollando componentes reutilizables.
- Y a procurar seguir mejorando en cuanto a la automatización de tests. Desde que empecé a escribir tests, hago commits con la conciencia más tranquila :).