Thinking on hiring me?

Please read

Fernando Guillén

a Freelance Web Developer

cabecera decorativa

software development as an artistic expression

Archive for the ‘programando’ Category

Lunes, Agosto 11th, 2008

Ruby, script generador de script javascript para precarga de imágenes en tu html

El truco más sencillo para precargar las imágenes de tu web y así no ver el horrible efecto de mouse-over hueco es hacer un script javascript como este:

img1 = new Image();
img1.src="imagen.jpg";

Esto invocará la imagen y el navegador, sino es muy tonto, la dejará en la caché para cuando verdaderamente la necesite.

Bueno, pues es lo que quiero hacer para una web que tiene un montón de background-image definidos en su css.

Para ello me he hecho un script en ruby que me busca todas las imágenes en todos los css y me genera un script de javascript con todo el rollito de los preload.

class Preloator
  def self.generate_script( css_directory )
    # take all .css on directory
    css_file_names = []
    Dir.foreach( css_directory ) do |file|
      if file =~ /.*\.css$/
        css_file_names << css_directory + '/' + file
      end
    end
 
    # take all the images by looking at 'url'
    image_names = []
    css_file_names.each do |file_name|
      self.grep( 'url', file_name ).each do |line|
        image_names << line.scan( /.*\((.*)\)/ ).flatten.first
      end
    end
 
    # generate the script
    script = "<script>\n"
    image_names.each_with_index do |image_name, index|
      script += "    img#{index} = new Image();\n"
      script += "    img#{index}.src = \"#{image_name}\";\n"
    end
    script += "</script>"
  end
 
  def self.grep( pattern, filename )
    matches = []
    regexp = Regexp.new( pattern )
    File.open(filename) do |file|
      file.each do |line|
        matches << "#{filename} #{file.lineno.to_s}: #{line}" if regexp.match(line)
      end
    end
    matches
  end
end
 
puts Preloator.generate_script( ARGV[0] )

Esto genera una salida como esta:

$ ruby etc/preloator.rb public/stylesheets/
<script>
img0 = new Image();
img0.src="/imgs/fondo.jpg";
img1 = new Image();
img1.src="/imgs/fondo_carpeta.png";
img2 = new Image();
img2.src="/imgs/blog_sombra_abajo.png";
img3 = new Image();
</script>;

Seguramente quieras mejorarlo un poquito: meterlo en un .js o invocarlo cuando el document.load.

El script ahorra trabajo si, como en mi caso, tienes más de 20 imágenes en el css.. y escribir el javascript a mano sería un coñazo.

Lunes, Agosto 4th, 2008

Ruby on Rails: expirar la caché desde un script ó como activar los Sweepers como Observers

No sé si es que soy yo el liante o es que me da por hacer las cosas raras.

El caso es que me he encontrado con otro dolor de cabeza haciendo algo, en principio, relativamente sencillo.

Se trata de insertar en la BD un modelo desde un script, que más adelante será un rake. Todo iba bien, no es complicado:

m = MiModelo.new( :nombre => 'el nombre' )
m.save

Pero, algo olía mal, pues los listados de este modelo tienen una vista, y esta vista está cacheada, y si insertaba el modelo desde el script la vista no cambiaba, osea: no estaba expirando la caché.

El problema estaba en que todos los engranajes de expiración de cachés estaban en los sweepers y éstos sólo se activan si el código pasa por el application.rb, padre de todos los controladores, concretamente con el método: cache_sweeper, y no encontraba manera de activar los sweeper sin pasar por un controlador.

Estuve dando unas buenas vueltas y preguntando a colegas, resulta que la caché en Rails está altamente integrada con el controlador. Y esto tiene su sentido pues no hay caché sin renderizado y no hay renderizado sin llamada a un controlador. Pero cuando hablamos de expirar cachés no veo tan claro que deba seguir estando integrado con el controlador, pues, como vemos en mi ejemplo del script, pueden existir muchos escenarios donde sea necesaria una expiración de caché sin necesidad de pasar por un controlador.

Googleando por ahí encontré un post que según creo entender también se queja un poco del exceso de integración entre la caché y los controladores.

La primero aproximación que parece ocurrírsenos es la de usar un observer en vez de un sweeper pero el sweeper tiene implícitamente un montón de métodos muy útiles para realizar la tarea de expiración de caché, como son los expire_* y los renderizadores de urls al estilo mi_modelo_url.

Además si empezaba a migrar todos los sweepers a observers empezaba a salirme del camino de como le gusta a Rails que se hagan las cosas.

Pero es que resulta que al parecer a Rails no le gusta que se expiren cachés desde un script y el workarround para conseguirlo no es del todo limpio pero se ha conseguido activar los sweepers desde un script para que se disparen al insertar un nuevo modelo en la BD.

El workarround es obra de Daniel Rodriguez Troitiño y aquí podéis revivir la lucha hasta conseguirlo.

Está funcionando para 2.0.1 y no sé si funciona en otras versiones.

require 'action_controller/test_process'
 
ActiveRecord::Base.observers = [MiSweeper]
ActiveRecord::Base.instantiate_observers
 
MiSweeper.instance.controller = ActionController::Base.new
 
tr = ActionController::TestRequest.new
MiSweeper.instance.controller.request = tr
MiSweeper.instance.controller.instance_eval( '@url = ActionController::UrlRewriter.new(tr, {})' )
 
m = MiModelo.new( :nombre => 'el nombre' )
m.save

Vemos que se activa el sweeper como un observer y luego se inicializa con todo lo necesario para que funcione.

Muchas gracias a Daniel que se lo ha tomado como reto personal ;).

Jueves, Julio 31st, 2008

Ruby: cliente Pop SSL ó como leer tu cuenta Gmail desde Ruby.

Cómo ya dicen en muchas partes, pero me repito aquí para parecer muy listo y por marcarlo como nota mental, para acceder a tu cuenta Pop en Gmail desde Ruby hay que hacer una ñapa porque la versión actual de Ruby (1.8.6) no admite conexiones Pop bajo SSL.

Si si.. la 1.9 ya tiene el soporte, y dicen por ahí que descargándote el pop.rb de esta versión desde el repositorio y haciéndole un require ya funciona.. pero no, por lo menos a mí no porque me salta alguna dependencia con OpenSSl:

NoMethodError: undefined method `set_params' for #<openssl::ssl::sslcontext:0x210f4d0>;
</openssl::ssl::sslcontext:0x210f4d0>

Y no quería seguir tirando de el hilo.

El workarround que más me ha gustado ha sido el de montar un tunel ssh y hacer la petición desde el Net::POP3 al túnel y que el túnel se la haga llegar al pop de Gmail bajo SSL.

No voy a entrar en detalle porque ya lo hacen en muchos sitios.

Actualizado: acabo de ver un sitio dónde explican como usar la implementación pop.rb de la 1.9 sin el problema que me da a mí.

Los pasos resumidos que este post explica son:

1) Descargarte una implementación de la librería POP3: la versión 13778.

2) Ponerla en tu carpeta lib con este nombre por ejemplo: pop_ssl.rb con esto sobreescribiremos la implementación de esta librería que trae ruby por defecto con una versión mayor.

3) Descargarte este fichero y ponerlo también en lib: pop_gmail_client.rb

class PopGmailClient
  def self.read_account( account_user, account_pass )
    mails = []
    Net::POP3.enable_ssl(OpenSSL::SSL::VERIFY_NONE)
    Net::POP3.start( 'pop.gmail.com', 995, account_user, account_pass ) do |pop|
      pop.each_mail do |m|
        mails << m.pop
      end
    end
    mails
  end
end

4) Requerirlos desde el environment.rb al final del todo con:

require 'pop_ssl'
require 'pop_gmail_client'

Y ya podemos usarlo como queramos:

$ script/console
Loading development environment (Rails 2.0.2)
>> PopGmailClient.read_account( "fguillen.testing@gmail.com", "xxx" )

O desde ruby directamente:

$ irb
>> require 'lib/pop_ssl.rb'
=> true
>> require 'lib/pop_client_gmail.rb'
=> true
>> PopGmailClient.read_account( "fguillen.testing@gmail.com", "xxx" )
Miércoles, Julio 30th, 2008

Ruby on Rails: before_filter y caches_action el orden sí importa.

Estuve un día volviéndome loco con uno de estos tantos poltergeist que todo lenguaje o framework oculta, en este caso RoR.

Aprovecho para señalar mi opinión de que es imposible conocer un lenguaje/framework en unos pocos meses, por muy listo que seas y por muchos libros que seas capaz de leer en ese periodo. El verdadero conocimiento se esconde después de enfrentarte a un gran número de problemas/errores/bugs/y poltergeist que el lenguaje/framework en cuestión esconde, conocerle como si se tratara de conocer el carácter de una persona con la que convives hasta que entiendes como tratarle y entenderle. Es a lo que aveces nos referimos como la intuición.

Siguiendo con el poltergeist que nos ocupa: se trataba de que al activar la caché de acción en determinados controllers no se me estaban ejecutando los before_filters (aunque curiosamente si se ejecutaban los before_filters del padre ApplicationController  no de mis propios Controllers).

Esto no era muy normal y estaba claro de que algo estaba haciendo mal, pues precisamente una de las peculiaridades de la caché de acción es que siempre ejecuta los filtros, a diferencia de la caché de página que no ejectua nada.

Bueno, después de seguir el sabio consejo: si te estás espesando déjalo para otro día, hoy ya he encontrado lo que ocurría y no es ni más ni menos que el orden en el que se declaran los before_filter y los caches_action.

Yo lo tenía así:

class MiController < ApplicationController
  caches_action :show
  before_filter :ejecutar_antes, :only => [ :show ]
end

Y se solucionó cambiándolo a:

class MiController < ApplicationController
  before_filter :ejecutar_antes, :only => [ :show ]
  caches_action :show
end

Es muy fácil de probar:

class MiController < ApplicationController
  before_filter :X1
  caches_action :show
  before_filter :X2
 
  private
    def X1
      p "XXXXXXXXXXXX1"
    end
 
    def X2
      p "XXXXXXXXXXXX2"
    end
end

Si ejecutas :show una vez que ya está cacheada verás como sólo se ejecuta el primer filtro ‘X1′ y no el ‘X2′.

Si conoces algún sitio dónde se indique el órden en el que hay que hacer estas declaración pega el link en un comentario.

Miércoles, Julio 23rd, 2008

Texto vertical con javascript

Ni CSS3 ni SVG ni leches.

<script>document.write( "el texto".replace( /(.)/g, "$1<br />" ) ); </script>

Ya sé que no queda vertical y que es un seudo horizo-vertical.. pero por lo menos funciona. ;)

Sábado, Julio 19th, 2008

2 horas programando para 4 líneas

Es lo que tiene ruby.

Llevo un par de horas intentando sacar un Float en formato ‘d.ddd.ddd,dd’. Hay muchas cosas en internet para conseguirlo, pero no todas funcionaban bien, y otras funcionaban demasiado bien, con un montón de opciones.

El caso es que hay un helper del ActionView que tiene la función number_to_currency pero es un cabroncete de helper y no podía acceder desde el modelo. También teníamos la gema Currency pero era un pedazo monstruo para la tontada que yo quería.

Al final la gema Scruffy me ha dado la pista y esto es lo que tengo:

class Float
  def en_euros
    parts = sprintf("%01.#{2}f", self).split('.')
    parts[0].to_s.gsub(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1.") + "," + parts[1].to_s
  end
end

Es un parchecito del Float para poder hacer esto:

>> 1234.566.en_euros
=> "1.234,57"
Martes, Julio 15th, 2008

“Lo sentimos: volvemos en cinco minutos” ó “En todos sitios se cuecen habas”

Si estás en el mundo este del desarrollo web ya te habrás encontrado alguna vez que tu aplicación en producción tiene algún problemilla y que se traduce en que escupe algún error o que incluso se ha venido abajo.

Si la aplicación es para un cliente y éste se ha percatado del problemilla se habrá puesto en contacto contigo para explicarte la extrema importancia de que esto no ocurra nunca más, que el mundo entero depende de ello y que no entiende cómo algo así puede ocurrir.

Bueno, la verdad es que ocurre, una aplicación web es un ente extremadamente frágil y complejo, con una cantidad de casuística enorme. Por muy bueno que seas, por mucho cuidado que pongas siempre hay una alineación de variables que no habías contemplado.

Tranquilicémonos, no… señores, no se acaba el mundo, se arregla se sube a producción y ya está. Y si se tarda un poco no creo que los satélites vayan a caerse sobre nuestras cabezas ¿no?. ¿Estamos hablando de una aplicación web o del control de misiles de la OTAN?

Expongo aquí una lista de grandes y pequeños a los que me he encontrado caídos alguna vez. Si tienes algún pantallazo de petes de otras aplicaciones me pasas el link plis.

Google Docs con problemillas

Google Docs Error inexperado

Gmail tiene sus momentos

Gmail Error

La página de Correos muestra las enaguas en ASP

Error en página de correos

Los ingenieros de Gmail trabajando

Error Google 2

Google Analytics en mantenimiento

Google Analytics Mantenimiento

Google Reader se levanta con dolor de cabeza

google reader error

Los chicos de Microsiervos tienen problemillas

microsiervos off line

La página de 20minutos también requiere su mantenimiento

20 minutos de mantenimiento

Gente de gmail.es por lo menos ponerlo en castellano que he marcado un .es…

Gmail.es under construction

Nooo, levanta Stage6¡¡, quiere ver el capítulo de House ahora

stage6

Es buscador de paquetes de gentoo estuvo también indispuesto

Esta vez explican cual es la causa: bloquear la aplicación mientras arreglan una posible falla de seguridad

gentoo maintenance

¿Os suena estos?

twitter upgrading

twitter error

NameCheap también tiene sus visitas al médico

namecheap

WebCache necesita unos días para recuperarse (aún siguen)

webcache off

WaybackMachine tiene lo que se dice ‘dificultades técnicas’

WayBack Off

Google, ¿tú también hijo mío?

Google

Google Analytics descubre que ha perdido los datos de una semana

Google Analytics error

FeedBurner nos muestra su corazoncito de Tomcat

FeedBurner error

Loogic: algo pasa con la mysql

loogic caido

El servidor de yahoo mail es ‘normalmente fiable’

Yahoo mail error

A los amigos de agilewebdevelopment se les ha ahogado en ngix

agilewebdevelopment error

Tropezones con problemas temporales en Yahoo Mail

Yahoo mail error

La Apple Store tiene unos errores bastante poco estilosos

apple store

La aplicación de reportes de bugs de apple tiene un bug

error en la página de bugs

Un error en paypal muy explicativo

paypal error explicativo

Yahoo Mail estaba el día 7 de mantenimiento pero hoy día 14 todavía no ha acabado

Yahoo mail error 4

blip.tv me muestra este error justo después de registrarme, fijaros en el email de contacto :)

blip.tv error

Viernes, Junio 27th, 2008

Ruby on Rails, el plugin cache-test y la activación de la caché en los tests

Este es mi primer apunte seudo-técnico sobre RoR. No es muy profundo, en realidad lo dejo caer aquí como nota mental.

Resulta que cuando instalas el interesantísimo plugin para testear cachés y sweepers: cache-test, éste tiene en su configuración la activación de las cachés en modo test:

ActionController::Base.perform_caching = true

Tanto en el fragment_cache_test.rb como en el page_cache_test.rb.

Hasta ahora esto no me había causado ningún conflicto pues sólo hacía una llamada a una página get/post cacheada en cada test y con la misma llamada comprobaba todo.

Pero con Shoulda se hacen varias llamadas a la misma página en cada llamada se comprueba una cosa y si la página está cacheada hay varias cosas que pueden fallar como éstas:

context "on GET to :show" do
  setup do
    get( :show, :id => '1' )
  end
  should_assign_to :variable1
  should_assign_to :variable2
  should_assign_to :variable3
  should_render_template :show
end

Aquí se hace una llamada get para cada should_ , el primero funcionará pero los posteriores al estar activada la caché fallarán porque la variable o la vista buscada tendrá valor ‘nil‘.

Este no es un problema de Shoulda, simplemente no me había aparecido hasta ahora. Con los tests normales surgirá igual si tienes la caché activada y haces 2 llamadas a la misma página cacheada y esperas encontrar una variable asignada, la segunda en ejecutarse fallará.

Workarround

Lo único que he encontrado por ahora es poner esto en el setup de los tests:

ActionController::Base.fragment_cache_store.reset

Para mí me funciona, para mis tests y para la configuración de mis cachés, puede que a ti no te funcione.

Y lo que si puede ser es que tengas una solución mejor, plis coméntala.

Miércoles, Mayo 7th, 2008

‘Software como poesía’ en el DorkBot del Viernes en Madrid.

Que la creación de software es un tipo de expresión artística es una de las visiones que tengo de esta mi profesión. Profundizando un poco: las líneas de código son literatura que cuentan una historia con sus personajes, sus acciones, su nudo, su desenlace. Puede incluso acercarse a la poesía por su ritmo, su rima, su cadencia…

Interesante charla pues la que nos presenta Santiago Gala en el DorkBot de este Viernes:

“Software es poesía”: Un poco de teoría y algunos ejemplos sobre cómo el software, como cualquier otro sistema de signos, es utilizable para el arte. Expresión, interpretación y transgresión en el software.

Para ver la lista de charlas completa, lugar, hora y demás.

Vía lista de correo de DorkBot Madrid. (La página web más desactualizada y difícil de enteder de la Internet) .. es broma :P

Domingo, Mayo 4th, 2008

Entre la aptitud y la actitud.

El desarrollo de software, sobre todo cuando el objetivo es ser usado por humanos, requiere de un cuidado y un cariño especial.

La aptitud en esta profesión es importante, es bueno tener cualidades técnicas y conocimientos y sobretodo experiencia, pero todo esto no sirve de nada si se carece del empuje, del gusto por lo que haces, de vocación, y de algo muy importante de lo que ya hablé citando a Erich Fromm: la intuición.

La diferencia de tener intuición o no tenerla es que cuando no la tienes sabes porque estás haciendo las cosas y sabes porque las estás haciendo así,  normalmente te da igual el resultado siempre y cuando hayas seguido la metodología, al fin y al cabo así es como se hacen las cosas ‘bien’, es así como lo dice el libro.

Cuando te apoyas en la intuición es difícil defender y justificar tus decisiones que muchas veces contradicen la metodología académica, el resultado es algo orgánico, fluido, más real, más verdadero.

Es la diferencia entre pintar un cuadro rellenando las zonas numeradas con los colores indicados o enfrentarte al lienzo en blanco mirando con la imaginación y dando libertad a todos los trazos.

Me acuerdo ahora de una oferta de trabajo que solicitaba la gente de nVivo para un puesto de desarrollador web, en la cuál se especificaban unos mínimos requisitos académicos pero que en el detalle del perfil requerido se daba más importancia a:

  • Pasión por la música.
  • Acudir por lo menos a 19 conciertos al año.
  • Mantener un blog actualizado.
  • Tener un perfil en last.fm, mystrands .com o ilike .com con más de 10 artistas, con el 70 % fuera de los circuitos.

(Para el que no lo sepa nVivo es una red social de conciertos y adictos a la música en vivo)No es precisamente esto a lo que me refiero, pero tiene cierta aproximación, la gente de nVivo lo sabe bien. Es muy importante que te guste lo que estás haciendo, que conozcas el mundo al que va dirigido es más: que seas el mundo al que va dirigido. De este modo será tu intuición quien te ayude, quien te guíe.

No creo que puedas ser buen panadero sino te gusta el pan, buen mecánico de motos si no eres un apasionado de las 2 ruedas, … En efecto podrás ser todo eso y mucho más pero no serás bueno.

.. o por lo menos, es mi opinión.

a Freelance Web Developer is proudly powered by WordPress
Entries (RSS) and Comments (RSS).

Creative Commons License
Fernando Guillen's blog by Fernando Guillen is licensed under a Creative Commons Attribution-NoDerivs 3.0 Unported License.