Junin de los Andes

Estas pascuas tocó visitar Junín de los Andes, lugar por el que pasé mil veces pero en el que nunca había estado el sufuciente tiempo como para recorrer la zona.

El fin de semana empezó en duda, ya que los cortes de ruta por los docentes rionegrinos y neuquinos estuvo en pié hasta último momento, pero por suerte el conflicto se «solucionó» y pudimos viajar.

La zona como toda la zona cordillerana neuquina es muy linda, más cuando te tocan días de 27 grados y sin nubes :). Hicimos caminatas a lagos, cascadas, volcanes y alguna que otra cabalgata para descansar. Comimos mucho ahumado (sobre todo jabalí y ciervo :D) y mucha cerveza y fernet para acompañar.

Volvimos tempranito el domingo porque mi cuñado viajaba a la noche para buenos aires (pobre!) mientras yo por suerte me quedé descansando en Cipolletti hasta el 26, día en que me toca volver a la tierra maldita (a.k.a Ciudad autónoma de buenos aires).

Un descando cada varios meses no vienen mal :).

Consejos ante una emergencia

El otro día en las aulas de la UP se podían leer los carteles de cómo responder ante una emergencia, y lo curioso eran las últimas dos recomendaciones :

Una lástima que solo tenía el celular para capturarlo, espero que lo puedan leer, así están prevenidos y no hacen lío en una emergencia :).

Take A Photo – Fotos instantáneas desde tu web

En la última semana estuve trabajando en agregar nuevas funcionalidades a un sitio de un cliente y entre los pedidos estaba una especie de Fotoblog para los usuarios (y bue, hay que pagar las cuentas a fin de mes :P).

La cosa salió rápido, usando Paperclip que guarda las imágenes que se suben, se muestra en orden, etc, nada del otro mundo. Pero hablando con el cliente surgió la idea de hacer que el usuario se pueda tomar una foto directamente desde la web usando su webcam, así que después de decir «si, se debe poder hacer» mentalmente me salió un «doh!, que dije!«. Lo último que se dijo en esa reunión fue «Lo quiero» :D.

Ya había visto juegos flash que utilizan la webcam así que empecé por ahí, para ver como sacaban un frame del video, lo cual era muy fácil. Lo siguiente era serializarla. A falta de algo mejor hice un serializador de imágenes muy pedorro, pero que anda (aunque es lento), que envía por POST la información de cada pixel.

La parte de Ruby fue fácil y decidí encapsularla en un plugin de Rails para poder reutilizarlo luego o por si a alguien más le sirve :). Además se puede integrar con Paperclip o AttachmentFu para hacer la persistencia de la imagen en donde sea.

La única parte que usa Flash es el capturador de la cámara, porque otra no quedaba, pero luego el botón para tomar la foto y los eventos se manejan todo por Javascript.

El plugin tiene varios TODOs, pero por si a alguien le sirve está en github.

Update : A falta de demo, algunas de las fotos tomadas con la aplicación de ejemplo que hice hoy durante Locos x rails.

Locos X Rails – ¡últimos lugares!

Así es, ya quedan apenas unos pocos lugares disponibles. Vos, que le tenés ganas, ¿te lo vas a perder?.

La registración en online y vas a poder disfrutar de charlas dadas por reconocidas figuras como David Heinemeier Hansson (creador de Rails),Obie Fernandez, Luis Lavena, Yehuda Katz y Fabio Akita, entre otros.

En pocos días (3 y 4 de abril) ya vamos a estar todos Locos x Rails :), te esperamos!

Cómo ser un hacker famoso

Uno leyendo descubre muchos hacker famosos : Capitan Krunch, El Chacal, Kevin David Mitnick, en fin, lista larga. Pero lo realmente difícil es estar entre esos nombres.

Bueno, a no desesperar, en Argentina, país de oportunidades, es más fácil de lo que parece :

  1. Create un blog
  2. Escribí mucho y además publicá algún proyectito de software libre o participá en uno
  3. Hacelo varios meses, así hitteas bien en Google
  4. Espera que un diario publique tu nombre en algún complot del gobierno 🙂

Si, adivinaste, mi nombre está en esa lista :), va, aunque por ahí no soy yo ya que «Se omiten los nombres completos y los domicilios por cuestiones de seguridad«, pero 99.99999% que se refieren a mi :D.

Refactoring de «Fat Methods» – Episodio 5

Pasar programadores PHP a Ruby no siempre es una tarea trivial, mayormente porque lo primero que tratan de hacer es escribir código en lugar de pensar que es lo que quieren hacer :). No es que me queje, a todos nos pasa que resolvemos el problema como primero sale (más aún cuando las fechas de entrega son apretadas :).

El otro día queriendo modificar un código me encuentro con este before_filter en un controller :

def setprofile
  @viewer = false
  if (!params['id'] && !params['profile_id'])
    @profile = @passport
  else
    if params['profile_id']
      pid = params['profile_id']
    else
      pid = params['id']
    end
    @profile = Passport.find_by_id(pid)			
    if (!@profile) 
      redirect_to(:controller => 'my3dg', :action => 'show') and return false
    end
    if (@profile.id != @passport.id)
      @viewer = true
    end			
  end
end

Lo primero que pense «uff, que paja, que complicado» hasta que miré mejor la estructura y ahí comprendí que en realidad era muy simple, solo que estaba escrito de forma complicada. Lo primero que me gustó de Ruby cuando empecé a entenderlo fue el uso de «||» para reemplazar esos molestos if anidados cuando tengo más de una opción. «Si no está a, poner a en el valor default». En ruby es un simple «a || valor_default» (ojo con los valores de verdad en ruby).

Lo otro que veo mucho (incluso en los trabajos que corrijo en la facultad) es utilizar un if para después setear una variable en true o false, cuando casi todos los lenguajes aceptan expresiones booleanas del lado derecho de la igualdad.

Refactorizando el método anterior obtenemos el siguiente código :

def setprofile
  @profile = Passport.find_by_id(params['profile_id'] || params['id']) || @passport
  @viewer = @profile.id != @passport.id
  redirect_to(:controller => 'my3dg', :action => 'show') unless @profile
  return false unless @profile
end

Como nota, uso find_by_id porque retorna nil en caso de no encontrar el registro, en cambio find tira una excepción RecordNotFound, de esa forma puedo acoplar otro «||» para setear el valor default (@passport es la credencial del usuario loggeado en este caso).

Limpiando los mails de Yahoo Groups

Una de las cosas más molestas que tiene Yahoo Groups es la cantidad de basura que le mete a los emails que llegan desde el grupo. Como dicen, una imagen dice más que mil palabras :

Es realmente perturbante, sobre todo porque lo pone en cada email. La primer opción que busqué fue decirle a Gmail que me muestre los emails como plain-text, lo que no encontré. Después recordé que como uso Gmail para trabajar, me llegan emails con links en html-only :S, por lo que de todas formas no me servía.

Entonces dije «no hay drama, lo modifico con Stylish«, una extensión de Firefox que permite mediante CSS cambiar cosas (y un poco más liviana que Greasemonkey). La cosa no fue tan fácil, ya que el HTML que inserta Yahoo no tiene ni class ni id en los tags HTML, por lo que tuve que hacer un poco de magia con los CSS Selectors de Firefox, que por fortuna son varios :).

El resultado final obtenido es :

Todavía quedan algunos detalles, como sacar una imagen de 1×1 pixels al final del cuerpo que según parece usa Yahoo para geolocalizar desde donde se leen sus email.

El CSS aplicado :

@namespace url(http://www.w3.org/1999/xhtml);
@-moz-document domain(mail.google.com) {
  .ii > div > div > div > div > div + div {
    display: none !important;
  }
  .ii > div > div > div > div {
    display: none !important;
  }
  .ii > div > div > :first-child {
    width: 95% !important;
  }
  .ii > div > div > div > :first-child {
    display: block !important;
    width: 100% !important;
  }
}

Do it right! – Manejo de dependencias

En estos días he tenido varias discusiones sobre algunas prácticas muy acostumbradas en varios proyectos, que a mi parecer están muy lejos de lo útil. Es por eso que decidí escribir un par de artículos denominados «Do it right!» (hazlo bien!, si mi inglés no es tan malo como pienso :D). En esta primer entrega voy a tratar el tema de manejo de dependencias.

Escenario

Muchas veces uno se encuentra con un software que necesita y le es útil. Vamos a suponer de entrada que no tiene paquete para su distribución y/o sistema operativo favorito. En al leer el README vemos que depende de muchas cosas : alguna biblioteca de procesamiento de imágenes, algún captcha system o lo que sea.

Mirando mejor nos encontramos con una realidad muy fea : todas las dependencias están incluidas en el archivo que nos bajamos originalmente, y alguna veces se cargan por métodos poco ortodoxos.

Cualquiera que haya bajado cosas en PHP o Java seguramente se ha encontrado con esto : Clases bajadas de phpclasses.org o miles de archivos JAR en un directorio lib de la aplicación Java que se cargan en el classpath. También lo he visto en varios proyectos Rails últimamente.

La excusa que siempre escucho es «Because it makes the app more self contained«, si, si, BWTF. Pero la pregunta es : ¿es la forma correcta?. Si respondes que si, estás muy lejos de la realidad y seguramente tu sysadmin te odia mucho, pero mucho :).

El Problema

Entonces, ¿cuál es el problema con esto?. En principio parece una maravilla, nos facilita todo, descomprimimos y ya está!, el sysadmin (nosotros) agradecido, pero si el sysdamin es otra persona y se respeta los va a putear mucho, pero muuuuuucho.

Uno de los problemas con empaquetar todas las dependencias es la facilidad de solucionar problemas a futuro. El mejor ejemplo que he vivido es el típico cambio de time zone en nuestro país. PHP, por ejemplo, tiene su propia DB de timezones, y si actualizamos el tzdata de nuestro servidor, maravillosamente PHP ni se entera. Está bien que en este caso como programadores no podemos hacer mucho, es el lenguaje el que está mal, pero el ejemplo ilustra mi punto.

Un software con el que tuve que trabajar, vBulletin, va aún más allá. Tiene su propia DB de timezones por arriba de la que tiene PHP!, hardcodeada en un array!. ¿La excusa? Que la de PHP no anda bien en Windows y es mejor de esta manera.

Otro ejemplo que puedo dar es el otro día cuando migré unos sitios en el trabajo. Uno de los admines se quejó que dejó de andar porque usaba la función «dl» de PHP para cargar extensiones en tiempo de ejecución! (es decir, cualquier script PHP puede cargar un .so que extiende PHP de cualquier manera, incluso para saltearse otras medidas de seguridad), lo que no solo es una chanchada, sino que es un potencial problema de seguridad.

Tener el manejo de dependencias con la aplicación además nos prohíbe actualizar fácilmente un bug de seguridad, usabilidad o lo que sea de esa dependencia. No podemos en muchos casos hacer un upgrade de ese paquete que está embebido dentro de un todo llamado «aplicación».

En rails he visto ya muchos que acostumbran a usar «rake gems:unpack» para meter las gemas de las que dependen en el directorio vendors/gems, así no las tienen que instalar aparte. Rubygems disgusta en muchos ambientes, no voy a entrar en eso hoy :). Si uno depende  de una versión específica la forma correcta sería especificar en el environment.rb la versión, y luego que el que hace el deploy haga un «rake gems:install» para asegurar que se cumplan las dependencias. Con Capistrano es una papa hacer esta tarea automáticamente ;).

Entonces, ¿nunca más lo hago?

No me gustan los extremos y creo que estas malas prácticas que se ven hoy tiene usos muy específicos.

Supongamos que el proyecto X usa la lib Y, pero tal cual la provee upstreem no me sirve. Lo lógico es hacer un patch para upstream solucionando el problema o agregando la característica.

Mientras upstream acepta el patch y realiza un nuevo release, ahí si tiene sentido tal vez, y de forma temporal tener esa dependencia embebida.

Un ejemplo donde yo lo estoy haciendo es con el uso de la gema contacts, que depende de la gema json. En una aplicación con Rails 1.2.6 no hay ningún problema, pero en otra que usa Rails 2.1 si, porque este último integra un parser de JSON y conflictua con la gema del mismo nombre. La opción lógica sería migrar la aplicación 1.2.6 a una nueva versión de Rails, cosa que no siempre es fácil y se necesita el tiempo. Como no se pudo, es más fácil meter en uno de los proyectos la gema de manera que no moleste al resto de los proyectos en el transcurso de la actualzación.

Seguro hay algún otro caso, ahora no se me ocurre alguno que realmente lo justifique.

Se fue el último …

Así es, costó más de lo pensado, pero luego de dos semanas reescribiendo mi último trabajo práctico finalmente obtuve ese glorioso 5 que hace que en mi libreta tenga firmada absolutamente todas las materias necesarias para recibirne :).

Queda solo un pasito más por dar, que es terminar y presentar mi Tesis de Ingeniería en Informática, cosa que no va a demorar más de unos meses y que se podría decir que está al 40%, quedando el tramo más fácil.