jueves, 30 de diciembre de 2010

Reinventar la rueda

Esta última parte del año estoy muy poco rails y, sin embargo, muy javascript. Y, como no podía ser de otra forma, mi último post del año es de javascript. Corto, sencillo, conciso y útil, como debe ser nuestro javascript.

El caso es que andaba parseando fechas y viendo cómo podía sacarlas en una página en castellano viejo y me he encontrado el método toLocaleDateString() del objeto Date. Básicamente, a partir de una fecha genera un string en base a la configuración local del navegador. La referencia completa, donde siempre, en w3schools.

Y nada más, y nada menos. ¡Salud y rocanrol!

Entre la intensa bruma del castillo
se ve su figura aparecer.
Puente, jinete y la luna
con ojos atentos de mujer.

Es el héroe de paz triste y solitario,
que llega al atardecer.
Castiga brujas, duendes y villanos
que pagan con sangre su traición.

Las trompetas suenan la llegada.
La corte le recibe con honor.
La princesa le clava los ojos en el alma,
si a él no le asusta el amor.

No se inclina ante el rey ni baja la mirada.
Arrogancia avalada por valor.
Envidia y traición se esfuman con miedo.
Su mirada inspira terror.

No hay ningún loco sólo es leyenda,
todo lo cuentan en la taberna.
No hay ningún loco sólo es leyenda,
tú también tienes tu princesa

miércoles, 15 de diciembre de 2010

Alinear imágenes y textos

Lo típico que tienes una imagen en medio de una frase y no eres capaz de alinearla ni a la de trés. Pues bien, en el sitio de siempre está la solución: la propiedad vertical-align, que entre otros, puede tener los siguientes valores...

top
alineada por arriba con el elemento más alto de la línea
text-top
alineada por arriba con el top de la fuente la línea
middle
alineada al centro
bottom
alineada por abajo con el elemento más bajo de la línea
text-bottom
alineada por abajocon el bottom de la fuente la línea
Para más información, seguir el enlace. ¡Salud y rocanrol!

...
Una tarde en el rellano, mi vecina me gritó.
Su marido ya a empujarme. La madera apareció.
Que soy un borracho, estruendoso y peleón,
les dijeron,
y una mano de hostias allí mismo me dieron.
¡Ay! ¡Ay! ¡Ay! ¡Qué dolor!
Todas las noches canto esta triste canción.
¡Ay! ¡Ay! ¡Ay! ¡Qué dolor!
Las hostias ya me las dieron, pero tú no duermes, cabrón.
Malditos vecinos.

sábado, 4 de diciembre de 2010

Deploy error I

Pasando una aplicación a producción me he encontrado con que el siguiente código me casca:

1.upto(10).map{|i| [i, i]}

Como ya nos las hemos visto con estas, con aquellas e incluso con otras más feas, lo primero es ver qué versiones tenemos de las cositas básicas, y ha cantado la gallina a la primera. En desarrollo ruby 1.8.7; en producción ruby 1.8.6 enterprise edition.

Resulta que en esa versión upto necesita un bloque por narices. Po' fueno, po' fale, po' malegro... Lo cambiamos por...

(1..10).map{|i| [i, i]}

...y a correr.

¡Salud y rocanrol!

Deja ya de joder
yo no me llamo Javier
suéltame mujer
Yo no me llamo Javier
Yo no me llamo Javier
Yo no me llamo, Javier...
¿Hola como estás?
Qué niño tan bonito
¿Cómo? ¿Que es mío?
¿Que yo soy el padre?
¿Pero esto como va a ser
si yo soy impotente?
Yo no me llamo Javier
No te quiero volver a ver

miércoles, 1 de diciembre de 2010

Bordes, que sois unos bordes


Hoy, nuevamente, me he caído de un guindo. Esta vez, trasteando con html, su hoja de estilo, una tabla y su borde.

El problema a resolver era el siguiente: dada una tabla, con su thead, su tbody, sus tr's, sus th's y sus td's, poner con css un borde de 1px a todas sus celdas.

Inmediatamente piensas en algo como

table, th, td{border: 1px solid black;}

Y claro, no cuentas con que unos bordes se suman a otros y acabas con bordes de 1px y bordes de 2px. Entonces empiezas a darle vueltas a ver cuántas clases necesitas y cómo las vas a organizar. Que si la tabla con borde, los tr's con borde arriba menos el primero, los td's y th's con borde a la derecha menos el último... ¡Madre del amor! Así que le preguntas a Google y te lleva a donde todo lo saben y te enteras que todo se resuelve con una de esas propiedades que siempre has visto y nunca has usado:

table{border-collapse:collapse;}

¡Salud y rocanrol!

Joder con el chepa, el que no bebía
y lleva en la espalda, un barril de sangría.
Por allí va el mudo, que lleva en la cabeza
un tatuaje que dice "dame otra cerveza".

Este es el baile, el baile de los sordos,
todo el mundo iba para empinar el codo.
Este es el baile de los mutilados,
aquí no bebe nadie que diga que está sano.

El manco cortaba el jamón en tacos
y con la otra mano se bebe el vino blanco.
Mirar a la sorda, la que no se entera,
gritaron "calimocho" y allí está la primera.

Al tonto llevaban a hombros por la calle
por haberse tirado a la mujer del alcalde.

Este es el baile, el baile de los sordos,
todo el mundo iba para empinar el codo.
Este es el baile de los mutilados,
aquí no bebe nadie que diga que está sano.

miércoles, 17 de noviembre de 2010

Facebook es tu amigo

Después de renegar de la integración de Facebook en mis aplicaciones por el hecho de que te obligaba a utilizar su código, he redescubierto su nuevo api REST (o cuasi-REST) y me mola.

Por ejemplo, he podido enlazar a mis amigos en Facebook desde una página cualquiera. Para ello hay que seguir los siguientes pasos:
  1. Dar de alta una aplicación en Facebook: se hace aquí. Se obtiene un CLIENT_ID, un API KEY y un API SECRET, que se pueden utilizar para muchas cositas. De hecho hay todo un sistema de autorización OAUTH disponible.

  2. Obtener un AccessToken: vía curl, por ejemplo, con el siguiente código...

    curl -F grant_type=client_credentials -F client_id=XXXXX -F client_secret=YYYYYY https://graph.facebook.com/oauth/access_token -k

  3. Acceder a los datos: con las urls que te ofrece el API y que están descritas aquí. Por ejemplo, para ver mis amigos en...

    https://graph.facebook.com/100000135407379/friends?access_token=XXMYACCESSTOKENYYY

  4. Utilizarlos convenientemente: porque el API devuelve JSON. Utilizando JQuery...

    jQuery.ajax({
     url: 'https://graph.facebook.com/XXMYFACEBOOKIDYYY/friends',
     data: {access_token: 'XXMYACCESSTOKENYYY'},
     success: function(data){...},
     error: function(){},
     dataType: 'jsonp'
    })

    Importantísimo este último parámetro. Si no se utiliza, el same origin policy hará que no se reciban datos.
Ya sólo queda jugar un poquito y ver qué se saca. ¡Salud y rocanrol!

Well the kids are all hopped up and ready to go
They're ready to go now they got their surfboards
And they're going to the discotheque Au Go Go
But she just couldn't stay she had to break away
Well New York City really has is all oh yeah, oh yeah

Sheena is a punk rocker
Sheena is a punk rocker
Sheena is a punk rocker now

viernes, 24 de septiembre de 2010

El detalle es el detalle

De esto que pruebas tu aplicación sobre Internet Explorer 7 y, ¡oh, tristeza!, ¡oh, dolor! se te ha escojonao el menú.

Primero juras en arameo. Luego te cagas en todo lo cagable. Mencionas a todas las deidades y santidades que se pasan por la cabeza, a la familia Gates, y a todos sus antepasados. Y terminas por echarte un cubata y ponerte a ver qué pasa.

Y te das cuenta de que donde debería haber un <br/>, ¡hay dos! Pero en mi código sólo se genera uno. ¿Quién lo pone? ¡Pero si en Firefox no sale!

El error tipico: Internet Explorer es una puta mierda y me duplica los saltos de línea. O... seguro que la última actualización de Windows lo ha roto. O incluso... seguro que esto tiene una parámetro de configuración que se pone a no y se arregla.

Y al final, la dura realidad te cae en la cabeza y te la parte en cuatro trozos. Te das cuenta que generas el salto con content_tag(:br) y un <br/> es un tag sin contenido. Y lo que se genera es <br></br> y eso es lo que el maldito Internet Explorer interpreta como dos saltos.

Y lo cambias a tag(:br) y adiós sufrimiento.

¡Salud y rocanrol!

Doctor doctor, please
Oh, the mess I'm in
Doctor doctor, please
Oh, the mess I'm in
She walked up to me
and really stole my heart
And then she started
to take my body apart
Living! Loving! I'm on the run
So far away from you
Living! Loving! I'm on the run
So far away from you


domingo, 19 de septiembre de 2010

Cómo utilizar Putty en Windows para acceder por OpenSSH


Después de dar mil vueltas, por fin he conseguido configurar mi acceso a servidores Lynux con mi clave pública. Y todo lo he encontrado aquí.
En resumen:
  1. generar un par de claves (pública y privada)
  2. poner la clave pública entre las claves aceptadas en el servidor
  3. generar una clave privada manejable por putty a través de puttyGen
  4. configurar un acceso seguro
Et voilà! Salud y rocanrol.
If you're feeling down depressed and lonely
I know a place where we can go
22 Acacia Avenue meet a lady that I know
So if you're looking for a good time
And you're prepared to pay the price
Fifteen quid is all she asks for
Everybody's got their vice

jueves, 5 de agosto de 2010

Subversión, TortoiseSVN y Windows Vista


Una recomendación de última hora antes de irnos de vacaciones. Si tienes que actualizar Tortoise para Subversión en Windows Vista, OJITO con la versión 1.6.10. Al instalarla desaparecen los menús contextuales. Con la versión 1.6.9 se arregla el estropicio.

Y ¡ya! Salud y rocanrol.

Entre mis recuerdos no puedo encontrarte
Y ando perdido en mi soledad
Y voy por las calles contando los días
Y se van pasando sólo y sin ti

Yo le pido al tiempo que me diga algo
Y que en el silencio escuche tu voz
Y pasan las horas y no escucho nada
Tan sólo me queda un poco de amor

Sigo caminando entre multitudes
Como lo hacen tantos en la soledad
No pretendo nada, nada pueden darme
Solo tu mirada me haría feliz

miércoles, 7 de julio de 2010

Rails 3: rutas


En ASPgems hemos hecho una presentación conjunta sobre Rails 3 para, entre todos, conocer un poco mejor todos los cambios que trae. Mi trocito habla de rutas. Toda la información se puede encontrar en las Rails Guides.

Mi presentación:



Salud y rocanrol

Cogieron a la Jacinta, la moza de mejor pinta,
y en la misma plazoleta la pusieron en porretas
y la echaron al pilón sin mayor vacilación.
Luego fue una comitiva a Villatripas de arriba
a decirles que bajaran, miraran y compararan.
Comparando las dos Venus, cual es más y cual es menos...
Excepto algún poetastro que alabó a la de alabastro
y el pelma de don Simón que de un vuelo fue al pilón,
se oyó gritar al compás: - ¡La Jacinta mucho más! ¡La Jacinta mucho más! -
Y con grandiosa vehemencia añadió la concurrencia,
sobre todo los varones, que en lo tocante a erecciones,
la Jacinta en el pilón matarile, rile, ron.


lunes, 31 de mayo de 2010

Time, time, time

Las extensiones a la clase Time que se añaden en ActiveSupport me parecen geniales.

Por una parte tenemos las extensiones propias de Time::Calculations donde se añaden todo tipo de métodos de manejo y comparación de fechas. Mi favorita es advance que permite moverse a partir de una fecha dada en cualquier dirección. Recibe como parámetros una hash con las posibles claves :years, :months, :weeks, :days, :hours, :minutes, :seconds.

El método since es un wrapper de las otras extensiones, las Numeric. Éstas permiten hacer cálculo de fechas a partir de números. Permiten formar expresiones del tipo 2.years.from_now, más cercanas al lenguaje natural que Time.now.advance(:years => 2) pero que pueden quedarse cortas según las necesidades de cada uno.

Merece la pena echar un ojo. ¡Salud y rocanrol!

Today is the day
I've got something in my heart to say
tonight is maybe the night
but I need time, time, time


jueves, 15 de abril de 2010

agua + aceite = colacao

Por ir al grano, que dijo un dermatólogo, estaba yo con un modelo que soportase archivos anexos y traducciones y decidí tirar de attachment_fu y translate_columns. Para que los archivos anexos fueran traducibles también fue necesario incluir los campos que utiliza attachment_fu y sobreescribir el método public_filename. La cosa quedó más o menos así:

class Attachment < ActiveRecord::Base
 has_many :translations, :class_name => 'AttachmentTranslation'
 translate_columns :title, :url, :size, :content_type, :filename, :height, :width

 has_attachment :content_type => :image, :storage => :file_system, :path_prefix => 'public/uploads/attachments', :max_size => 4.megabytes

 def full_filename(thumbnail = nil)
  if self.translation && !self.translation.filename.blank?
   self.translation.full_filename(thumbnail)
  else
   file_system_path = (thumbnail ? thumbnail_class : self).attachment_options[:path_prefix].to_s
   File.join(RAILS_ROOT, file_system_path, *partitioned_path(thumbnail_name_for(thumbnail))) rescue ''
  end
 end
end

class AttachmentTranslation < ActiveRecord::Base
 belongs_to :attachment
 has_attachment :content_type => :image, :storage => :file_system, :path_prefix => 'public/uploads/attachment_translations', :max_size => 4.megabytes
end

¡Y listo! Ha sido corto pero intenso. ¡Salud y rocanrol!

Sea tan amable y diga qué le debo
Y 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
Diga qué le debo
Que me diga qué le debo de una vez


viernes, 26 de marzo de 2010

Engañando al ojo

Enunciado: Dado un formulario Ajax con los campos Asunto y Contenido cuyo resultado es el envío de su contenido en un email, añadir un campo de tipo archivo para poder adjuntar documentos al mismo.

Bueno, pues lo primero es cambiar el formulario. Primero, reemplazamos la helper que lo genera de form_remote_tag a form_tag. Segundo, hacemos que su enctype sea "multipart/form-data". De esta forma permitimos adjuntar archivos a través del formulario. Y tercero, debajo del formulario creamos un iframe oculto donde enviar la petición del formulario para que parezca ajax.

<div style="overflow:hidden;width:0px;height:0px"><iframe id="hiddenIframe" name="hiddenIframe" src="" width="0" height="0"></iframe><div>

Lo siguiente es añadir un campo de tipo archivo. En rails

<%= file_field 'mail','attachment' %>

Probamos el envío para ver si nos llega al servidor lo que nos tiene que llegar y todo va bien. Así que ponemos en el evento onsubmit del formulario todos los efectos javascript que antes manejaba el helper form_remote_tag. Y todo se rompe. Y lo que leo en los logs y nada es lo mismo. Hasta que quito el efecto de deshabilitar el formulario en el evento onsubmit y todo vuelve a la normalidad. En fin, así es la vida. Sigamos.

En el controller hemos de recoger el parámetro que recoje el archivo adjunto y pasarlo tal cual al método que realiza el envío del archivo. Además, utilizaremos el plugin respond_to_parent para manejar la respuesta en el iframe oculto.

responds_to_parent do
 render :update do |page|
  ...
 end
end


La clase que realiza el envío debe crear con el archivo temporal un attachment pero como de un TempFile no se conoce su tipo (salvo si utilizamos algún plugin al uso), lo haremos de forma genérica. Siendo att la variable que contiene el archivo temporal...

filename = att.original_filename
filedata = att.read
attachment "application/octet-stream" do |a|
 a.body = filedata
 a.filename = filename
end


Y cuando parece que todo está listo, nos encontramos con una cosilla más. Resulta que cuando se adjuntan attachments no se ejecuta el render normal del email por lo que es necesario crear a mano un part con el contenido del correo y poner el content-type del correo a multipart/alternative. En el método de envío del correo, donde antes decía

@body[:content] = content

ahora debe decir

part :content_type => "text/html", :body => content

Y con esto y un bizcocho, todo funcionando. Espero que se entienda. ¡Salud y rocanrol!

Kick your ass to heaven
With rock'n'roll tonight
I'll make this night a special one
Make you feel alright
Shoot my heat into your body
Give you all my size
I'm gonna beat the beat tonight
It's time to break the ice
Dynamite


jueves, 25 de febrero de 2010

Stringando que es gerundio

Una de enlaces útiles: inflections.

Me encantan la extensiones de la clase String para darles forma según su contenido. Resumiendo:
  • camelize convierte a camel case.
  • constantize busca una constante con el nombre especificado en el string.
  • dasherize sólo cambia underscores por guiones(dashes).
  • demodulize de un string que contiene un nombre de clase, elimina la parte referente a módulos.
  • foreign_key genera un nombre de clave extranjera del nombre de una clase.
  • humanize genera una frase legible, con mayúsculas, minúsculas, espacios...
  • parametrize elimina cualquier caracter extraño para dejar un string utilizable en urls.
  • pluralize devuelve el plural de la palabra contenida en el string.
  • singularize retorna el plural de la palabra contenida en el string.
  • tableize genera un nombre de tabla al estilo Rails.
  • titleize genera una frase legible pero con la letra inicial de cada palabra en mayúscula
  • underscore sustituye de una palabra las mayúsculas por un underscore y su correspondiente minúscula.
Además, se pueden parametrizar plurales irregulares o incontables en el archivo de configuración inflections.rb.

A ver si, una vez más, consigo recordar lo que escribo y no tengo que andar mirando la documentación cada dos por tres seis. ¡Salud y rocanrol!

I left alone my mind was blank
I needed time to think to get the memories from my mind

What did I see can I believe
that what I saw that night was real and not just fantasy

Just what I saw in my old dreams
were they reflections of my warped mind staring back at me

Cos in my dreams it's always there
the evil face that twists my mind and brings me to despair

The night was black was no use holding back
Cos' I just had to see was someone watching me
In the mist dark figures move and twist
was all this for real or some kind of hell

Six six six the Number of the Beast
Hell and fire was spawned to be released


miércoles, 13 de enero de 2010

Pinceladas sobre migrations

Ayer le di una vuelta a las rails guides para refrescar la memoria acerca de las relaciones polimórficas y siguiendo un par de enlaces llegué a la guía sobre migrations. Y encontré que hay una helper para crear campos con foreign keys.

Los ejemplos de la guía son estupendos:

create_table :products do |t|
  ...
  t.references :category
  ...
end


creará una tabla products con un campo category_id para hacer referencia a una tabla categories.

Para reforzar la clave extranjera con un índice apropiado es necesario utilizar un plugin como foreign key migrations.

Por otra parte, también podemos utilizar la helper references para crear campos para una relación polimórfica:

create_table :addresses do |t|
  ...
  t.references :addressable, :polymorphic => true
  ...
end


creará una tabla products con los campos addresable_type y addresable_id para que funcione una relación como

class Address < ActiveRecord::Base
  belongs_to :addressable, :polymorphic => true
end


Más información, aquí y aquí.

¡Salud y rocanrol!

Darkness
Imprisoning me
All that I see
Absolute horror
I cannot live
I cannot die
Trapped in myself
Body my holding cell

Landmine
Has taken my sight
Taken my speech
Taken my hearing
Taken my arms
Taken my legs
Taken my soul
Left me with life in hell