miércoles, 22 de diciembre de 2010

Upload de ficheros con CKEditor

Hace unos días, en un proyecto en el que estamos usando CKEditor para que los administradores puedan gestionar el contenido de la web, me pidieron añadir upload de imágenes.

La opción más simple que encontré fue utilizar el plugin rails-ckeditor, que integra la funcionalidad de subida de imágenes de una forma bastante elegante usando SWFUpload.

Como siempre, en local funcionaba todo perfectamente, pero al instalar en la máquina de integración dio un poco de guerra.

Para empezar, el primer problema fue con la versión de RMagick, instalando la última versión disponible (2.13.1) me daba un bonito error

Updating installed gems
Updating rmagick
Building native extensions.  This could take a while...
ERROR:  Error installing rmagick:
ERROR: Failed to build gem native extension.
...
checking for ImageMagick version >= 6.4.9... no
Can't install RMagick 2.13.1. You must have ImageMagick 6.4.9 or later.


El problema es que la máquina de integración tiene Ubuntu Hardy, y la versión de ImageMagick de Hardy es la 6.3.7:

$ convert -version
Version: ImageMagick 6.3.7 06/04/09 Q16 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2008 ImageMagick Studio LLC

Así que mirando en github las dependencias de la Rmagick en el fichero extconf.rb se encuentra que la última versión que se puede usar es la 2.12.2, actualizamos bundler y instalación superada.

El siguiente problema aparece al probar la subida de imágenes y ver que da simplemente un alert de javascript, a veces con un 401 y otras con un 2038 sin ninguna más información.

Mirando en el log de apache se encuentra el error

84.79.196.203 - - [11/Nov/2010:11:16:03 +0100] "POST /es/ckeditor/create/image?.... HTTP/1.1" 401 350 "-" "Shockwave Flash"

El problema es debido al Flash de subida de imágenes, que no es capaz de gestionar la autentificación básica del servidor de integración y da un Unathorized.

La solución, permitir el acceso a esa carpeta del servidor de integración en Apache añadiendo en el virtual host


<Location /*/ckeditor/create/image*>
Satisfy Any
Allow from all
</Location>


El * porque utilizamos el plugin routing filter para gestionar el multilenguaje.


 Y con estos dos pequeños cambios, prueba superada. Aquí lo dejo por si a alguien le sirve de ayuda....

martes, 16 de noviembre de 2010

Conferencia Rails 2010 - Impresiones

Retomo mi abandonado blog desde hace meses para hablar un poco de la conferencia rails que se celebró en Madrid hace un par de semanas.

No se como explicarlo, pero me ha dejado una sensación extraña esta conferencia. En las dos primeras que asistí, en 2007 y 2008, la mayoría de conferencias a las que fui estaban centradas exclusivamente en rails (funcionalidades, escalabilidad, buenas prácticas, ....) y en testing de aplicaciones desarrolladas con rails

El año pasado cambió un poco la cosa, se introdujeron algunas charlas en inglés, se habló de las novedades (rack, sinatra, rails 3),  y se filosofó mucho sobre programación

En cambio este año, tengo la impresión de que no se ha hablado practicamente nada de rails y no acabo de entender muy bien el motivo. Puede ser porque la comunidad rails española ya es bastante madura y interesa más explorar otros temas, que no se presentaran propuestas interesantes de charlas centradas en rails, pero no acabo de entenderlo, y de ahí esa sensación extraña de la conferencia (rails?)

Aunque todas las charlas han sido en inglés, la mayoría de los asistentes eran locales, supongo que en parte debido a que en fechas muy cercanas, se ha celebrado la primera RubyConf Uruguay y la Ruby And Rails en Amsterdam

A destacar las charlas sobre node.js y de WebSockets, que son temas a tener en vista y que pueden dar mucho juego dentro de un tiempo, y los siempre brillantes Pablo Delgado hablando de neo4j y Cavallé sobre CQRS


A ver que nos depara la conferencia 2011... allí estaremos para verlo...

jueves, 3 de junio de 2010

Euruko 2010


Para no perder la costumbre, como cada vez que voy a una conferencia, unas notas sobre la European Ruby Conference de este año, que ha sido en Cracovia.


En cuanto a las charlas, por citar unas cuantas, son destacables:
- El keynote tardío de Matz
- Jose Valim con una charla algo filosófica sobre cuando usar DSL
- Karel Minařík, hablando sobre como enseñar a programar usando ruby
- Sven Fuchs explicando las novedades de i18n en Ruby
- Jason Goecke y su presentación de Tropo, para añadir voz a las aplicaciones
- Piotr Szotkowski y profiling en Ruby 1.9
- Florian Hanke que está desarrollando un buscador en ruby
- Florian Glicher contando como funciona el Character encoding in Ruby 1.9

(tengo que añadir links a todas las charlas, los añadiré en breve...)  Los vídeos de las charlas están publicados en Vimeo


La representación española estuvo en las lightning talks, a cargo de javi, que nos contó como documentar usando las plantillas de las rails guides y anunció que la Conferencia Rails de este año será en inglés, invitando a participar a los asistentes y de fernando guillén, con una de las presentaciones más aplaudidas y divertidas de toda la conferencia hablando de un juego que hizo con gosu

Y de las que no vi, que fueron pocas, me supo mal perderme la de Tomasz, que dio una gran charla el año pasado

He encontrado estas notas de @cypher sobre el primer y segundo día donde hay un resumen bastante completo de las conferencias



Y comparando con Euruko 2009, me han gustado menos las charlas, el año pasado fueron mucho más variadas y tocaron muchos temas. En cambio, en las de este año, en casi todas tenía la impresión de que aunque ninguna hablaba de rails, casi todo era aplicable a rails, por lo que me llevo la sensación de que ha sido más monotemática, aunque no lo parezca por los contenidos.

Tampoco me gustó que no se publicará ninguna información sobre las charlas aparte del título, aunque sólo había un track y no se podía elegir charlas, siempre es interesante saber de que van a ir...

En cambio, las actividades 'extraescolares' fueron bastante mejores, con zumos, bebida y comida disponibles prácticamente durante todo el día, las conferencias en el centro de la ciudad de forma que nos pudimos mover a pie durante todo el fin de semana y un gran ambiente nocturno, donde el triunfador absoluto fue el Jazz Rock Cafe

Nos vemos en Berlin el año que viene en la Euruko 2011

jueves, 29 de abril de 2010

Actualizando Google Maps API de la v2 a la v3

Me ha tocado actualizar unos mapas que estaban utilizando la versión 2 de la API de Google Maps a la versión 3.

Algunas de las novedades de la versión 3 son el soporte a iPhone y Android, mejora de la velocidad de carga, ya no es necesaria una clave de acceso y siguiendo la línea del resto de aplicaciones de Google ya no soporta IE6.

La idea de este post es hacer una guía rápida de migración, con el código de la v2 y el equivalente de la v3, no he utilizado ninguna nueva funcionalidad.

Suponiendo que tenemos definidas las variables longitude, latitude, zoom_level, image_path, html_content y div_element (autoexplicativas todas)

Primero de todo incluimos el JS de google, que ha pasado de

http://maps.google.com/maps?file=api&v=2&key=API_KEY


a

http://maps.google.com/maps/api/js?sensor=false


Donde sensor indica si la aplicación utiliza un sensor para localizar al usuario.

La creación de un mapa en la v2 era

var myLatlng = new GLatLng(latitude, longitude)
map = new GMap2(div_element);
map.setCenter(myLatlng, zoom_level);



Y en la nueva versión

var myLatlng = new google.maps.LatLng(latitude,longitude);
var myOptions = {
  zoom: zoom_level,
  center: myLatlng,
}
map = new google.maps.Map(div_element, myOptions);



Por una parte se ha sustituido la 'G' del nombre de los objetos por el namespace 'google.maps.' y por otra parte, las propiedades se asignan a través de un objeto (myOptions en este caso) en lugar de utilizando métodos.

Una vez creado el mapa, se le pueden cambiar / asignar nuevas propiedades con el método setOptions, p.e. los controles del mapa, que en la versión 2 se asignaban con

map.addControl(new GSmallMapControl());

Ahora se asignan


map.setOptions({
    navigationControl: true,
    navigationControlOptions: { style: google.maps.NavigationControlStyle.SMALL}
})

         
No es exactamente el mismo control, pero todavía no están implementados todos en la nueva versión.

A la hora de crear un marcador con imagen personalizada pasamos de

var icon = new GIcon(G_DEFAULT_ICON);
icon.image = image_path;
marker = new GMarker(new GLatLng(latitude, longitude), icon);
map.addOverlay(marker);


a

marker = new google.maps.Marker({
  position: point,
  map: map,
  icon: image_path
});


Igual que en la creación del mapa, por medio de un objeto pasamos todas las propiedades al marker.


Al borrar elementos de pantalla la cosa se complica. En la versión anterior simplemente llamando a map.clearOverlays() limpiabamos el mapa. En la nueva versión hay que guardar la referencia a los objetos para borrarlos manualmente aplicando el método setMap(null). En la documentación hay un ejemplo bastante completo

Por último tambien ha cambiado tambien la creación de mensajes (bubbles), antes era:


var myLatlng = new GLatLng(latitude, longitude)
map.openInfoWindowHtml(myLatlng, html_content)


Y ahora

var myLatlng = new google.maps.LatLng(latitude,longitude);
var infowindow = new google.maps.InfoWindow({
  content: html_content,
  position: myLatlng
});


Disclaimer: No he pretendido hacer una guía exhaustiva de migración, simplemente explicar los cambios que me aplicado migrando un mapa ya existente. Es posible que tanto la implementación anterior como la nueva no fueran de la forma más óptima o canónica, ya que como en la mayoría de las cosas, no soy experto en el tema....

lunes, 29 de marzo de 2010

Ubuntu Remix Edition en Dell Mini 10v

Hace algo más de un mes compré un Dell mini 10v. Viene con Windows 7 starter y con 1GB de RAM y al ver lo lento que iba todo, lo que tardaba en arrancar, ... decidí formatearlo y instalarle Linux.

Dell tiene algunos modelos con Ubuntu, así que buscando un poco encontré que tienen una versión de Moblin para descargar en su wiki, que se instala sin ningún problema desde USB y que funciona perfectamente.

Eso si, despues de unas semanas de uso no me convenció la interfaz gráfica de Moblin, no me parece cómoda de usar, así que decidí instalar Ubuntu Remix Edition.

Una vez instalado todo funciona perfectamente, todo... menos la wi-fi... que es una Broadcom BCM4312 (se puede ver el modelo con lspci). Parece que no se instala el driver por defecto porque es un controlador no libre suministrado por el fabricante

Y para instalar el driver, de nuevo buscando un poco, en la sección de WifiDocs de la ayuda de Ubuntu hay una página donde lo explica todo paso a paso.

Simplemente hay que instalar un par de paquetes (dkms y patch, tambien dicen que hace falta fakeroot pero a mi me funcionó sin instalarlo), instalar bcmwl-kernel-source y habilitar el controlador privativo

Y si os pasa como a mi, que a mi router wi-fi le han dejado de funcionar los puertos ethernet para poder conectarlo directamente, pues os tocará bajaros los ficheros desde otro ordenador uno a uno desde la web de ubuntu y luego instalarlos a mano...

Eso es todo, relativamente sencillo y realmente me gusta mucho más el entorno de Ubuntu Remix Edition que el de Moblin y va mucho más rápido que con Windows.

ACTUALIZACIÓN 12/04/2010: En los comentarios me recomiendan Jolicloud, no lo he probado, pero tiene buena pinta. Gracias por la sugerencia!

sábado, 27 de febrero de 2010

Event Delegation en Javascript

Hace unos días haciendo una página que básicamente es un listado con 3 radio buttons por fila (si, porras, aunque en tu charla del madrid-rb del jueves dijeras que no sabes para que se usan, a veces son útiles), quería que se enviara el formulario al seleccionar uno de los radio-buttons sin tener que pulsar en submit.

Para hacerlo un poco limpio, lo hice con javascript no intrusivo y prototype de la siguiente forma, donde cada uno de los input tiene definida la clase radio_submit

document.observe("dom:loaded", function() {
    $$('input.radio_submit').each(function(item) {
        item.observe('click', function() {
            item.parentNode.submit();
        });
    });
});

Pero no me gustaba esa solución donde tengo 3 function anidados, así que le pedí consejo a Paco a ver si se le ocurría una mejor solución.

Y evidentemente había una solución mejor, basada en Event Delegation

document.observe("dom:loaded", function() {
  $('user_source_list').observe('click', function(event){
    var element = event.target;
    if (element.match('input.radio_submit')){
      element.up('form').submit();
    }
  });
});


La idea es que en lugar de crear un evento en cada uno de los elementos, se crea sólo un evento en un objeto que los contiene a todos (en este caso es un div con el id 'user_source_list'), y capturamos el click sobre ese objeto.

Otra mejora que me propuso es que en lugar de usar parentNode para ir al elemento padre usara up('form'), de esa forma, si cambia el diseño de la página y se introduce algún elemento intermedio en el dom de la página, el código seguirá funcionando.

Paco tambien me pasó este enlace donde se ve como en Rails 3 se utilizará la misma técnica de javascript no intrusivo con delegación de eventos.

lunes, 18 de enero de 2010

Notas sobre webs un poco grandes

En ASPgems desde hace bastante tiempo vamos dando charlas internas para compartir el conocimiento entre nosotros, y desde hace unos meses las charlas son abiertas a todo el que quiera apuntarse.

Las charlas se publican en el blog y en twitter y la inscripción es en stage.


La última charla me ha tocado a mi, en la que he hablado un poco sobre mi experiencia durante más de dos años desarrollando BeRuby, un proyecto que ha pasado en este tiempo a ser el mayor proyecto de Rails en España y entre los 40 mayores del mundo (según en ranking de Alexa en la lista de rails100)

Repasando la presentación me he dado cuenta de que hablé muy poquito de Rails y mucho de MySQL, así que va a ser que uno de los puntos más importantes a la hora de escalar es un buen diseño y uso de base de datos, por mucho que las malas lenguas digan por ahí que Rails no escala :-)

La presentación tambien se grabó en vídeo (es la primera que grabamos y todavía está pendiente de retocar porque el audio no se oye muy bien), así que por ahora publico las transparencias, aunque sin la explicación algunas páginas no aportan mucho ....





De todas formas, entre nosotros, el orador no se puede decir que sea un comunicador nato, así que no espereis una gran charla cuando se publique el vídeo.... eso si, si hay cualquier duda o sugerencia sobre la presentación, aquí estoy para contestarla.


NOTA: La charla al final se publicó en el canal de Vimeo de ASPgems