Logo de La Coctelera

A lo largo de todo este tiempo que llevo como desarrollador de Rails he cogido una serie de manías y hábitos, a la vez que he descubierto una serie de herramientas y plugins que me han parecido imprescindibles, y que incluso podrían venir incorporadas de serie en Rails.

Así que tras el clásico rails vaporware_project hago lo siguiente:

Instalar el plugin annotate_models

Se trata de un plugin que te copia un listado de atributos de la clase como comentarios en los ficheros del modelo y de las fixturas mediante un simple rake annotate_models.

El resultado es algo como esto:


# == Schema Information
# Schema version: 4
#
# Table name: sources
#
#  id          :integer(11)   not null, primary key
#  url         :string(255)   default(), not null
#  feed_type   :string(255)   default(), not null
#  title       :string(255)   default(), not null
#  description :text          
#  created_at  :datetime      not null
#  updated_at  :datetime      not null
#
class Source < ActiveRecord::Base

Más información: http://agilewebdevelopment.com/plugins/annotate_models

Instalar el plugin test_fixtures

Este plugin, desarrollado por Ernesto Jiménez, añade dinámicamente un test de las fixturas de cada uno de los modelos.

Más información: http://www.lacoctelera.com/ernesto-jimenez/post/2007/04/19/plugins-mi-propia-cosecha

Instalar el plugin memory_test_fix

Se trata de un plugin que permite que los tests se ejecuten contra una base de datos cargada en memoria, lo cuál hace que vayan infinitamente más rápidos, algo muy recomendable si su número crece y crece.

Más información: http://agilewebdevelopment.com/plugins/memory_test_fix

Tanto este plugin como el anterior son ideales si vas a empezar un proyecto siguiendo la metodología TDD

Limpiar los ficheros database.yml y environment.rb

Esto es más una manía que otra cosa, pero ambos ficheros vienen llenos de comentarios (muy instructivos y útiles, la verdad), pero que hace que ocupen infinitamente más de lo que deberían de ocupar.

Por ejemplo, mi database.yml es así:


development:
  adapter: mysql
  database: vapor_development
  username: user
  password: pass
  host: localhost
test:
  adapter: sqlite3
  database: ":memory:"

Y mi environment.rb es así:


RAILS_GEM_VERSION = '1.2.3' unless defined? RAILS_GEM_VERSION
require File.join(File.dirname(__FILE__), 'boot')
Rails::Initializer.run do |config|
end

Utilizar los generadores de Rails

Los generadores de Rails son realmente útiles para crear las plantillas de los ficheros que vamos a utilizar: son mucho más limpios que el scaffold porque crean los ficheros vacíos, pero ya crean fixturas, controladores, tests, etcétera.

Especialmente recomendable el nuevo script/generate resource item, que nos creará nuestro modelo y nuestro controlador como un recursos, creando también las rutas asociadas.

Copio el script rsql en mi carpeta de scripts

El script rsql nos lo enseñó Juan Lupión, y si le dieran un céntimo por cada vez que lo utilizamos ya sería rico.

Se trata de un script de consola que toma como argumento el entorno (cogiendo por defecto development si no indicamos nada) y abre un cliente de SQL con los datos que lee del fichero config/database.yml, con lo cuál en lugar de un mysql -u user -p password -h host databasename, basta con hacer un script/rsql production para entrar en la base de datos de producción, por ejemplo.

El script no sé de donde es ni que licencia tiene, pero podéis descargar de aquí una versión mejorada por el mismo Juan.

The end

Y eso es todo, hay cosas más personales y hay cosas que son un must do, pero seguro que os resultan útiles.

¿Y tú tienes algún consejo?

Ayer terminó la segunda conferencia Rails americana , que ha tenido lugar en Portland, Oregon. Y ya están disponibles algunas de las presentaciones para ser descargadas.

Si le echáis un vistazo por encima, así a bote pronto destacar la variedad: 2 presentaciones sobre testing, otro para sobre ActiionView, una de Joyent sobre el escalado de aplicaciones web (a la que le he echado un ojo y venía a echar un cable a los chicos de Twitter), REST, routing, y mucho más.

La verdad es que parecen bastante interesantes.

Y como anécdota, una pequeña broma sobre la presentación de David, un bingo con las buzzwords de su keynote:

A destacar bastards de entre todas ellas.

  • sin comentarios compártelo favorito
  • Tags: ,

No los voy a traducir porque soy un vago, pero no dejéis de echárles un vistazo, que seguro que descubrís alguno nuevo:

15 Must know Firefox shortcuts

  • 1 comentario compártelo favorito
  • Tags: ,

ActiveRecord, la librería encargada en Rails de gestionar toda la capa de modelo de datos, incorpora de serie unos callbacks que permiten controlar el ciclo de actualización de un objeto de manera más o menos precisa.

En el siguiente gráfico, extraído del Agile Web Development ed. 2, se puede ver la jerarquía de callbacks y el orden en el que se ejecutan:

Su uso es muy recomendable si queremos escribir un código limpio en los modelos de nuestra aplicación.

Sin embargo, hace unas semanas nos ha surgido la necesidad de ir un poco más allá en los callbacks. Os cuento la situación:

Imaginad un modelo Post y un modelo Blog. En el modelo Blog, tengo un atributo que me dice cuántos posts publicados tiene ese blog (un atributo desnormalizado). Pues bien, con un sencillo after_save en el modelo Post puedo conseguir mantener actualizado dicho campo sin mucho esfuerzo:


class Post < ActiveRecord::Base
  ...
  def after_save
    blog.posts_count = Post.count(:conditions => ["blog_id = ? and status = ?", id, STATUS_PUBLISH])
    blog.save
  end
  ...
end

Este callback se ejecutará, efectivamente, cada vez que publique un post. Sin embargo, también lo hará cada vez que modifique un post que ya existe, para editar el contenido del mismo, o su título, atributos que no están relacionados con el blog al que pertenece el post.

Es decir, en realidad yo sólo quiero que se ejecute mi método after_save en un caso concreto: cuando se publica un post. O mejor dicho: cuando un post cambia de estado. El estado, o status, de un post simplemente indica si es un borrador o está publicado: si está en borrador, no aparece en los listados públicos y si está publicado sí. Por eso, el contador de posts del blog sólo se refiere a posts publicados.

Resumiendo: sólo quiero actualizar el blog asociado a un post cuando cambie el atributo status del mismo.

Y esto, amigos míos, ActiveRecord no lo permite, o por lo menos no de forma nativa. Pero con un poco de imaginación se puede llegar a saber dentro de un callback qué atributos se han modificado en el objeto.

Para ello, utilizaremos una variable de instancia (un atributo, vaya) al que llamaremos before_update_attributes y que va a hacer referencia a los atributos del objeto antes de la actualización. Lo declararemos y lo utilizaremos así:


  attr_reader :before_update_attributes
  ...
  def before_validation
    ...
    @before_update_attributes = Post.find(id).attributes if id
  end

Es decir, en el callback before_validation, el primer callback de los que se ejecutan al modificar un objeto, vamos a guardar los valores de los atributos del objeto en nuestra variable para, posteriormente cuando nos haga falta, comparar los valores actuales con los que había previamente, antes de modificarlo.

Así, nuestro after_save podría quedar así:


  def after_save
    # comprobamos que exista el before_update_attributes y que contenga el status
    return if before_update_attributes and not attributes.diff(before_update_attributes).keys.include?("status")
    # si no existe es que el objeto es nuevo
    # si no contiene el status, es que este atributo no se ha modificado
    blog.posts_count = Post.count(:conditions => ["blog_id = ? and status = ?", id, STATUS_PUBLISH])
    blog.save
  end

Y con este código, realizar los tests es realmente sencillo y no requiere realizar ninguna comprobación extraña, simplemente actualizar o no el status y verificar que se actualiza o no el atributo posts_count del blog.

Reconozco que no es la forma más elegante y que se podría mejorar e incluso generalizar de alguna manera (¿alguien se anima a hacer un plugin?), pero como primera aproximación parida en el tren camino a Valencia no está mal.

Así que animáos a opinar y, sobretodo, me interesa saber si conocéis alguna manera de abordar este problema de otra forma diferente.

En TextMate hay un comando que te permite buscar en la lista de ficheros de un proyecto por su nombre: se activa mediante manzana + T y según vas escribiendo el nombre del fichero te va afinando la lista de candidatos.

Sin embargo, si el fichero es muy largo, como por ejemplo frontpages_controller_test.rb, escribir el nombre puede ser lento e ineficiente.

Hoy, haciendo pruebas he descubierto que si pones la primera letra que sigue a cada guión bajo ('_'), TextMate acierta, y vas mucho más rápido. Así, para el caso de querer abrir el frontpages_controller_test.rb bastaría con escribir fct.

El problema es que puede hacer más ficheros con esas inciales, pero bueno, ya hemos ganado suficiente tiempo como para que no nos importe seleccionar el que queremos mediante las flechas del teclado.

  • 4 comentarios compártelo favorito
  • Tags:

Algoritmos de Yahoo: Flickr Interestingness™ es un post realmente interesante, que explica en detalle cómo (supuestamente, pues todo es ingeniería inversa y una patente) hace Flickr para dotar de relevancia a las fotos que sube la gente y crear la sección Interesting, que seguro habéis visitado alguna vez y conocéis por lo espectacular de sus fotos.

Dicha selección se realiza automáticamente, en base a una serie de baremos que maneja Flickr, como pueden ser el número de vistias a la foto, desde dónde se ha visitado, el número de meta-datos y la calidad de los mismos, o incluso la cercanía de la foto a la ciudad donde has dicho que resides.

Pero en realidad, lo que nos debería de hacer reflexionar este algoritmo es cómo han resuelto un problema, para mí abierto, que es el de la relevancia social de los contenidos generados por los usuarios, ya sean fotos, enlaces, posts, vídeos, etcétera.

Y es que si por algo se caracteriza esta época de Internet que estamos viviendo es por la cantidad de dicho contenido, que obliga a filtrarlo si queremos seguir teniendo vida social, familiar y laboral. Y ahí está el problema, en filtrar lo relevante de lo menos relevante.

Criterios como:

  • número de enlaces entrantes (veces que te han citado)
  • número de visitas
  • número de comentarios
  • tags asociados al contenido
  • karma del autor del contenido
  • o el reciente sistema de clasificación por votos

no aseguran, para nada, dar en el clavo y asegurarnos la interestingness, pero de momento es con lo que nos podemos conformar.

Por suerte cada escenario plantea unas características inherentes a él diferentes, lo que permite elaborar criterios específicos mucho más precisos.

Por ejemplo, todos conocemos del.icio.us y su sistema de recomendación de URLs a través de tu red social. ¿Qué es relevante para ti? Lo que te recomiendan tus amigos. Nada más.

Por otro lado tenemos digg o <pon aquí tu clon>, que cuanto más populares se hacen, el sistema de votaciones se vuelve más permisivo, y se convierten en medios más genéricos, con lo cuál abarcan más usuarios, pero éstos están más insatisfechos con los contenidos. ¿La solución? Más contenido en portada, con lo cuál volvemos a tener que filtrar el resultado del filtro (votos, en este caso)

Y por último, tenemos la fusión de estos dos conceptos en coRank, como se puede ver en este pequeño gráfico incluído en su web:

Problemas:

  • tienes que convencer a tu red social de que lo utilice
  • es un concepto que requiere mucha más labor activa por parte del usuario, que la que puede requerir del.icio.us, pues el filtrado va implícito al uso de la herramienta (sino para qué utilizarla, pudiendo utilizar un agregador convencional), con lo cuál el usuario se va a cansar y va a terminar abandonándola
  • tiene, además, el peligro de que los primeros siempre serán los primeros, es decir, que los que están ya arriba en el ránking, van a seguir estando por mucho tiempo

Y esto es de lo más nuevo en filtrado colaborativo que se ha hecho últimamente, y la lista de aplicaciones que han fracasado no es corta, precisamente (¿recordáis Rojo?)

Concluyendo: que es un problema difícil, y lo es más, cuanto más se intenta abarcar. Supongo que pronto irán surgiendo nuevas ideas, cada vez más basadas en redes de confianza, pues si al final el uso de internet se está extendiendo tanto éstas cada vez serán más numerosas, y ¿qué mejor forma de que te digan tus "amigos" qué tienes que leer?

El equipo de desarrolladores de The Cocktail hemos escrito una pequeña documentación sobre cómo hemos resulto nosotros el problema de la lectura de varias bases de datos simultáneamente utilizando Ruby on Rails.

Todo, dicho sea de paso, a raíz de la polémica generada por la entrevista a Alex Payne (un desarrollador de Twitter), la contestación de David HH y los comentarios chismosos de algún blogger amarillo de esta nuestra blogosfera, cuyo blog no citaré.

Por cierto, lo podéis leer directamente desde aquí (pdf).

Y si queréis bucear un poquito más, en la lista de correo de Ruby on Rails en castellano se está generando un hilo muy bonito, con gran cantidad de información, y sin trolls ni polémicas.

Acaba de anunciarse serestandar.es una iniciativa que pretende ser

Un conjunto de talleres y conferencias sobre diseño y desarrollo web con estándares, en los que participarán como ponentes muchos de los mejores diseñadores y desarrolladores cuyo método de trabajo está basado en el respeto a los estándares web.

Allí estaremos algunos conocidos del sector durante tres días, hablando sobre web y estándares, así que parece que será interesante y divertido.

El evento tendrá lugar del 27 al 29 de junio en Sevilla.

Sobre in web we trust

Avatar de Fernando
Valencia y Madrid, España
ver perfil »
contacto »
Blog personal de Fernando Blat, desarrollador en The Cocktail, sobre programación web y Ruby on Rails. Puedes seguir a "mi otro yo" en blat.