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