domingo, 10 de julio de 2011

Appeartowork - Enmascarando el uso de Facebook

Disfrute Facebook mientras aparenta trabajar

El día 8 de julio de 2011 a las 21:00 h (apróximadamente ;o) finalmente logré desplegar el sitio web  Appeartowork . Consiste en una idea interesante que radica en mostrar ciertos contenidos de  Facebook de una forma que el usuario aparenta estar trabajando. Actualmente hay tres variantes de camuflaje. La primera le da al sitio un aspecto similar al editor de textos  MS Word, y así parece que se está redactando un documento muuuuuy importante ;o). Otra variante es parecida al  MS Excel . ¡Cualquiera puede pensar que estamos haciendo cuentas bien difíciles! ;o). Finalmente si Usted es un poco geek también puede enmascarar su acceso a  Facebook aparentando que usa una consola :O . En todos los casos, aunque todavía faltan varios detalles por pulir, es una idea muy interesante . Espero que les guste. Si tiene otra idea, no dude en compartirla. Recuerde que todo es posible simelo pide.

martes, 14 de junio de 2011

El misterio de la variable controller en la definición de rutas

Routes - mapeo de URLs para aplicaciones web

En este artículo les hablaré acerca de una característica del módulo  PyRoutes que al menos yo no encontré bien documentada. Se trata del manejo de la variable controller dentro de la definición de las rutas en una aplicación web. Le invito a continuar leyendo este artículo si quiere conocer qué es lo que hace este módulo, la naturaleza del problema (si es que se le puede llamar así) y cómo se resuelve.

Acerca del módulo PyRoutes

El módulo  Routes ha sido diseñado para resolver un problema muy frecuente en el desarrollo de aplicaciones web, que es cómo relacionar las URLs con acciones concretas. Por ejemplo, blog/2008/01/08 podría mostrar una lista de artículos publicados en cierta fecha, mientras que login se utilizaría para autentificar los usuarios, ... y así sucesivamente.

Es característico de  Routes el poder definir las acciones del sitio y la jerarquía de URLs de forma independiente, para luego enlazarlas del modo que sea más conveniente. Si en algún momento se cambia de idea acerca de una URL solo se cambia la línea donde se define la regla, y no será necesario tocar la definición de la acción. Incluso es posible tener múltiples caminos para lograr el mismo resultado.

El diseño de  Routes ha sido inspirado por  Ruby On Rails, pero en su estado actual existen divergencias significativas. Con el tiempo se ha convertido en la base de frameworks como  Pylons,  CherryPy, y permitió la integración de  TurboGears 2 con  Pylons.

El problema

 Routes forma parte también de un framework  WSGI muy sencillo que desarrollo desde hace poco tiempo. Al utilizarlo siempre me llamó la atención que la documentación ofrecía ejemplos donde se utilizaba la variable controller en la definición de las rutas. Por ejemplo en este caso :

>>> from routes import Mapper
>>> mapper = Mapper()
>>> mapper.connect('test', '/{controller}/{action}')
>>>
>>> print mapper.routematch('/hello/world')
None

Cómo se puede apreciar este código no funciona. Por otra parte , si se cambia ligeramente el código anterior entonces sí funciona.

>>> from routes import Mapper
>>> mapper = Mapper()
>>> mapper.connect('test', '/hello/{action}', controller='hello')
>>>
>>> mapper.match('/hello/world')
{'action': u'world', 'controller': u'hello'}

¿Entonces cuál es la causa de esta situación aparentemente tan extraña?

Utilizando la variable controller en definiciones de rutas

Pues bien la cuestión es que en el Mapper() no se especifican los controladores. Todo parece indicar que hay que hacer esto explícitamente. La implementación predeterminada utiliza los nombres de los ficheros en un directorio. Sucede que por defecto, si no encuentra el controlador adecuado al procesar la ruta siempre se devuelve None. Ese es también el motivo por el que el segundo ejemplo funciona al especificar un controlador.

Para solucionarlo, existen dos opciones:

  1. Pasar a Mapper() la ruta (absoluta) a los controladores
mapper = Mapper(directory='/ruta/a/los/controllers']

  1. Pasar a Mapper() una función controler_scan que devuelva una lista con los nombres de los controladores disponibles. Por ejemplo:
>>> def controller_scan(directory=None):
...        return 'hello', 'auth'
... 
>>> mapper = Mapper(controller_scan=controller_scan)
>>> mapper.connect('default', '/{controller}/{action}')
>>> mapper.connect('login', '/login', controller='auth', action='login')
>>> mapper.connect('logout', '/logout', controller='auth', action='logout')
>>> mapper.match('/hello/world')
{'action': u'world', 'controller': u'hello'}

En mi caso particular, la segunda opción es la más apropiada. Así que muchas gracias  Chema Cortes por  aclararme esta duda ... ;o) Espero que este artículo le sirva a Usted también de referencia y quizás le ahorre un buen tiempo tratando de hacer que esto funcione.

lunes, 6 de junio de 2011

Uso local de Dragonfly para depurar sitios web con Opera

Dragonfly = Firebug para Opera

Escribo este artículo después de descubrir cómo utilizar una herramienta desarrollo tan importante como Dragonfly sin tener que estar conectado a los servidores de Opera. Despúes de haber pasado mucho tiempo creyendo firmemente que la mejor opción era tener algo como su equivalente Firebug por fin he logrado instalarlo y hacerlo funcionar en la PC donde desarrollo aplicaciones web. Todo parece indicar que encontré el checkbox correcto ;o). Si sigue leyendo este artículo hasta el final Usted descubrirá una forma más cómoda de depurar con Opera los errores o defectos de sus aplicaciones. Como siempre le invito a suscribirse mediante RSS a este blog; especialmente si desea estar informado de temas relacionados con programación, diseño de sitios, herramientas o trucos útiles, y muchas otras cosas interesantes del mundo de la informática.

Instalación paso a paso de Dragonfly

El proceso es realmente simple. Lo primero que hay que hacer es descargar la versión más reciente de Dragonfly desde los servidores de Opera.

Descargar Dragonfly

Una vez hecho esto, extraiga los contenidos del fichero .zip en una carpeta en su sistema de archivos local. En este caso, como utilizo Ubuntu 10.04 Lucid, la carpeta que escogí fue /var/www/dragonfly , pero puede ser cualquiera (... donde el usuario tenga derechos de lectura, por supuesto ;o).

Posteriormente, es preciso sobre-escribir la URL desde donde se descargará la herramienta y remplazarla por una que haga referencia a la ubicación de la carpeta creada anteriormente. Hay dos formas de hacerlo. Las describo a continuación .

Editando el fichero operaprefs.ini

La vía más avanzada consiste en editar manualmente el fichero operaprefs.ini (así que si Usted prefiere los diálogos de configuración, mejor consulte el próximo epígrafe ;o) . En Ubuntu 10.04 este fichero se encuentra en la ruta ~/.opera/operaprefs.ini . En Windows la ruta sería C:\Documents and Settings\<Usuario>\Application Data\Opera\Opera\operaprefs.ini. Cuando lo encuentre, utilice el editor de texto de su preferencia para ver sus contenidos. Debe haber un fragmento similar al que se muestra a continuación

[Developer Tools]
Developer Tools URL=https://dragonfly.opera.com/app/

Remplace esta URL por otra de la forma file://localhost/path/to/dragonfly/client-en.xml. En mi caso, como he extraído los ficheros en /var/www/dragonfly, la configuración quedaría así.

[Developer Tools]
Developer Tools URL=file://localhost/var/www/dragonfly/client-en.xml

Utilizando el editor de preferencias de Opera

Si Usted prefiere utilizar diálogos de configuración, sin dudas esta variente es más apropiada. Si Usted está utilizando Opera simplemente haga click en el enlace que se muestra a continuación y verá el editor de preferencias del navegador. Su apariencia es parecida a la que se muestra en la figura.

Editor de preferencias de Opera

URL predeterminada en panel de preferencias de Opera

Remplace la URL (i.e. https://dragonfly.opera.com/app/) por otra de la forma file://localhost/path/to/dragonfly/client-en.xml. En mi caso, como he extraído los ficheros en /var/www/dragonfly, la URL sería file://localhost/var/www/dragonfly/client-en.xml.

URL predeterminada en panel de preferencias de Opera

Posteriormente, presione la combinación de teclas Shift + Ctrl + I e immediatamente aparecerá Dragonfly en la parte baja de la ventana . Poco tiempo después Usted podrá ver las pestañas que permiten observar y manipular el DOM, inspeccionar las peticiones hechas a través de la red, conocer el espacio dedicado al almacenamiento de datos de sesión, ... y así sucesivamente.

Consejos útiles

Si siguió los pasos anteriores, entonces my probablemente ya estará utilizando Dragonfly sin tener que estar conectado a los servidores de Opera. En este caso quizás desee añadir los siguientes botones para facilitar el acceso directo a estas herramientas. Simplemente arrástrelos (drag) y suéltelos (drop) sobre cualquier panel de Opera.

Enlaces directos a Dragonfly

Reload from cache
Dragonfly

En caso que no le funcione algo o tenga dudas en algun paso, simelo pide, podria ayudarle. Espero sus comentarios ;o).

miércoles, 9 de marzo de 2011

Funcionalidades no documentadas de la API de Facebook

Facebook hacks

Jugando un poco descubrí una funcionalidad no (muy bien) documentada de la API de Facebook conocida como Facebook Graph API. Realmente es un detalle que me hacía falta utilizar en un proyecto para disminuir el número de peticiones que se hacen a los servidores de Facebook. Cuando leí la documentación se aborda la manera en que la API permite hacer este tipo de cosas e incluso se muestran ejemplos de peticiones sencillas. Les invito a leer este artículo y sabrán de una forma de optimizar las peticiones que se realizan a la API de Facebook y, por consiguiente, mejorar el desempeño de las aplicaciones. Si desea estar al tanto de otros artículos similares, Usted puede suscribirse a este blog mediante RSS.

Lo más frecuente, al utilizar la API antes mencionada, es hacer peticiones para obtener los datos de objetos individuales (e.g. usuarios) o de sus conexiones (e.g. las páginas que le gustan a un usuario). En la documentación se puede encontrar información acerca de cómo hacer esto (y por brevedad asumiré que Usted ya está familiarizado con los detalles, pero si no es así, solícitelo en un comentario y le dedicaré otro artículo a esta materia ;). Solo menciono que para lograrlo se utilizan URLs del tipo https://graph.facebook.com/<ID de objeto> (e.g. la información de la página de la Coca-Cola sería estaría disponible en https://graph.facebook.com/cocacola ).

Sin embargo, a veces es necesario solicitar la misma información para múltiples objetos (e.g. los mensajes de estado de un grupo de usuarios). Si se sigue el procedimiento anterior en este caso se necesitaría efectuar varias peticiones. La API permite hacer esto eficientemente. Por ejemplo, si se necesitara obtener los datos de la página antes mencionada y los de Bret Taylor entonces con una única petición a https://graph.facebook.com/?ids=cocacola,btaylor ya se podrían obtener todos estos datos.

Digamos que queremos obtener los mensajes que varios usuarios han publicado en su status. Ya entonces no resulta tan evidente lo que hay que hacer debido a que la URL para obtener el de un solo usuario es e.g. https://graph.facebook.com/btaylor/statuses . La duda entonces consiste en saber donde situar los IDs de los objetos.

Pues bien, digamos que desea obtener los mensajes míos y de Bret Taylor en una sola petición, entonces la URL sería así https://graph.facebook.com/statuses?ids=btaylor,olemis , es decir se mantiene el tipo de conexión al final y se añaden los IDs de los objetos como parámetros.

Ya lo sabe, si antes no le resultaba evidente, aquí tiene los ejemplos que no aparecen en la documentación oficial. Espero que les sea útil el consejo para optimizar sus aplicaciones. Pregunte cualquier duda, siempre podrá contar con mi ayuda, simelo pide.

miércoles, 9 de febrero de 2011

No más Yoga ... ¡RON!

Yoga vs Ron

¡Estudios confirman que beber RÓN trae los mismos beneficios que el yoga! ¿No me creen? Más les vale empezar a practicar, a mí me va bien. :D

lunes, 17 de enero de 2011

Slitaz - Una distribución GNU/Linux minimalista

Logotipo de Slitaz

Recientemente tuve que utilizar una laptop con problemas de hardware que impedían que arrancaran correctamente los LiveCD de Knoppix, Ubuntu y varias otras distribuciones (que hasta ahora no me habían fallado). Tampoco logré que arrancara un CD de instalación de Windows. Fue entonces cuando me decidí a buscar una distribución minimalista para tratar de resolver el problema, y entonces encontré a Slitaz. Esta es una distribución de GNU/Linux que incorpora un sistema operativo completo, con escritorio OpenBox y navegador de internet Midori (entre otras herramientas básicas ;o) en solo 30MB. Simelo preguntan les recomiendo que lo tengan a mano pues podría ser muy útil si necesitan reparar su PC.

viernes, 7 de enero de 2011

Dos años y sigo blogueando ...

Aunque no lo parezca han pasado ya dos años desde que comencé a publicar artículos en este blog. Quería agradecerles a todos aquellos que lo han visitado desde más de 80 países en unas 16 regiones o subcontinentes. Hasta ahora hemos hablados de muchos temas , así que les invito a conocer cómo es que Ustedes, los lectores, han reaccionado ante los contenidos que aquí se publican. Para mí es un placer saber que Ustedes tienen un lugar para este blog dentro de su tiempo (libre); y ya saben, todo es posible ... SIMELO piden.

Como se puede apreciar las visitas son más frecuentes desde Sudamérica, Europa, Centroamérica y Norteamérica. Supongo que esta distribución se deba a los lazos culturales y al conocimiento del idioma español.

Los artículos más populares (al menos los que más han accedido directamente ;o) han sido los siguientes :

Página Pageviews Unique pageviews Average time
1. / 1,198 1,780 00:05:37
2. GeneXus: Convirtiendo aplicaciones de escritorio a web 366 320 00:02:25
3. La cara oculta de Fibonacci (en Python) 351 297 00:04:10
4. No me gustan los templates de Django ... 255 208 00:03:58
5. Comandos : Pipe Viewer ... ¿Qué está pasando por esta tubería? 207 171 00:03:06
6. Tutorial: Cómo crear enlaces directos en Windows con Python 190 156 00:00:54
7. Añadir gadgets de Google en entradas (artículos) de Blogger 169 130 00:02:44
8. Dibujando figuras geométricas con Eukleides y LATEX 144 121 00:02:37
9. Introducción a la API de Google Analytics 138 111 00:03:17
10. Microsoft firma acuerdo con la PSF. ¿Python para Visual Studio? 134 111 00:07:40

Les muestro más gráficos que ilustran que todavía debo ser más sistemático si quiero alcanzar los niveles de audiencia que tuve en marzo del 2010.

¿Y qué pasará ahora?

Este fin de año 2010 ha sido una temporada en la que se puede decir que fui muy feliz. Un día me senté a releer los artículos y me he dado cuenta de que puedo hablarles más de mi lado no tecnológico. Así que tengo en mente aumentar la frecuencia de las entradas que traten temas más relajados y de esparcimiento. Como siempre, simelo preguntan, les digo que espero que Ustedes sigan ahí escuchando ... ¡ La invitación esta hecha !

jueves, 30 de diciembre de 2010

Barça es todo CORAZÓN

Xavi inauguró el marcador

Si todavía Ud. tenía dudas de que los catalanes sabían bailar, pregúntele al  Real Madrid. Ni Cristiano Ronaldo, ni ninguna otra de sus estrellas pudo detener la sinfonía. Todos se seguían muy bien el ritmo: era el mismo compás que escuchaban las últimas 5 veces que enfrentaron a este equipo; era la sinfonía de Guardiola. Los corazones de todos los jugadores, del público, ... todo estaba bien coordinado para lograr la resonancia que sentimos en el Camp Nou. Mourinho estaba muy fatigado (por decirlo de alguna forma ...) y no sabía cómo bailar este vals (¿o era una polka?): nada de paseitos, nada de reclamos a los árbitros, ni picardías ... todo era en vano. Y es que el  Barça quiere el balón y el afecto es recíproco. Después de un favorable 6-2 en el encuentro previo ahora el equipo merengue se llevo una manito.

Mourinho cariacontecido

Pero esto no bastaba y volvimos a la carga. Próxima víctima el  Rubin Kazan. Esta vez se rompió el hechizo. Lo que no lograron los titulares años atrás, lo supieron hacer los suplentes esta vez. Porque el  Barça es todo talento; sin dudas el relevo está asegurado. Esta vez la máquina no quiere parar. Para no dejar lugar a dudas, ya lejos del Camp Nou, la visita a la  Real Sociedad también rindió sus frutos. De allí nos llevamos otra manito. Sí, necesitábamos DOS manos porque así una lava la otra, así como Messi también hizo DOS goles.

Celebración de Xavi Hernández Messi, Xavi e Iniesta aspirantes al Balón de Oro

Lo que muchos todavía no entienden es que  Barça es puro orgullo. Es por eso que son la base del equipo de España, actual campeón del mundo; es por eso que la CANTERA otra vez VENCIÓ a la CARTERA; es por eso que provienen de allí los tres  candidatos al Balón de Oro (aunque confieso que prefiero a Schneider o Forlán en vez de Iniesta); es por eso que todo el mundo está de fiesta ... simplemente ES QUE EL BARÇA ES TODO CORAZÓN.

jueves, 23 de diciembre de 2010

Usar bindings de XAML para mostrar valores de tipos enumerados en controles WPF

Microsoft.NET

Este artículo es breve y consiste en una respuesta a  un pequeño tutorial que publicó mi amigo Feston en  su blog. Su solución consiste en utilizar el método GetValues para obtener un arreglo con todos los valores definidos para el tipo de datos en cuestión. Sin embargo, ¿realmente es necesario escribir líneas de código para lograr esto? Continúe leyendo y conocerá una alternativa que logra el mismo efecto, pero sólo utiliza el fichero XAML (que es dónde debería especificarse este tipo de cosas).

El procedimiento es simple (qué otra cosa podría decir :). Comencemos por crear una aplicación WPF sencilla (menú File > New > Project ... y selccionar WPF Application). El Visual Studio mostrará el editor WPF con una ventana vacía. Para hacer más simple el ejemplo, editaré el fichero Window1.xaml.cs para que luzca de la forma siguiente. Esto no implica que haya pérdida de generalidad en la discusión, puesto a que los pasos son similares si el tipo enumerado se define en otro fichero o assembly.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace EnumNamespace {
    public enum MyEnum {Value1, Value2, Value3, Value4}
}

namespace WpfEnumBinding {
    public partial class Window1 : Window {
        public Window1() {
            InitializeComponent();
        }
    }
}

Una vez hecho esto, se añade en el fichero XAML una referencia al namespace dónde se encuentra el tipo enumerado y otra al namespace System (seguro que el IntelliSense ayudará mucísimo ;o). Luego se define un recurso del tipo ObjectDataProvider que permita hacerle binding al valor que devuelve el método GetValues. Posteriormente se utiliza la extension StaticResource para hacer referencia al valor en cuestión. Si utilizamos un combobox, el fichero XAML queda de la siguiente manera:

<Window x:Class="WpfEnumBinding.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:EnumNamespace="clr-namespace:EnumNamespace"
    xmlns:System="clr-namespace:System;assembly=mscorlib"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <ObjectDataProvider x:Key="MyEnumResource" 
                            MethodName="GetValues" 
                            ObjectType="{x:Type System:Enum}">
            <ObjectDataProvider.MethodParameters>
                <x:Type TypeName="EnumNamespace:MyEnum" />
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="25" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <ComboBox ItemsSource="{Binding Source={StaticResource MyEnumResource}}"/>
    </Grid>
</Window>

... y la aplicación luce así

Espero que les sea útil esta sugerencia, al menos para aplicar en otras circunstancias parecidas los conocimientos adquiridos. Si le gustó este artículo le digo que los demás serán igual de interesantes, por lo que le invito a  suscribirse a este blog para que este al tanto de otros trucos similares. No lo olvide simelo pide siempre habrá una respuesta a esa inquietud o duda que Usted tenga del mundo de la informática y la programación.

Moropo: Bind de un tipo Enum a un combobox en C#