jueves, 10 de diciembre de 2009

No hablo de la Conferencial Rails 09 porque no estuve

Por motivos personales, este año me he perdido más de la mitad de los contenidos de la Conferencia Rails. Como casi todos los años el balance cosas positivas vs cosas negativas es bastante favorable.

De lo que vi, lo que más me gustó fueron las charlas pseudofilosóficas de Javi Ramírez, Sergio Gil y Aitor Garcia Rey porque, a pesar de que no estoy del todo de acuerdo con ellos, sí que creo que reflexionamos poco acerca de lo que hacemos día a día, acerca de todos los errores que hemos cometido en nuestra actividad y acerca de cómo podemos enforcar nuestra actividad de modo que nos haga sentir bien con nosotros mismos. Pero bastante contaron ellos como para ponerme aquí a disertar sobre el bien y el mal.

Lo peor, la charla de apertura y la de cierre del viernes. No se puede recibir a la masa con una charla que verse sobre soy guay y estoy escribiendo un libro guay después de que esa masa haya salido la noche anterior a tomar el fresco. De hecho, no se pude recibir a la masa con una charla así nunca, por el amor de dios. De la misma forma que no puede cerrar la conferencia un señor que twittea que se está durmiendo en la conferencia y que sale a dar la charla más soporífera que recuerdo en años. ¿He dicho charla? Me he confundido; he querido decir lectura, porque leyó más de la mitad de lo que dijo. Y así pasó, que más de uno y más de dos se echaron en brazos de Morfeo.

Eso sí, como siempre, la organización se merece todos mis elogios. Y lo del tío del jamón, un puntazo.

¡Salud y rocanrol!

Brothers the battle is raging, choose your side.
Sing with us the Battle Hymns, Into Glory Ride.
Hail to England. The Sign of the Hammer's our guide.
Forever we're Fighting the World, side by side.

On a crusade the world we bring
Four Kings of Metal, Four Metal Kings.
Death to the false ones, dance on a string
'Til the blood on your sword is the blood of a king.
'Til the blood on your hand is the blood of a king.

martes, 1 de diciembre de 2009

Templates en Windows

Hello!

Acabo de crear un proyecto basado en un template de rails, como siempre, en entorno windows. La sitaxis es la conocida

rails nombre_de_proyecto --template=ruta_del_template

La ruta puede ser un path físico en la máquina o una url. He tenido que hacer un par de apaños muy fáciles sobre el template original para que todo funcione debidos, en su mayoría, a que ruby no es capaz de ejecutar archivos .bat si no le damos explícitamente la extensión:
  • Las llamadas a run 'gem ...' las he cambiado por run 'gem.bat ...'.
  • Las llamadas a rake las he cambiado por run 'rake.bat ...'.
  • He eliminado cualquier referencia a sudo en todas las llamadas a sistema.

El resto ha funcionado a la perfección. Ha costado más identificar el mensaje de error que otra cosa. Por cierto es éste:

c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.3.2/lib/active_support/core_ext/kernel/agnostics.rb:7:in ': Exec format error - rake db:create:all'

Me volverá a ocurrir esto mismo otra vez y me olvidaré. Lo saben aquí y en la República Democrática del Congo. ¡Salud y rocanrol!

Way down in Louisiana amongst the tall grown sugar canes
lived a simple man and a domineerin' hen and a rose of a different name.
The first time I fell lightly I was standing in the drizzlin' rain
with a trembling hand and a bottle of gin and a rose of a different name.
The devil made me do it the first time the second time I done it on my own.
Lord put a handle on a simple handed man and help me leave that black rose alone.

When the devil made that woman Lord she threw the pattern away.
She was built for speed with the tools you need to make a new fool every day.
Way down deep and dirty on the darker side of shame,
you caught a cane cuttin' man with a bottle of gin with a rose of a different name
The devil made me do it the first time the second time I done it on my own.
Lord put a handle on a simple handed man and help me leave that black rose alone.

sábado, 21 de noviembre de 2009

Conferencia Rails 2009

El próximo miércoles 25 comienza la Conferencia Rails 2009. Este año me han colocado las cosas como a mí me gustan, casi sin colisiones entre temas interesantes. Además hay mucha presencia internacional, tanto en ponentes como en asistentes: Obie Fernández, Yehuda Katz, David Black, Scott Chacon... Aquí podéis ver la nota de prensa oficial.

En CameraWC he subido un vídeo para saludar tanto a los asistentes como a los no asistentes. Y en unvlog hay muchos más.

Bueno, tengo fundadas esperanzas en que este año todo va a ser mucho mejor que el pasado. La semana que viene lo comentamos. Salud y rocanrol!

I was getting kind of tired of her endless chatter.
Nothing I could say ever seemed to matter.
So I took a little drive just to clear my head,
and I saw a flashing neon, up ahead.
It looked like a place to find some satisfaction
with a little less talk and a lot more action.

I paid the man at the door and pushed my way to the bar.
Shouted for a drink over a screaming guitar.
A drunk on a stool tried to mess with my head
but I didn't even listen to a word he said.
I knew somewhere amid all this distraction.
Was a little less talk and a lot more action

jueves, 12 de noviembre de 2009

Generando un avatar

Inventemos una palabra en castellano para traducir avatar. Podemos castellanizarla directamente, avatario o ávatar, porque parece que no podemos traducirla y, algo como, imagencilla, imagen de usuario o imagen en twitter, no me convence del todo.

Y dicha la tontería, vamos a lío. Supongamos que tenemos una imagen cuya ruta es C:/Users/danimata/full_body.jpg. Vamos a recortar un trozo de la imagen cuyo vértice superior izquierdo es (x1, y1) e inferior derecho (x2, y2). Además, para que el recorte nos quede bien en nuestra página de perfil de usuario, lo vamos a escalar para que tenga altura h y anchura w. Finalmente, lo guardaremos como C:/Users/danimata/avatar.jpg

Si utilizamos RMagick haremos lo siguiente:

require 'RMagick'

img = Magick::Image.read("C:/Users/danimata/full_body.jpg").first
tmp_avatar = img.crop(x1, y1, (x2 - x1 + 1), (y2 - y1 + 1))
avatar = tmp_avatar.resize(w, h)
temp = Tempfile.new("C:/Users/danimata/avatar.jpg") avatar.write "png:" + temp.path

Sin embargo, si utilizamos image_science haremos lo siguiente:

require 'image_science'

temp = Tempfile.new("C:/Users/danimata/avatar.jpg")
ImageScience.with_image "C:/Users/danimata/full_body.jpg" do |image|
  image.with_crop x1, y1, x2, y2 do |cropped|
    cropped.resize w, h do |avatar|
      avatar.save temp.path
    end
  end
end

Y listo. Como siempre, salud y rocanrol!

La noche se está cayendo
y con ella cae el tiempo.
El día no sirvió de nada,
tarde de nubes sin agua.
Hoy el cielo es de cemento,
parece que dios está muerto.
Golpean la puerta de casa,
mensajeros de desgracia...
¡malas noticias!

miércoles, 28 de octubre de 2009

Presentación sobre OpenID y OAuth

He creado una presentación para contar a unos amigos lo más básico sobre OpenID y OAuth.



Salud y rocanrol

¿Quién tiró la piedra? ¿Quién escondió la mano?
¡Quién le puso el pie al gordo del "Gran Hermano"?
Quien sabe lo que sabe, sabe que no sabe nada.
El que nada no se ahoga o le dan por la almorrana
¡O le dan por la almorrana!

Y si tiene almorranas es que sufre en silencio.
El silencio pa' los muertos, yo me quedo con un tercio.
Tres tercios son un litro o cinco botellines.
Con cinco botellines hay que echarse un cigarrito.
¡Hay que echarse un cigarrito!

domingo, 25 de octubre de 2009

La absurdez hecha duda

Hoy me ha surgido la duda de cómo hacer una validación de unicidad sobre dos atributos de un modelo. Nunca había tenido que hacer algo similar en Rails.

La mejor opción que he encontrado ha sido

validates_uniqueness_of :family_id, :scope => :user_id

Esto validará que para cada valor de user_id el valor de family_id es único. Seguro que hay una solución mejor y más estándar, pero yo no me la sé.

Weno, pues nada. Ha sido breve pero intenso. Salud y rocanrol.

We all came out to Montereax
On the Lake Geneva shoreline
To make records with a mobile
We didn't have much time
Frank Zappa and the Mothers
Were at the best place around
But some stupid with a flare gun
Burned the place to the ground
Smoke on the water, fire in the sky
Smoke on the water...


lunes, 5 de octubre de 2009

Git en Windows Vista

Por fin he puesto a funcionar un proyecto que tira de un repositorio git. Para ello he tenido que hacer tres cosas:
  • instalar git para windows desde aquí
  • confgurar la variable de entorno GIT_SSH para que apunte al ejecutable ssh que viene con el instalador de git, típicamente en C:\Program Files\Git\bin\ssh.exe
  • clonar el repositorio y empezar a trabajar
Ya sólo me queda familiarizarme con la manera de trabajar con git.

Un par de links interesantes por si encontráis otros problemas: un manual http://kylecordes.com/2008/04/30/git-windows-go/ y una lista de posibles errores con su solución http://github.com/guides/addressing-authentication-problems-with-ssh

Salud y rocanrol!

She was a fast machine
She kept her motor clean
She was the best damn woman that I'd ever seen
She had the sightless eyes
Telling me no lies
Knocking me out with those American thighs
Taking more than her share
Had me fighting for air
She told me to come but I was already there
Cause the walls started shaking
The earth was quaking
My mind was aching
And we were making it and you
Shook me all night long
Yeah you
Shook me all night long


martes, 29 de septiembre de 2009

FasterCSV y Rails 2.3

Pues parece FasterCSV y Rails 2.3 no terminan de llevarse bien. De hecho, en las aplicaciones rails que he migrado a la versión 2.3.2, cualquier exportación de datos a formato CSV ha dejado de funcionar. Lo extraño es que no falla nada salvo que los archivos resultantes están vacíos.

Menos mal que San Google siempre está ahí, cuando se le necesita. Buscando buscando llego aquí donde explican que en Rails 2.3 a ActionController::Response le han quitado el método << con lo que las concatenaciones típicas en la generación de archivos CSV no funcionan. En el link se ofrece una solucioncilla on the fly que funciona estupendamente para código viejuno.

En fin, as usual, salud y rocanrol

Piensas otra vez que ahora es tu momento,
aunque al parecer todo vuelve a cambiar.
Es difícil ser otra vez tú mismo,
y no ver a tiempo que estás acabado.
¿Quién te convenció de cantar así?
¿Quién te prometió la inmortalidad?
Tratan de volver los desertores del rock.
Tratan de volver los desertores del rock.
¡Pero es tarde ya!.

miércoles, 9 de septiembre de 2009

Nota mental

Hay cosas que por más que las leas, las veas y las intentes retener, son imposibles de memorizar. Hay otras, sin embargo, que se quedan ahí contigo para el resto de tu vida, y que no sirven para nada. Como la típica cancioncilla que oyes a alguien y no se te va de la cabeza en todo el día. Probemos con 'dragones y mazmorras, un mundo infernal, se esconde entre las sombras, la fuerza del mal'.

En fin, no sé cuantas veces he buscado cómo se llama la variable local que contiene el número de iteración que pinta en cada momento. Por lógica, se llama contador o counter, pero en estos casos la lógica no aparece por ningún lado. Y para que cada partial tenga la suya, por delante se pone el nombre del archivo. Es decir, si ejecutamos

<%= render :partial => 'line', :collection => @lines %>

cada ejecución del partial _line.html.rb contará con la variable local line_counter cuyo valor irá creciendo en cada ejecución desde 0 hasta el número de items contenidos en @lines menos 1.

Para más información, pregunten por el señor api.

Me juego una caña a que se me olvida que he escrito este post. Salud y rocanrol

Sólo quiero ser más rápido que ellos
y echar todo a perder un día tras otro
y un buen rato después saber llegar a casa
antes de que el sol, me diga que es de día


viernes, 17 de julio de 2009

Combos dependientes re-visited

Hace tiempo ya conté cómo hacer combos dependientes con observe_field pero debe ser que me hago viejo y que me gusta hacer las cosas cada vez más pedrestres. En fin, que tirando a pelo de prototype, un poco de javascript y adaptando un controlador, conseguimos lo mismo de forma muy sencilla.

Supongamos dos modelos dependientes

class Country < ActiveRecord::Base
 has_many :provinces
end

class Province < ActiveRecord::Base
 belongs_to :country
end

enlazados en nuestro archivo de rutas como

map.resources :countries do |country|
 country.resources :provinces
end

En a vista enlazamos países y provincias en dos combos...

<%= select :person, :country_id, countries_for_select.map{|c| [c.name, c.id]}, {}, {:onchange => "change_provinces('person_province_id', this.value);", :class => 'w150'} %>
<%= select :person, :province_id, provinces_for_select.map{|c| [c.name, c.id]}, {}, {:class => 'w150'} %>

donde countries_for_select y provinces_for_select nos dan los registro a pintar inicialmente en cada uno de ellos.

Sólo falta la función javascript change_provinces que haga la llamada Ajax y el repintado del combo cuyo ide recibe como primer parámetro...

function change_provinces(combo_id, country_id){
 var url = '/countries/' + country_id + '/provinces';
 var combo = $(combo_id);
 for (var i = combo.options.length-1; i >= 0; i--){
  combo.options[i] = null;
 }
 new Ajax.Request(url, {
  method: 'get',
  onSuccess: function(transport) {
   prov_array = eval(transport.responseText);
   for (var k = 0; k < prov_array.length; k++){
    combo.options[k] = new Option(prov_array[k][1], prov_array[k][0]);
   }
   combo.options[0].selected = true;
  },
  onFailure:function(transport) {
  }
 });
}

... y finalmente adaptar provinces_controller

def index
 @provinces = ...
 if request.xhr?
  render :text => @provinces.map{|province| [province.id, province.name]}.inspect
  return
 end
end

Y a correr. Ale, salud y rocanrol!

We shall go on to the end, we shall fight in France,
we shall fight on the seas and oceans,
we shall fight with growing confidence and growing strength in the air,
we shall defend our Island, whatever the cost may be,
we shall fight on the beaches,
we shall fight on the landing grounds,
we shall fight in the fields and in the streets,
we shall fight in the hills, we shall never surrender!"

martes, 16 de junio de 2009

Quiero logarme usando open ID

Lo primero es instalar la gema ruby-openid y el plugin open_id_authentication. Intenté usar directamente el plugin restful_open_id_authentication pero ya tenía montada una autenticación de tó la vida y preferí añadir únicamente la parte de open ID.

Ahora sólo queda seguir las instrucciones que encontramos en los links, pero con un par de matices:

  • Generamos las tablas que necesita el plugin

    > ruby script/generate open_id_authentication_tables MigrationName

    Esto generará una migration con las tablas open_id_authentication_associations y open_id_authentication_nonces, asi que...

    > rake db:migrate

    Si el modelo User aún no tiene un campo para almacenar el openid, tenemos que crearlo, claro está.

  • En el archivo de rutas nos aseguramos de que exista una ruta root y permitimos el acceso al método create del controlador sessions mediante GET

    map.open_id_complete 'session', :controller => "sessions", :action => "create", :requirements => {:method => :get }

  • En la vista correspondiente al login de la aplicación, añadimos un campo que contenga el openid del usuario.

    <%= text_field_tag 'identity_url' %>

  • Adaptamos sessions_controller para que ejecute el login contra openID cuando sea necesario. Basta con seguir las instrucciones que nos proporcionan los creadores del plugin, juntarlo con el código que tengamos para autenticar (en este caso, restful_authentication) y retocar un par de cosas.

    En el controller sessions_controller.rb

    def create
     if !params[:identity_url].blank? || request.get?
      open_id_authentication(params[:identity_url])
     else
      password_authentication
     end
    end

    protected
     def password_authentication
      self.current_user = User.authenticate(params[:login], params[:password])
      if logged_in?
       if params[:remember_me] == "1"
        current_user.remember_me unless current_user.remember_token?
        cookies[:auth_token] = { :value => self.current_user.remember_token , :expires => self.current_user.remember_token_expires_at }
       end
       successful_login "Logged in successfully"
      else
       failed_login "User and password do not match"
      end
     end

     def open_id_authentication(identity_url)
      authenticate_with_open_id(identity_url) do |status, identity_url|
       unless status.successful?
        failed_login status.message
       else
        if @current_user = User.find_by_identity_url(identity_url)
         successful_login
        else
         failed_login "Sorry, no user by that identity URL exists"
        end
       end
      end
     end

    y en el plugin, en open_id_authentication.rb

    def successful?
     @code == :successful
    end

Y a correr.

Salud y rocanrol. (hoy no hay ánimo para canciones, sorry)

domingo, 7 de junio de 2009

Mensajes de error enviando mails

He encontrado este artículo que explica bastante bien los mensjaes de error más comunes que recibimos al enviar un email de forma errónea.

Divide los mensajes en tres grupos: provocados por errores en el dominio, por errores en el mailbox o por filtros antispam. Para más detalles lo mejor es leer el artículo.

Ha sido corto, pero intenso. Salud y rocanrol!

I've got friends in low places
Where the whiskey drowns
And the beer chases my blues away
And I'll be okay
I'm not big on social graces
Think I'll slip on down to the oasis
Oh, I've got friends in low places

martes, 12 de mayo de 2009

Un nuevo site

La semana pasada puse en producción el site del restaurante de unos amigos: La Lumbre del Cacique. Es mi segunda experiencia con el diseño y cualquier feedback es bienvenido.

Ha sido breve, pero intenso. Salud y rocanrol.

Sea tan amable y diga qué le debo.
Yo suelo pagar lo que como y lo que bebo.
He comido un pincho de tortilla,
dos bocadillos de morcilla.
He acabado un queso de tetilla
y me niego a fregar la vajilla.


lunes, 11 de mayo de 2009

Estar actualizado

El viernes pasado, camino de la Euruko2009, iba en el AVE intentando ver porqué no me funcionaban unos modelos que unas horas antes sí lo hacían. Era obvio que habían dejado de funcionar al añadirles el comportamiento acts_as_versioned que en otros proyectos me había funcionado la mar de bien.

Ahí estaba mi error. Mi profesor de carpintería en Estados Unidos me lo advirtió hace 22 años:
there's a big differece between assure and ass U're
Las versiones antiguas de acts_as_versioned mantenían los atributos que cambian de un objeto en un array llamado changed_attibutes, el mismo nombre que tiene un array parecido que se utiliza en Rails 2.3 para ver cuando un objeto que hereda de ActiveRecord está dirty.

Salí al paso cambiando el nombre al array en el plugin y hoy he actualizado el código.

Nota mental: stay updated regularly.

Salud y rocanrol

Sabes que si me dejas, muy triste me quedaré.
Tú sabes que si me abandonas, tal vez me pueda perder.
Cuando con cualquier otro chico, tu te burlas de mí
me hallaras en casa sentado
en el suelo hablando con la pared
Por eso no es extraño que tu estés loca por mí.
No es extraño que tu estés loca por mí.


lunes, 20 de abril de 2009

Cuatro URLs donde enviar sitemaps

A estas URLs se puede enviar el sitemap de cualquier site para que los buscadores te incluyan en su índice:

  • ASK:
  • http://submissions.ask.com/ping?sitemap=http://www.danimata.com/sitemap.xml
  • YAHOO:
  • http://search.yahooapis.com/SiteExplorerService/V1/ping?sitemap=http://www.danimata.com/sitemap.xml
  • MSN:
  • http://api.moreover.com/ping?u=http://www.danimata.com/sitemap.xml
  • GOOGLE
  • http://www.google.com/webmasters/sitemaps/ping?sitemap=http://www.danimata.com/sitemap.xml

Para ver el formato de un archivo sitemap, la url es la habitual: http://www.sitemaps.org/.

Ha sido corto, pero intenso. Salud y rocanrol!!!

Ni se paga con dinero ni se vende libertad,
ganas me dan de hartarme de reír.
Que animal! No me extraña que te sientas infeliz.
Ser el rey del hormiguero no es motivo de envidiar,
como si fuera el guarda del redil.
Ven p'acá, que parece que te has vuelto a confundir.

sábado, 11 de abril de 2009

Una razón más para cambiar

Llevo una temporada leyendo The Railsway de Obie Fernández y estoy interiorizando muchas cosas que antes me costaba bastante aceptar incluso entender. Creo que es por el enfoque directo que le da al libro, el punto de vista práctico del que parte y el lenguaje humano que utiliza. También porque es mucho más fácil entender cosas que ya has puesto en práctica y con las que has luchado a vida o muerte y contrareloj.

Ha coincidido mi comprensión definitiva de las rutas y de la aplicación de los principios REST con la formación de dos personas en Rails. Una de ellas lynuxera, phpera, joven y de mente abierta. La otra, windowsera, javera, joomlera, menos joven y con bastantes manías y estereotipos arrastrados de su larga experiencia. Mezclado todo ello con la presión de un proyecto importante, la situación se me estaba yendo de las manos y no estaba consiguiendo hacer las cosas bien.

Decidí sacar mi chuleta de los 4 verbos, las 7 acciones, la facilidad de extender éstas y lo fácil que resulta hacer todo siempre que se puede de la misma manera... et voilà. El caos se transformó en claridad, la deriva en control y las dudas en seguridad.

En dos patadas creé un proyecto con autenticación y administración sobre el que trabajar y añadir funcionalidad fácilmente. La ordenación de datos, la paginación, los métodos del controlador salían sólos y, trabajando juntos sobre el código, la velocidad de aprendizaje se incrementó considerablemente. Y lo mejor de todo, el arranque de un proyecto real con dos personas neoraileras fue bastante más controlada de lo habitual.

Vamos a ver qué ocurre a la hora de integrar con diseño. Algo nos inventaremos.

Como siempre, salud y mucho rocanrol!!!

Esperando en el metro
a que salga el Sol.
En la calle, chaval,
hace frío y es de noche.
Y se escuchan sirenas al pasar.


martes, 17 de marzo de 2009

Apoyando a los colegas

Mi compi, Dani Cabrera, presenta Freelancit en el BBVA Open Talent. Desde aquí le apoyo e invito a los que leáis esto a que también lo hagáis. Sin duda, el proyecto lo merece.

Freelancit es una comunidad online para profesionales freelance y está, cómo no, desarrollada en Ruby on Rails por ASPgems



Salud y rocanrol¡

Carry on, my sons forever
Carry on, when I am gone
Carry on, when the day is long
Forever carry on
For as long as were together
Then, forever carry on


lunes, 9 de marzo de 2009

No es lo mío , pero bueno...

Ayer desplegué www.procesosmadrid.es, el site de la empresa de mi amiga Julia. Se dedican a control de plagas y ahora también a evitar que los rayos te caigan encima.

Yo no soy diseñador, pero bueno, algo ha mejorado el site. Hemos aprovechado para darlo de alta en Google Analytics para aprender un poco de analítica web.

Visitas, visitas, queremos visitas¡¡¡

Salud y rocanrol

Porque sé que es un baile salvaje
combate a mala cara
veo todo en blanco y negro, blanco y negro...
Sólo quiero ser más rápido que ellos
y echar todo a perder, un día trás otro
y un buen rato después saber llegar a casa
antes de que el sol me diga que es de día.


jueves, 5 de marzo de 2009

El principio de la mínima sorpresa

Me dice un amigo que tiene un problema con el plugin acts_as_feeder. Tiene un modelo en el que ha incluido ese comportamiento y a la hora de lanzar la carga sobre una de sus instancias el sistema canta por soleares.

Escarbando, escarbando llegamos a que el casque ocurre al ejecutar el método open pasándole como parámetro un StringIO. Ese parámetro es el resultado de ejecutar también open pasándole la URL de un feed.

Ponemos trazas y vemos que al primer open le llega un String, como esperábamos; pero al segundo le llega unas veces un Tempfile y otras un StringIO. El primer caso funciona pero el segundo no y, además, lo que ocurre no tiene sentido.

Pues sí lo tiene. Sólo nos queda mirar qué hace el método open de open-uri y observamos este pedazo de código:

217 StringMax = 10240
218 def <<(str)
219 @io << str
220 @size += str.length
221 if StringIO === @io && StringMax < @size
222 require 'tempfile'
223 io = Tempfile.new('open-uri')
224 io.binmode
225 Meta.init io, @io if Meta === @io
226 io << @io.string
227 @io = io
228 end
229 end


Ahí la llevas. Si se trae más de 10Kb te lo mete en un Tempfile; si no, te devuelve un StringIO.

Y claro, esto ha dejado de funcionar al meter un blog nuevo en la BD. Por eso el proceso que lee no trae casi nada y de ahí todo el problema.

¿Me sorprende? No. El principio de la mínima sorpresa vuelve a triunfar.

Salud y rocanrol.

Navega, velero mío,
sin temor, que ni enemigo navío,
ni tormenta, ni bonanza
tu rumbo a torcer alcanza,
ni a sujetar tu valor.

Veinte presas hemos hecho
a despecho del inglés,
y han rendido sus pendones
cien naciones a mis pies.

Que es mi barco mi tesoro,
que es mi dios la libertad,
mi ley, la fuerza y el viento,
mi única patria, la mar.


jueves, 19 de febrero de 2009

Google Analytics: la polémica

Sólo quiero dejar clara mi postura en este tema.

Todo viene de un post del CEO de toprural acerca de cómo Google Analytics recoje sus datos y de cómo un parámetro de configuración que muy poca gente conoce puede alterar sensiblemente los resultados que se obtienen.

Las opiniones que se han dejado ver en la red son de todo tipo y color, pero se pueden agrupar en dos, como bien se explica en fansgao:
  • la expresada en loogic, 'Un ejemplo más de lo que ocurre cuando construimos un negocio sobre los cimientos de una empresa que a la que al final del día lo que más le importa es reportar buenos resultados a sus accionistas'
  • la expresada en web-analytics, 'Un ejemplo más de lo que ocurre cuando contruimos un negocio sobre los cimientos de una herramienta que no sabemos cómo funciona'
Y yo, claramente, con Pere Rovira y los que como él opinan que la culpa no es sólo de la herramienta sino de aquellos que hasta ahora han optado por utilizar google porque es gratis, sin saber como funciona. Es muy fácil confiar tus datos y tus decisiones a terceros y desentenderte de la herramienta elegida y de la analítica en sí misma, para luego no tener ni el más mínimo sentido de la autocrítica.

Salud y rocanrol

Bien oculto en tu disfraz en mis sueños siempre estás.
No lo puedo remediar, te deseo cada vez más.
Al principio todo era paz y contigo llego la maldad.
Surgiste de las tinieblas con fuego arrasador.
Has escrito la historia de la humanidad.
Haces siempre lo que quieres sin tener piedad.
Dios eterno todo lo haces a tu voluntad.

Maldito maldito sea tu nombre!
Maldito maldito sea tu nombre!

jueves, 15 de enero de 2009

Concepto interensante: La Jerarquía de Optimización

Este es una artículo de hace casi dos años al que hoy he accedido a través del blog de Gemma. En él se desarrolla el concepto de la jerarquía de optimización.

De manera similar a cómo la Pirámide de Maslow trata de explicar el orden de importancia que los humanos le damos a nuestras necesidades como una pirámide, Brian Eisenberg explica el orden de importancia que un cliente potencial de una sitio web le da a las suyas.

Abraham Maslow explica que mientras no sean satisfechas las necesidades en la parte inferior de la pirámide (al menos hasta cierto punto) no prestaremos atención a las necesidades superiores. En la base de la pirámide estarían las necesidades fisiológicas (respirar, comer, dormir...), seguidas de las necesidades de seguridad, afiliación y afecto, y estima y reconocimiento, hasta llegar al nivel superior de necesidades, ocupado por la necesidad de autorealización.

Según la jerarquía de optimización de Eisenberg, en la zona inferior de la pirámide se encuentra lo funcional, es decir, si tenemos en nuestro site lo que el cliente viene buscando (un producto, un servicio, una noticia...). Las siguientes necesidades en orden ascencente son lo accesible que resulta nuestro site y lo usable que es. Finalmente, el cuarto y el quinto nivel de la pirámide lo ocupan lo intuitivo que es el proceso de adquisición y lo persuasivo que resulta éste, de forma que el cliente quede plenamente satisfecho.

Un concepto muy interesante. Salud y rocanrol¡¡¡

Para Gemmamú:

Would you lay with me
in a field of stone.
If my needs were strong,
would you lay with me.
Should my lips grow dry,
would you wet them, dear,
In the midnight hour.
If my lips were dry.
Would you lay with me
in the stream of life
when the moon is full.
Would you bathe with me
Will you still love me,
when I'm down and out.
In my time of trial,
would you stand by me.
Would you go away
to another land,
walk a thousand miles
through the burning sand.
Wipe the blood away
from my dying hand
if I give myself to you.

miércoles, 14 de enero de 2009

Comenzamos 2009 con pair programming

Feliz 2009.

Últimamente no pasan cosas interesantes entre Rails y yo. No sé si, como cantaba Medina Azahara 'se perdió el amor' o la cosa va más por 'la vida sigue igual' de Julio Iglesias.

Sin embargo, hoy, por primera vez y después de mucho escuchar cómo otros hablaban de ello, he perdido la virginidad en el pair programming. Y lo he hecho con una persona tan escéptica o más que yo acerca de sus bondades (hola David).

Teníamos que meter un combo de idiomas en 9 formularios de actualización de datos y que en el evento onchange del combo se recargase el valor de cierto campo con su traducción al idioma seleccionado en dicha combo(este párrafo es para ahogarse).

Hemos decidido hacer juntos un partial con el combo y el observe_field que maneje la recarga del valor del campo a traducir y un método de controlador que haga la parte servidor de búsqueda de traducciones. Después, por separado, cada uno ha metido el partial en sus formularios de edición y ha modificado los métodos que éstos invocaban. Previamente, habíamos acordado la forma de implementar los cambios en estos métodos.

El resultado, desde mi punto de vista, ha sido muy positivo:
  • hemos desarrollado el trabajo común en menos tiempo que si lo hubiera hecho uno sólo
  • el código resultante de ese trabajo sólo ha necesitado un pequeño retoque a posteriori
  • además, David y yo tenemos fortalezas y defectos bastante complementarios, con lo que los dos hemos aportado
  • el trabajo por separado nos ha llevado muy poco tiempo porque hemos dejado la parte común muy fina
Sigo pensando que el pair programming como práctica diaria quita más que aporta. Sin embargo, veo que como práctica quizás semanal o como punto de partida de los proyectos y en proyectos que requieran equipos de varias personas puede aportar bastante valor. Como todo, en su justa medida, me gusta el pair programming.

Salud y rocanrol

Well I'm upper upper class high society
God's gift to ballroom notoriety
And I always fill my ballroom
The event is never small
The social pages say I've got
The biggest balls of all