<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Marcos Vanetta (malev)</title>
 
 <link href="http://malev.com.ar/" />
 <updated>2012-05-06T17:31:08-03:00</updated>
 <id>http://malev.com.ar/</id>
 <author>
   <name>Marcos Vanetta (malev)</name>
 </author>

 
 <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/malev" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="malev" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
   <title>Nginx, passenger and PHP</title>
   <link href="http://malev.com.ar/nginx-passenger-and-php" />
   <updated>2012-04-13T00:00:00-03:00</updated>
   <id>http://malev.com.ar/nginx-passenger-and-php</id>
   <content type="html">&lt;h1&gt;Nginx, passenger and PHP&lt;/h1&gt;

&lt;p&gt;Suele pasar, solemos llenar de cosas nuestros VPS, y bueno, tuvo que pasar, necesitaba un Wordpress en un VPS y debo admitir que extrañé Apache por unos minutos. Luego de googlear mucho encontré esta solución:&lt;/p&gt;

&lt;h2&gt;Instalamos algunas cositas:&lt;/h2&gt;

&lt;blockquote&gt;&lt;p&gt;sudo yum -y install mysql-server php-fpm php-mysql php-pecl-apc&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Una buena práctica es ejecutar &lt;strong&gt;/usr/bin/mysql_secure_installation&lt;/strong&gt; para dejar nuestro MySQL en perfectas condiciones.&lt;/p&gt;

&lt;p&gt;En Ubuntu podríamos hacer:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;sudo apt-get install php5-cli php5-cgi php5-common php5-curl php5-dev php5-gd php5-imagick php5-mcrypt php5-mhash&lt;/p&gt;

&lt;p&gt;sudo apt-get install php5-mysql libmysqld-dev&lt;/p&gt;&lt;/blockquote&gt;

&lt;h2&gt;Instalando spawn-fcgi&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;spawn-fcgi&lt;/strong&gt;[1] es un herramienta del proyecto Lighttp que nos ayuda a preparar el ambiente para FastCGI. Tenemos que hacerlo amigo de &lt;strong&gt;nginx&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;cd /tmp&lt;/p&gt;

&lt;p&gt;wget http://www.lighttpd.net/download/spawn-fcgi-1.6.3.tar.gz&lt;/p&gt;

&lt;p&gt;tar -xvzf spawn-fcgi-1.6.3.tar.gz&lt;/p&gt;

&lt;p&gt;cd spawn-fcgi-1.6.3&lt;/p&gt;

&lt;p&gt;./configure --prefix=/usr&lt;/p&gt;

&lt;p&gt;make&lt;/p&gt;

&lt;p&gt;sudo make install&lt;/p&gt;

&lt;p&gt;sudo nano /usr/bin/php5-fcgi&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Y le pegamos esto:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;/usr/bin/spawn-fcgi -f /usr/bin/php-cgi -a 127.0.0.1 -p 49232 -C 2 -P /var/run/fastcgi-php.pid&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;También vamos a necesitar crear un archivo de inicio para spawn-fcgi. Creamos &lt;strong&gt;/etc/init.d/php5-fcgi&lt;/strong&gt; y le pegamos el contenido de &lt;a href="https://gist.github.com/2373780"&gt;este gist&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Cambiamos algunos permisos:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;sudo chmod +x /usr/bin/php5-fcgi&lt;/p&gt;

&lt;p&gt;sudo chmod +x /etc/init.d/php5-fcgi&lt;/p&gt;

&lt;p&gt;sudo update-rc.d php5-fcgi defaults&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;y ahora a lo más (sarcamo on) divertido (sarcasmo off), recompilamos &lt;strong&gt;nginx&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;Bajamos el código fuente:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;rvmsudo passenger-install-nginx-module&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Elegimos la opción 2 y le pasamos estos parámetros extras:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;--with-http_ssl_module --with-http_dav_module --with-http_gzip_static_module --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-client-body-temp-path=/var/lib/nginx/body --with-http_stub_status_module&lt;/p&gt;&lt;/blockquote&gt;

&lt;h2&gt;Configurando un VirtualHost&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/2373815"&gt;Aquí&lt;/a&gt; les dejo mi archivo de configuración de &lt;strong&gt;nginx&lt;/strong&gt;. Por supuesto lo deben guardar en un lugar donde nginx lo pueda encontrar. Si siguieron mi &lt;a href="http://blog.malev.com.ar/rvm-plus-nginx-plus-server/"&gt;post anterior&lt;/a&gt;, pueden colocarlo en: &lt;strong&gt;/opt/nginx/conf/conf.d/mycoolblog.conf&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;Reiniciamos y listo el pollo!&lt;/h2&gt;

&lt;blockquote&gt;&lt;p&gt;sudo mkdir /var/lib/nginx/&lt;/p&gt;

&lt;p&gt;sudo /etc/init.d/php5-fcgi start&lt;/p&gt;

&lt;p&gt;sudo /etc/init.d/nginx restart&lt;/p&gt;&lt;/blockquote&gt;

&lt;h2&gt;Base de datos&lt;/h2&gt;

&lt;p&gt;Lo más seguro es que tengan que crear una base de datos y un usuario por ejemplo para un Wordpress, aquí los pasos:&lt;/p&gt;

&lt;p&gt;Ejecutamos:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;mysql -u root -p&lt;/p&gt;&lt;/blockquote&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sql"&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;database_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;ALL&lt;/span&gt; &lt;span class="k"&gt;PRIVILEGES&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;database_name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;user&amp;quot;&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;localhost&amp;quot;&lt;/span&gt; &lt;span class="n"&gt;IDENTIFIED&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;password&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;FLUSH&lt;/span&gt; &lt;span class="k"&gt;PRIVILEGES&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;EXIT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[1] http://cgit.stbuehler.de/gitosis/spawn-fcgi/about/&lt;/li&gt;
&lt;li&gt;[2] codex.wordpress.org/Installing_WordPress&lt;/li&gt;
&lt;li&gt;[3] http://internetmodulation.com/2011/01/11/install-wordpress-inside-passenger-app.html.html&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 <entry>
   <title>Learning Javascript</title>
   <link href="http://malev.com.ar/learning-javascript" />
   <updated>2012-04-09T00:00:00-03:00</updated>
   <id>http://malev.com.ar/learning-javascript</id>
   <content type="html">&lt;h1&gt;Learning Javascript&lt;/h1&gt;

&lt;p&gt;Hace bastante tiempo que vengo leyendo y escribiendo sobre &lt;strong&gt;Javascript&lt;/strong&gt; y hay algunos posts que lo demuestran: &lt;a href="http://blog.malev.com.ar/mustache/"&gt;Mustache&lt;/a&gt; y &lt;a href="http://blog.malev.com.ar/objects-in-javascript/"&gt;Objects in Javascript&lt;/a&gt;. Estoy convencido que es un lenguaje importantísimo y muy necesario de dominar (aunque en calle muchos digan otra cosa). Esta vez vengo a recomendar 2 libros que encontré y un artículo resumen realmente fantástico.&lt;/p&gt;

&lt;h2&gt;Object oriented programming in Javascript&lt;/h2&gt;

&lt;p&gt;Un enfoque &lt;strong&gt;minimalista&lt;/strong&gt; como lo describe el propio &lt;a href="https://twitter.com/#!/gabordemooij"&gt;Gabor de Mooij&lt;/a&gt;. Al fin! Una buena guía acerca de objetos en Js, hace rato que venía buscando una y por eso la linkeo &lt;a href="http://www.gabordemooij.com/articles/jsoop.html"&gt;aquí&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Essential JavaScript Design Patterns&lt;/h2&gt;

&lt;p&gt;Por alguna razón la mayoría del código Js que suelo ver (y a veces programar) es estructurado y embarrado. Aquí &lt;a href="https://twitter.com/#!/addyosmani"&gt;Addy Osmani&lt;/a&gt; nos deja un libro interesante para recordarnos que Javascript es un lenguaje de programación orientado a objetos y debemos tratarlo como tal. Además lo liberó con licencia Creative Commons. &lt;a href="http://addyosmani.com/resources/essentialjsdesignpatterns/book/"&gt;Libro&lt;/a&gt;. Y aún más interesante, podemos seguir su evolución en este &lt;a href="https://github.com/addyosmani/essential-js-design-patterns"&gt;repo&lt;/a&gt; de Github.&lt;/p&gt;

&lt;h2&gt;Eloquent JavaScript&lt;/h2&gt;

&lt;p&gt;Todavía no lo he ledído, pero lo cita el mismo Addy Osmani y también está liberado con licencia Creative Commons, entonces &lt;a href="https://twitter.com/#!/marijnjh"&gt;Marijn Haverbeke&lt;/a&gt; ya se ganó un lugar en mi kindle con su &lt;a href="http://eloquentjavascript.net/"&gt;A Modern Introduction to Programming&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Nada que ver&lt;/h2&gt;

&lt;p&gt;En mi cruzada por empezar a respetar Javascript me encontré con este &lt;a href="http://openmymind.net/2012/4/4/You-Really-Should-Log-Client-Side-Error/"&gt;artículo&lt;/a&gt; en &lt;a href="http://news.ycombinator.com/"&gt;Hacker News&lt;/a&gt; y ... hasta me pareció obvio que necesitamos loggear los errores cliente-side. Tan obvio que nunca se me habría ocurrido.&lt;/p&gt;

&lt;h2&gt;JS Conf&lt;/h2&gt;

&lt;p&gt;Así es, en Buenos Aires el 19 y 20 de Mayo se va a realizar una conferencia sobre Javascript. Así que nos veremos ahí! &lt;a href="http://jsconf.com.ar/"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Actualización&lt;/h2&gt;

&lt;p&gt;Y como siempre, ni bien termino de escribir un post aparece un link genial, en &lt;a href="https://github.com/tcorral/Design-Patterns-in-Javascript"&gt;este&lt;/a&gt; repo de Github hay ejemplos de diferentes patrones de diseño implementados en Javascript com para practicar un poco.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>RVM plus Nginx plus Server</title>
   <link href="http://malev.com.ar/rvm-plus-nginx-plus-server" />
   <updated>2012-04-08T00:00:00-03:00</updated>
   <id>http://malev.com.ar/rvm-plus-nginx-plus-server</id>
   <content type="html">&lt;h1&gt;RVM plus Nginx plus Server&lt;/h1&gt;

&lt;p&gt;Al fin pude hacer andar mi servidor con RVM y Nginx! Aquí voy a dejar una receta por si tengo que volver a hacerlo (espero que no en el mediano plazo al menos).
Vamos a necesitar algunas cosas antes de empezar: &lt;strong&gt;curl&lt;/strong&gt;, &lt;strong&gt;git&lt;/strong&gt;, muchos paquetes de desarrollo y un usuario que pueda usar sudo.&lt;/p&gt;

&lt;h2&gt;Empezamos con el usuario&lt;/h2&gt;

&lt;blockquote&gt;&lt;p&gt;sudo adduser malev&lt;/p&gt;

&lt;p&gt;sudo passwd malev&lt;/p&gt;

&lt;p&gt;sudo visudo&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;y agregamos al final:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;malev ALL=(ALL) ALL&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;y ahora nos transformamos en nuestro nuevo usuario:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;su malev&lt;/p&gt;&lt;/blockquote&gt;

&lt;h2&gt;Preparandonos para instalar&lt;/h2&gt;

&lt;p&gt;Primero necesitamos instalar RVM en modo multiusuario [1], para esto necesitamos &lt;strong&gt;curl&lt;/strong&gt; y &lt;strong&gt;git&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;sudo yum install git-core curl&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;e instalamos RVM:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;sudo bash -s stable &amp;lt; &amp;lt;(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer)&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Esto instalara RVM en &lt;em&gt;/usr/local/lib/rvm&lt;/em&gt; y nos generará archivos en: &lt;em&gt;/etc/rvmrc&lt;/em&gt; y &lt;em&gt;/usr/local/rvm&lt;/em&gt;. También necesitamos configurar nuestros &lt;em&gt;.bashrc&lt;/em&gt; y el esqueleto para los futuros usuarios, así que en los archivos: &lt;em&gt;/root/.bashrc&lt;/em&gt; y &lt;em&gt;/etc/skel/.bashrc&lt;/em&gt; agregamos:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="k"&gt;if &lt;/span&gt;groups | grep -q rvm ; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="k"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;source&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/usr/local/lib/rvm&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Ahora también tenemos un grupo llamado &lt;strong&gt;RVM&lt;/strong&gt; y necesitamos agregar nuestro usuario al mismo:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;adduser malev rvm&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Otra buena práctica es definir el &lt;strong&gt;environment&lt;/strong&gt; para todas nuestras aplicaciones Rails. En el archivo &lt;em&gt;/etc/environment&lt;/em&gt; agregamos:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;RAILS_ENV=production&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Aquí yo me deslogueo y vuelvo a entrar, pero esta vez como malev y al tipear:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;type rvm | head -n1&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;debería ver: &lt;strong&gt;rvm is a function&lt;/strong&gt;, lo cual me indica que RVM está correctamente instalado.&lt;/p&gt;

&lt;h2&gt;Avanzando&lt;/h2&gt;

&lt;p&gt;Yo estoy usando una distro basada en CentOS, así que para instalar las librerías de desarrollo tengo que hacer:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;sudo yum groupinstall "Development Tools"&lt;/p&gt;

&lt;p&gt;sudo yum install kernel-devel kernel-headers&lt;/p&gt;

&lt;p&gt;sudo yum install openssl-devel libcurl-devel ImageMagick httpd-devel ruby-libs zlib-devel libjpeg-devel giflib-devel readline-devel&lt;/p&gt;

&lt;p&gt;sudo yum -y install libpcap libpcap-devel libnet libnet-devel pcre pcre-devel gcc automake autoconf libtool make gcc-c++ libyaml libyaml-devel zlib zlib-devel pkgconfig ruby-devel libxml2 libxml2-devel libxslt libxslt-devel&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Si estas usando Ubuntu, hay MUCHA info sobre que instalar en este paso, pero en ppio bastaría con esto:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;sudo apt-get install build-essential ruby-full libmagickcore-dev imagemagick libxml2-dev libxslt1-dev git-core ruby-devel libxml2 libxml2-devel libxslt libxslt-devel&lt;/p&gt;&lt;/blockquote&gt;

&lt;h2&gt;Instalando Ruby&lt;/h2&gt;

&lt;blockquote&gt;&lt;p&gt;rvm pkg install readline&lt;/p&gt;

&lt;p&gt;rvm pkg install zlib&lt;/p&gt;

&lt;p&gt;rvm pkg install openssl&lt;/p&gt;

&lt;p&gt;rvm install 1.9.2&lt;/p&gt;

&lt;p&gt;rvm use --default 1.9.2&lt;/p&gt;&lt;/blockquote&gt;

&lt;h2&gt;Instalando Passenger&lt;/h2&gt;

&lt;blockquote&gt;&lt;p&gt;gem install passenger&lt;/p&gt;

&lt;p&gt;rvmsudo passenger-install-nginx-module&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Si lo instalaste en el directorio por defecto (&lt;em&gt;/opt/nginx&lt;/em&gt;), clonate este &lt;a href="https://gist.github.com/1918419"&gt;gist&lt;/a&gt; y copia el archivo &lt;strong&gt;nginx&lt;/strong&gt; en &lt;em&gt;/etc/init.d&lt;/em&gt; con permisos de ejecución.&lt;/p&gt;

&lt;h2&gt;Configurar Nginx&lt;/h2&gt;

&lt;p&gt;Buscar el archivo &lt;em&gt;/opt/nginx/conf/nginx.conf&lt;/em&gt; que debería verse más o menos como este &lt;a href="https://gist.github.com/1918436"&gt;gist&lt;/a&gt;. Las líneas más importantes son la 1 donde digo con qué usuario ejecutar nginx y la 22 donde establezco dónde ubicaré el resto de los archivos de configuración.&lt;/p&gt;

&lt;h2&gt;Instalar nuestra app&lt;/h2&gt;

&lt;p&gt;En mi caso voy a instalar una app llamada infofund. Y voy a deployar con &lt;em&gt;capistrano&lt;/em&gt;, pero las explicaciones de cómo usar &lt;em&gt;capistrano&lt;/em&gt; vendrán en otro post. De momento les dejo el archivo &lt;em&gt;/opt/nginx/conf/conf.d/infofund.conf&lt;/em&gt; cuyo contenido está en este &lt;a href="https://gist.github.com/2339504"&gt;gist&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;En principio y como para probar pueden bajarse el contenido del proyecto en el directorio &lt;em&gt;/home/malev/sites/infofund/current&lt;/em&gt;, crear el Gemset e instalar todas las gemas con nuestro amigo &lt;strong&gt;bundle&lt;/strong&gt; para luego iniciar &lt;strong&gt;nginx&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;sudo /etc/init.d/nginx start&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;y ya debería estar todo andando!&lt;/p&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;https://rvm.beginrescueend.com/rvm/install/#explained&lt;/li&gt;
&lt;li&gt;http://thekindofme.wordpress.com/2010/10/24/rails-3-on-ubuntu-10-10-with-rvm-passenger-and-nginx/&lt;/li&gt;
&lt;li&gt;https://rvm.beginrescueend.com/rvm/install/#explained&lt;/li&gt;
&lt;li&gt;http://ikennaokpala.wordpress.com/2011/12/27/deployment-strategy-for-rails-passenger-and-nginx-server-with-multiple-virtual-hosts/&lt;/li&gt;
&lt;li&gt;http://blog.ninjahideout.com/posts/a-guide-to-a-nginx-passenger-and-rvm-server&lt;/li&gt;
&lt;li&gt;http://kris.me.uk/2010/08/30/rails3-hosting-all-in-one.html&lt;/li&gt;
&lt;/ol&gt;

</content>
 </entry>
 
 <entry>
   <title>Mustache</title>
   <link href="http://malev.com.ar/mustache" />
   <updated>2012-03-04T00:00:00-03:00</updated>
   <id>http://malev.com.ar/mustache</id>
   <content type="html">&lt;h1&gt;Mustache&lt;/h1&gt;

&lt;p&gt;Hasta hace no mucho tiempo, cada vez que tenía que dibujar algún HTML con AJAX hacía que rails lo dibuje y después lo pegaba con alguna función jQuery. Algo así:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
  &lt;span class="vi"&gt;@review&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Review&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:review&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;flash&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:notice&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Thank you for reviewing this product&amp;quot;&lt;/span&gt;
  &lt;span class="n"&gt;respond_to&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="vi"&gt;@review&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;js&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Mientras que en algún lugar de la carpeta &lt;em&gt;views&lt;/em&gt; tenía:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;#reviews&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;lt;%= escape_javascript(render(:partial =&amp;gt; @review)) %&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Pero eso es el pasado! ¿Por qué hacer trabajar al server para dibujar un HTML is tranquilamente lo puede hacer el cliente? Porque no conocía &lt;a href="http://mustache.github.com/"&gt;Mustache&lt;/a&gt;, un lenguje te de &lt;strong&gt;templates&lt;/strong&gt; muy parecido a jinja.&lt;/p&gt;

&lt;h2&gt;¿Cuál es el plan?&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Hacer un request AJAX desde el cliente.&lt;/li&gt;
&lt;li&gt;El servidor busca / procesa los datos.&lt;/li&gt;
&lt;li&gt;El servidor devuelve Json.&lt;/li&gt;
&lt;li&gt;El cliente interpreta el Json y Mustache dibuja el HTML en base al template.&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;Ejemplo&lt;/h2&gt;

&lt;script src="https://gist.github.com/1967208.js"&gt; &lt;/script&gt;


&lt;p&gt;y eso nos daría como resultado:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Colors&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;&lt;/span&gt;red&lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#Green&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;green&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#Blue&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;blue&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;En lo personal la sintaxis no me parece la mejor, es un poco confuso que &lt;strong&gt;{{#items}}&lt;/strong&gt; y &lt;strong&gt;{{/items}}&lt;/strong&gt; se puedan usar para iterar y para condicionales. Y para pasar funciones similares a los &lt;strong&gt;helpers&lt;/strong&gt; de &lt;strong&gt;Rails&lt;/strong&gt; necesitamos pasarle un &lt;strong&gt;clousure&lt;/strong&gt;:&lt;/p&gt;

&lt;script src="https://gist.github.com/1967225.js"&gt; &lt;/script&gt;


&lt;p&gt;Por último, también nos permite el uso de &lt;strong&gt;partials&lt;/strong&gt; para fomentar el reuso y si no queremos tener todo nuestro template en Strings de Javascript, podemos encerrarlo en:&lt;/p&gt;

&lt;script src="https://gist.github.com/1967260.js"&gt; &lt;/script&gt;


&lt;p&gt;Y luego lo recuperamos con:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="nx"&gt;Mustache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;#template&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Lo cual nos permite esconder los templates dentro del mismo archivo HTML.&lt;/p&gt;

&lt;h2&gt;Contras&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Usa la misma sintaxis que Jinja, es decir en Django vamos a tener muchos muchos problemas.&lt;/li&gt;
&lt;li&gt;Fomenta la duplicación de código del template (el que se reenderea desde el server y el del cliente).&lt;/li&gt;
&lt;li&gt;La sintaxis no es del todo clara.&lt;/li&gt;
&lt;li&gt;No está bueno como maneja los helpers.&lt;/li&gt;
&lt;li&gt;Es adictivo.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;http://mustache.github.com/&lt;/li&gt;
&lt;li&gt;http://mustache.github.com/mustache.5.html&lt;/li&gt;
&lt;li&gt;http://mustache.github.com/mustache.1.html&lt;/li&gt;
&lt;li&gt;http://railscasts.com/episodes/295-sharing-mustache-templates&lt;/li&gt;
&lt;li&gt;http://net.tutsplus.com/tutorials/javascript-ajax/quick-tip-using-the-mustache-template-library/&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Nota&lt;/h2&gt;

&lt;p&gt;No es la única opción si necesitamos un parser de templates en &lt;strong&gt;Javascrpt&lt;/strong&gt;, existen varios otros entre los cuales yo destaco &lt;a href="http://handlebarsjs.com/"&gt;handlebars&lt;/a&gt;, del cual pienso hablar en un próximo post.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>About the new design</title>
   <link href="http://malev.com.ar/about-the-new-design" />
   <updated>2012-02-28T00:00:00-03:00</updated>
   <id>http://malev.com.ar/about-the-new-design</id>
   <content type="html">&lt;h1&gt;About the new design&lt;/h1&gt;

&lt;p&gt;¿Por qué cambié? Por varias razones: sentía que luego de 3 años algo tenía que cambiar y el diseño anterior ya no me cerraba. También me había cansado un poco de Wordpress (lo sigo bancando) y encima había visto esta nueva herramienta: &lt;strong&gt;Jekyll&lt;/strong&gt;. También leí el &lt;a href="http://gettingreal.37signals.com/ch09_Epicenter_Design.php"&gt;artículo sobre diseño&lt;/a&gt; de &lt;a href="http://gettingreal.37signals.com/toc.php"&gt;Getting Real&lt;/a&gt; y sus argumentos me convencieron y para colmo, el Sr. &lt;a href="http://twitter.com/hugoruscitti"&gt;Hugo&lt;/a&gt; me hizo llegar estos posts: &lt;a href="http://www.smashingmagazine.com/the-death-of-the-blog-post/"&gt;uno&lt;/a&gt; y &lt;a href="http://iampaddy.com/lifebelow600/"&gt;dos&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Al final me dije: hora de dar vuelta el blog! Busqué una fuente más divertida y más grande 2 colores y listo!
Por supuesto ahora estoy usando &lt;a href="https://github.com/mojombo/jekyll"&gt;Jekyll&lt;/a&gt; y debo decir que migrar mi blog de wordpress a Jekyll fue un desafío por demás de interesante.&lt;/p&gt;

&lt;p&gt;Otra vez, no está terminado, quiero agregarle publicidad y en ese plano me interesa mucho el enfoque de &lt;a href="http://www.taniquetil.com.ar/plog/post/1/482"&gt;Facu&lt;/a&gt; y seguramente alguna que otra cosilla por ahí.&lt;/p&gt;

&lt;p&gt;P/D: Bloggear con &lt;strong&gt;markdown&lt;/strong&gt; es lo más!!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>New blog styles</title>
   <link href="http://malev.com.ar/new-blog-styles" />
   <updated>2012-02-27T00:00:00-03:00</updated>
   <id>http://malev.com.ar/new-blog-styles</id>
   <content type="html">&lt;h1&gt;New blog styles&lt;/h1&gt;

&lt;p&gt;Así es! después de tanto tiempo me decidí y arreglé los estilos del blog! Ahora está más limpio, con letras más grandes y haciendo eje en el post que es el corazón del blog. Espero les guste!
Por supuesto, ahora me planteo escribir más seguido jeje&lt;/p&gt;

&lt;p&gt;saludos!&lt;/p&gt;

&lt;p&gt;Ojo! no está terminado, todavía lo puedo contaminar un poco más con redes sociales y tal vez publicidad (no estoy del todo decidido pues hasta ahora no gane un solo centavo real).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>MongoDB con Mongoid</title>
   <link href="http://malev.com.ar/mongodb-con-mongoid" />
   <updated>2011-11-09T00:00:00-03:00</updated>
   <id>http://malev.com.ar/mongodb-con-mongoid</id>
   <content type="html">&lt;h1&gt;MongoDB con Mongoid&lt;/h1&gt;

&lt;p&gt;Estoy en la &lt;a href="http://rubyconfargentina.org/"&gt;RubyConfArg&lt;/a&gt;, y hace unos minutos pasaron las LightTalks, en las que por suerte pude hablar sobre Mongoid, un ODM para MongoDB que cumple muy bien con su filosofía propuesta:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;The philosophy of Mongoid is to provide a familiar API to Ruby developers who have been using Active Record or Data Mapper, while leveraging the power of MongoDB's schemaless and performant document-based design, dynamic queries, and atomic modifier operations.
Aquí les dejo la presentación, cuando tenga fotos las subo.&lt;/p&gt;&lt;/blockquote&gt;

&lt;div style="width:425px" id="__ss_10091274"&gt;&lt;iframe src="http://www.slideshare.net/slideshow/embed_code/10091274" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"&gt;&lt;/iframe&gt;
View more presentations from [malev](http://www.slideshare.net/malev) &lt;/div&gt;

</content>
 </entry>
 
 <entry>
   <title>gemsets are the awesomeness</title>
   <link href="http://malev.com.ar/gemsets-are-the-awesomeness" />
   <updated>2011-11-09T00:00:00-03:00</updated>
   <id>http://malev.com.ar/gemsets-are-the-awesomeness</id>
   <content type="html">&lt;h1&gt;gemsets are the awesomeness&lt;/h1&gt;

&lt;p&gt;Cada vez que tenía que usar un proyecto con python, empezaba creando un ambiente particular con virtualenv. En ruby, en principio no podía hacer eso. Después conocí RVM y trabajaba con varias versiones de Ruby en mi PC, sobre todo para trabajar algunos proyectos legacy. Sin embargo, tenía un popurrí de gemas instaladas que ya empezaban a conflictuarse entre sí. Apareció bundler y su magia de &lt;strong&gt;bundle exec&lt;/strong&gt; para solucionar muchos problemas (nota: en futuras versiones de bundler esto ya no va a hacer falta). En fin, la ensalada de gemas seguí ahí, hasta que por fin conocí &lt;strong&gt;gemset&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blog.malev.com.ar/wp-content/uploads/2011/11/logo.png"&gt;&lt;img src="/images/posts/2011/11/logo.png" title="rvm" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mi workflow es más o menos así:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="err"&gt;➜&lt;/span&gt;  &lt;span class="o"&gt;~&lt;/span&gt;  &lt;span class="n"&gt;cd&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; 
&lt;span class="err"&gt;➜&lt;/span&gt;  &lt;span class="n"&gt;code&lt;/span&gt;  &lt;span class="n"&gt;mkdir&lt;/span&gt; &lt;span class="n"&gt;proyecto_nuevo&lt;/span&gt;
&lt;span class="err"&gt;➜&lt;/span&gt;  &lt;span class="n"&gt;code&lt;/span&gt;  &lt;span class="n"&gt;cd&lt;/span&gt; &lt;span class="n"&gt;proyecto_nuevo&lt;/span&gt; 
&lt;span class="err"&gt;➜&lt;/span&gt;  &lt;span class="n"&gt;proyecto_nuevo&lt;/span&gt;  &lt;span class="n"&gt;rvm&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="n"&gt;malev&lt;/span&gt;&lt;span class="vi"&gt;@proyecto_nuevo&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;rvmrc&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;
&lt;span class="no"&gt;Using&lt;/span&gt;&lt;span class="sr"&gt; /home/m&lt;/span&gt;&lt;span class="n"&gt;alev&lt;/span&gt;&lt;span class="o"&gt;/.&lt;/span&gt;&lt;span class="n"&gt;rvm&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;gems&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ruby&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p290&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;gemset&lt;/span&gt; &lt;span class="n"&gt;proyecto_nuevo&lt;/span&gt;
&lt;span class="no"&gt;WARN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rvmrc&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;moving&lt;/span&gt; &lt;span class="n"&gt;aside&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;preserve&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="err"&gt;➜&lt;/span&gt;  &lt;span class="n"&gt;proyecto_nuevo&lt;/span&gt;  &lt;span class="n"&gt;rvm&lt;/span&gt; &lt;span class="n"&gt;gemset&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;

&lt;span class="n"&gt;gemsets&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ruby&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p290&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;found&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="sr"&gt; /home/m&lt;/span&gt;&lt;span class="n"&gt;alev&lt;/span&gt;&lt;span class="o"&gt;/.&lt;/span&gt;&lt;span class="n"&gt;rvm&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;gems&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ruby&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p290&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;global&lt;/span&gt;
   &lt;span class="n"&gt;mobilenews&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;proyecto_nuevo&lt;/span&gt;
   &lt;span class="n"&gt;webui&lt;/span&gt;

&lt;span class="err"&gt;➜&lt;/span&gt;  &lt;span class="n"&gt;proyecto_nuevo&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Es decir, voy a mi directorio donde guardo mis proyectos / experimentos, creo un directorio, creo un nuevo gemset y listo! Todas las &lt;strong&gt;gems&lt;/strong&gt; que instale en ese &lt;strong&gt;gemset&lt;/strong&gt; van a estar aisladas del resto.
Lo interesante es que gracias a la magia de &lt;strong&gt;rvm&lt;/strong&gt;, cada vez que entre en el directorio de mi proyecto nuevo, &lt;strong&gt;rvm&lt;/strong&gt; me va a cambiar al &lt;strong&gt;gemset&lt;/strong&gt; ahí usado:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="err"&gt;➜&lt;/span&gt;  &lt;span class="n"&gt;code&lt;/span&gt;  &lt;span class="n"&gt;pwd&lt;/span&gt;&lt;span class="sr"&gt;&lt;/span&gt;
&lt;span class="sr"&gt;/home/m&lt;/span&gt;&lt;span class="n"&gt;alev&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;
&lt;span class="err"&gt;➜&lt;/span&gt;  &lt;span class="n"&gt;code&lt;/span&gt;  &lt;span class="n"&gt;rvm&lt;/span&gt; &lt;span class="n"&gt;gemset&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;

&lt;span class="n"&gt;gemsets&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ruby&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p290&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;found&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="sr"&gt; /home/m&lt;/span&gt;&lt;span class="n"&gt;alev&lt;/span&gt;&lt;span class="o"&gt;/.&lt;/span&gt;&lt;span class="n"&gt;rvm&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;gems&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ruby&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p290&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;global&lt;/span&gt;
   &lt;span class="n"&gt;mobilenews&lt;/span&gt;
   &lt;span class="n"&gt;proyecto_nuevo&lt;/span&gt;
   &lt;span class="n"&gt;webui&lt;/span&gt;

&lt;span class="err"&gt;➜&lt;/span&gt;  &lt;span class="n"&gt;code&lt;/span&gt;  &lt;span class="n"&gt;cd&lt;/span&gt; &lt;span class="n"&gt;proyecto_nuevo&lt;/span&gt; 
&lt;span class="o"&gt;=========================================================&lt;/span&gt;
&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;NOTICE&lt;/span&gt;                                                                     &lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="o"&gt;=========================================================&lt;/span&gt;
&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;RVM&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;encountered&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="kp"&gt;new&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;modified&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rvmrc&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="n"&gt;directory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;This&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;shell&lt;/span&gt; &lt;span class="n"&gt;script&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;therefore&lt;/span&gt; &lt;span class="n"&gt;may&lt;/span&gt; &lt;span class="n"&gt;contain&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt; &lt;span class="n"&gt;shell&lt;/span&gt; &lt;span class="n"&gt;commands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="o"&gt;=&lt;/span&gt;                                                                            &lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Examine&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;contents&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="n"&gt;carefully&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;sure&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;contents&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;safe&lt;/span&gt; &lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="n"&gt;trusting&lt;/span&gt; &lt;span class="n"&gt;it!&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="no"&gt;Choose&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;iew&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;below&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;contents&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="o"&gt;=========================================================&lt;/span&gt;
&lt;span class="no"&gt;Do&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="n"&gt;wish&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;trust&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rvmrc&lt;/span&gt; &lt;span class="n"&gt;file?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/home/m&lt;/span&gt;&lt;span class="n"&gt;alev&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;proyecto_nuevo&lt;/span&gt;&lt;span class="o"&gt;/.&lt;/span&gt;&lt;span class="n"&gt;rvmrc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;es&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;iew&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ancel&lt;/span&gt;&lt;span class="o"&gt;]&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;yes&lt;/span&gt;
&lt;span class="err"&gt;➜&lt;/span&gt;  &lt;span class="n"&gt;proyecto_nuevo&lt;/span&gt;  &lt;span class="n"&gt;rvm&lt;/span&gt; &lt;span class="n"&gt;gemset&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;

&lt;span class="n"&gt;gemsets&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ruby&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p290&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;found&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="sr"&gt; /home/m&lt;/span&gt;&lt;span class="n"&gt;alev&lt;/span&gt;&lt;span class="o"&gt;/.&lt;/span&gt;&lt;span class="n"&gt;rvm&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;gems&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ruby&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p290&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;global&lt;/span&gt;
   &lt;span class="n"&gt;mobilenews&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;proyecto_nuevo&lt;/span&gt;
   &lt;span class="n"&gt;webui&lt;/span&gt;

&lt;span class="err"&gt;➜&lt;/span&gt;  &lt;span class="n"&gt;proyecto_nuevo&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;em&gt;Si no tienes rvm instalado, corred e instaladlo por favor!&lt;/em&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Sobre callbacks en Rails</title>
   <link href="http://malev.com.ar/debates-sobre-callbacks-en-rails" />
   <updated>2011-10-27T00:00:00-03:00</updated>
   <id>http://malev.com.ar/debates-sobre-callbacks-en-rails</id>
   <content type="html">&lt;h1&gt;Sobre callbacks en Rails&lt;/h1&gt;

&lt;p&gt;¿Qué son los &lt;strong&gt;callbacks&lt;/strong&gt;? Son métodos que son llamados en determinados momentos del ciclo de vida de un objeto. Esto nos permite escribir código que se va a ejecutar cuando nuestros &lt;strong&gt;objetos&lt;/strong&gt; (&lt;strong&gt;ActiveRecord&lt;/strong&gt; u otros) son creados, grabados, actualizados, borrados, validados o cargados desde la base de datos (created, saved, updated, deleted, validated, or loaded).
Supongamos que nosotros queremos que inmediatamente después de haber creado un usuario, se cree automáticamente una cuenta para ese usuario. Podríamos hacer esto (por favor no lo intenten en sus casas, puede ser peligroso):&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsersController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
    &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@account&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="vi"&gt;@user&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Sin embargo, estaríamos contaminando nuestro &lt;strong&gt;controller&lt;/strong&gt; con lógica de modelo. Una primera aproximación, podría ser, usar un callback: after_create. Se ejecuta siempre que se crea un objeto y se lo guarda en la base por primera vez:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="c1"&gt;#...&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;after_create&lt;/span&gt;
    &lt;span class="no"&gt;Account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="c1"&gt;#...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Esta aproximación funciona y está buena, pero tiene algunos problemillas: el nombre del método no describe lo que hace y si tenemos que hacer varias cosas, tendríamos un método gigante. Aquí entran en acción el método de clase: after_create:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="c1"&gt;#...&lt;/span&gt;
  &lt;span class="n"&gt;after_create&lt;/span&gt; &lt;span class="ss"&gt;:create_account&lt;/span&gt;
  
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_account&lt;/span&gt;
    &lt;span class="no"&gt;Account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="c1"&gt;#...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Una vez creado el objeto, ActiveRecord buscará un método llamado "&lt;strong&gt;create_account&lt;/strong&gt;" y lo ejecutará. Esto nos permite tener varios métodos que se ejecuten como callbacks, he inclusive podemos llamarlos de manera secuencial:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Snippet&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;after_create&lt;/span&gt; &lt;span class="ss"&gt;:test1&lt;/span&gt;
  &lt;span class="n"&gt;after_create&lt;/span&gt; &lt;span class="ss"&gt;:test2&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test1&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;test 1&amp;quot;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test2&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;test 2&amp;quot;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;y los resultados:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="n"&gt;ruby&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p136&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;002&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Snippet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;#&amp;lt;Snippet id: nil, content: nil, user_id: nil... private: false&amp;gt; &lt;/span&gt;
&lt;span class="n"&gt;ruby&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p136&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;003&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;
&lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt; 
&lt;span class="n"&gt;ruby&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p136&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;004&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Por supuesto, after_create no es el único callback. Hay mucha información al respecto &lt;a href="http://guides.rubyonrails.org/active_record_validations_callbacks.html#callbacks-overview"&gt;aquí&lt;/a&gt;. Aquí solo voy a listar los callbacks disponibles:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creando un objeto&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;before_validation&lt;/li&gt;
&lt;li&gt;after_validation&lt;/li&gt;
&lt;li&gt;before_save&lt;/li&gt;
&lt;li&gt;before_create&lt;/li&gt;
&lt;li&gt;around_create&lt;/li&gt;
&lt;li&gt;after_create&lt;/li&gt;
&lt;li&gt;after_save&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;strong&gt;Actualizando un objeto&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;before_validation&lt;/li&gt;
&lt;li&gt;after_validation&lt;/li&gt;
&lt;li&gt;before_save&lt;/li&gt;
&lt;li&gt;before_update&lt;/li&gt;
&lt;li&gt;around_update&lt;/li&gt;
&lt;li&gt;after_update&lt;/li&gt;
&lt;li&gt;after_save&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;strong&gt;Eliminando un objeto&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;before_destroy&lt;/li&gt;
&lt;li&gt;after_destroy&lt;/li&gt;
&lt;li&gt;around_destroy&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Su uso es ampliamente recomendable y una cosa a tener en cuenta es... no podemos evitarlos! No son como las validaciones, en las que a veces podemos no ejecutarlas. Aquí si alguna vez necesitamos saltearlos algún callback, vamos a tener que repensar la lógica del modelo de vuelta. Usar con responsabilidad.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Agile testing</title>
   <link href="http://malev.com.ar/agile-testing" />
   <updated>2011-10-26T00:00:00-03:00</updated>
   <id>http://malev.com.ar/agile-testing</id>
   <content type="html">&lt;h1&gt;Agile testing&lt;/h1&gt;

&lt;p&gt;En mi trabajo nuevo, los equipos de desarrollo cuentan con gente de &lt;strong&gt;QA&lt;/strong&gt;, lxs &lt;strong&gt;Quality Assurance&lt;/strong&gt;. Y debo decir, es fantástico trabajar con gente que continuamente este viendo la calidad desde el punto de vista del usuario. Quizás no sea toda la calidad como nos gusta a nosotros (no abarcan todos los atributos de calidad de la &lt;a href="http://es.wikipedia.org/wiki/ISO/IEC_9126"&gt;ISO9126&lt;/a&gt;), pero es algo y ese algo es muy importante. Sin embargo, no todo es alegría y felicidad entre el quipo de desarrollo y el quipo de QA, aunque ambos esten en el mismo equipo, pero bueno. Uno de los principales choques que vivimos apenas se conformo el equipo (voy a seguir diciendo equipo muchas veces más) fue el choque entre &lt;strong&gt;Agile&lt;/strong&gt; y &lt;strong&gt;Waterfall&lt;/strong&gt; (o lo que sea que ellos usaban). Al principio costo mucho mezclar gente ágil (los desarrolladores) con gente que venía de procesos más rígidos (claramente la gente de QA). Esto sigue siendo un punto a resolver, pero el trabajo se da cada vez más natural. Si Uds, tienen un problema similar en sus organizaciones, les recomiendo este video de Google IO, donde &lt;a href="http://testobsessed.com/"&gt;Elisabeth Hendrickson&lt;/a&gt;, una alta tester de Quality Tree nos cuenta su experiencia de testing en equipo ágiles.&lt;/p&gt;

&lt;p&gt;&lt;embed id="VideoPlayback" src="http://video.google.com/googleplayer.swf?docid=-3054974855576235846&amp;hl=en&amp;fs=true" style="width:400px;height:326px" allowfullscreen="true" allowscriptaccess="always" type="application/x-shockwave-flash"&gt; &lt;/embed&gt;&lt;/p&gt;

&lt;p&gt;Yo mientras voy a seguir investigando del tema, si encuentro algo más, prometo publicarlo.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AsÃ­ es, di una charla en PyConAr 2011</title>
   <link href="http://malev.com.ar/asi-es-di-una-charla-en-pyconar-2011" />
   <updated>2011-10-17T00:00:00-03:00</updated>
   <id>http://malev.com.ar/asi-es-di-una-charla-en-pyconar-2011</id>
   <content type="html">&lt;h1&gt;AsÃ­ es, di una charla en PyConAr 2011&lt;/h1&gt;

&lt;p&gt;Así es, me anime, mande y me aceptaron. Buena onda! Este año por fin pude dar una charla en una PyCon y gracias a la experiencia en charlas anteriores como &lt;a href="http://blog.malev.com.ar/2011/07/26/y-paso-el-pyday-gonzalez-catan/"&gt;esta&lt;/a&gt;, la última no me salio tan mal :) Tuve un público receptivo que inclusive se animó a participar.
La charla fue sobre introducción al desarrollo web, pero desde el principio. Vi muchas charlas sobre introducción a Django o Rails o Web2Py que demandaban bastante conocimiento previo, bueno, fue este conocimiento previo que yo aborde en mi charla. Desde que es un servidor, HTML, Javascript, etc hasta una mini mini aplicación web hecha en &lt;a href="http://bottlepy.org/docs/dev/"&gt;Bottle&lt;/a&gt;. ¿Por qué Bottle? Justamente porque su simpleza y porque se enfoca en la web unicamente. No tiene ORM ni nada, pero para una introducción me pareció genial.
Aquí les dejo las diapositivas y más fotos (incluyendo la del super cuchillo que me regalo la organización)&lt;/p&gt;

&lt;div style="width:425px" id="__ss_9632998"&gt;
  &lt;object id="__sse9632998" width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introalaweb-111010113659-phpapp02&amp;stripped_title=introduccin-al-desarrollo-web&amp;userName=malev" /&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;param name="allowScriptAccess" value="always" /&gt;&lt;embed name="__sse9632998" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introalaweb-111010113659-phpapp02&amp;stripped_title=introduccin-al-desarrollo-web&amp;userName=malev" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;
&lt;/div&gt;


&lt;p&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/malev"&gt;malev&lt;/a&gt;.
Nota: ninguna foto es mía, las robe de muchos sitios, espero nadie se enoje.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Paso PyCon 2011</title>
   <link href="http://malev.com.ar/pycon-2011" />
   <updated>2011-10-11T00:00:00-03:00</updated>
   <id>http://malev.com.ar/pycon-2011</id>
   <content type="html">&lt;h1&gt;Paso PyCon 2011&lt;/h1&gt;

&lt;p&gt;Con un delay importante les cuento que paso PyCon Argentina 2011. Así es, el 23 y 24 de setiembre, gran parte de la comunidad hacker invadió Junín (provincia de Buenos Aires). Por supuesto estuve ahí.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blog.malev.com.ar/wp-content/uploads/2011/10/pyconar2011.png"&gt;&lt;img src="/images/posts/2011/10/pyconar2011.png" title="pyconar2011" alt="pyconar2011" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como siempre, la muy buena onda de la &lt;a href="http://blog.malev.com.ar/category/comunidad/"&gt;comunidad&lt;/a&gt; de python garantizó y cumplió con 2 días espectaculares. Hubo de todo, charlas de muy alto nivel, oradores locales e internacionales, conocí Google App Engine, obtuve consejos sobre &lt;a href="http://jbcabral.wordpress.com/2011/09/24/slides-de-mis-charlas-de-pyconar-2011/"&gt;como crear librerías&lt;/a&gt; y sobre TDD con python y mucho más. Las visitas internacionales, un verdadero lujo y hasta nos mando un saludo &lt;a href="http://es.wikipedia.org/wiki/Guido_van_Rossum"&gt;Guido van Rossum&lt;/a&gt; desde Londres.
No recuerdo el nombre, pero uno de los pibes Canonical me dio una mano sobre como configurar Launchpad para un aplicación que estoy haciendo (más adelante les comento que tal). Por último, también pude dar una charla, de la que hablare en otro post.
Solo una conclusión: &lt;strong&gt;Increíble!&lt;/strong&gt; y vayan guardando un lugar para mi en la próxima (todavía no sabemos donde va a ser).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Book Review: The Clean Coder</title>
   <link href="http://malev.com.ar/book-review-the-clean-coder" />
   <updated>2011-07-28T00:00:00-03:00</updated>
   <id>http://malev.com.ar/book-review-the-clean-coder</id>
   <content type="html">&lt;h1&gt;Book Review: The Clean Coder&lt;/h1&gt;

&lt;p&gt;Hace un par de semanas, luego de ver &lt;a href="http://youtu.be/mslMLp5bQD0"&gt;este&lt;/a&gt; video (que por cierto recomiendo mucho) me entere que &lt;a href="http://twitter.com/#!/unclebobmartin"&gt;Robert Martin&lt;/a&gt; (aka Uncle Bob) había publicado un libro llamado The Clean Coder: A Code of Conduct for Professional Programmers. Un código de conducta! Y eso, por supuesto me llamo profundamente la atención. Una semana después de "comprarlo" en &lt;a href="http://www.amazon.com/Clean-Coder-Conduct-Professional-Programmers/dp/0137081073"&gt;Amazon&lt;/a&gt; ya lo había leído y hoy voy a escribir acerca del mismo.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blog.malev.com.ar/wp-content/uploads/2011/07/51BSQqef+6L._SL500_AA300_.jpg"&gt;&lt;img src="/images/posts/2011/07/51BSQqef+6L._SL500_AA300_.jpg" title="The clean coder" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El libro está escrito en un lenguaje "piola", de lectura fácil y sin cosas rebuscadas. Por supuesto no contiene detalles técnicos, ya que no es un libro técnico, pero si mucha mucha experiencia encima y eso me gustó mucho. En lo personal me sentí muy identificado con el libro, el capítulo "saying No". Me gusto mucho como trato el tema de las estimaciones, por supuesto, siendo Bob uno de los firmantes del &lt;a href="http://agilemanifesto.org/"&gt;Agile Manifesto&lt;/a&gt;, todo está visto desde un enfoque agile. También destaco el capítulo sobre como practicar programación con los Katas, etc. Yo desconocía acerca de esas prácticas.
El libro en general me pareció más que recomendable para cualquiera que trabaje con desarrollo de software, diría que es obligatorio (is a must). No se si estoy del todo de acuerdo con el tema de "avoid the zone" o con el tema de capacitación. Explico un poco: Cuando programamos y nos concentramos mucho, por ahí entramos en una fase en la que el código parece fluir de los dedos de manera natural, se podría decir el momento de máxima concentración y producción. Este momento según Bob es conocido como "the zone" y justamente lo que no me termina de cerrar es el: "eviten la zona". Por supuesto, viene con justificaciones, pero igual, no me terminan de convencer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Con todo el libro es genial y lo recomiendo 100%.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;BTW, aquí está el video que video que les comente.&lt;/p&gt;

&lt;iframe width="560" height="349" src="http://www.youtube.com/embed/mslMLp5bQD0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

</content>
 </entry>
 
 <entry>
   <title>Y paso el PyDay Gonzalez Catan</title>
   <link href="http://malev.com.ar/y-paso-el-pyday-gonzalez-catan" />
   <updated>2011-07-26T00:00:00-03:00</updated>
   <id>http://malev.com.ar/y-paso-el-pyday-gonzalez-catan</id>
   <content type="html">&lt;h1&gt;Y paso el PyDay Gonzalez Catan&lt;/h1&gt;

&lt;p&gt;Como les había comentado hace unos días &lt;a href="http://blog.malev.com.ar/2011/06/15/pyday-en-gonzales-catan/"&gt;atrás&lt;/a&gt;. El sábado pasado (16/07/11) asistí al PyDay González Catán. El evento me gustó mucho! Los organizadores se re portaron y a los disertantes (sí hable de un tema) nos mimaron bastante. Hay fotos del evento en el &lt;a href="http://www.pyday.com.ar/catan2011"&gt;sitio del mismo&lt;/a&gt; y yo aquí posteo 2 en las que salgo yo jeje.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blog.malev.com.ar/wp-content/uploads/2011/07/0.jpg"&gt;
&lt;img src="/images/posts/2011/07/0.jpg" title="PyDay Gonzalez Catan" alt="Organizadores y desertantes" /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Y una durante mi charla que me saco &lt;a href="http://twitter.com/felipelerena"&gt;lipe&lt;/a&gt;.
&lt;a href="http://blog.malev.com.ar/wp-content/uploads/2011/07/347964781.jpg"&gt;
&lt;img src="/images/posts/2011/07/347964781.jpg" title="PyDay Gonzalez Catan" alt="PyDay Gonzalez Catan" /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La charla que di se titula Modelo de Objetos con Python, salió bien, pero podría haber salido mejor, creo que tengo que practicar un poco más. De todos modos, aquí dejo las diapositivas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://talks.malev.com.ar/modelo-objetos-python.html"&gt;http://talks.malev.com.ar/modelo-objetos-python.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://blog.malev.com.ar/wp-content/uploads/2011/07/modelo_de_objetos_de_python.odp"&gt;http://blog.malev.com.ar/wp-content/uploads/2011/07/modelo_de_objetos_de_python.odp&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Por último, algunas de las charlas fueron filmadas, aquí los videos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://blip.tv/reingart/experiencia-materia-algor%C3%ADtmos-i-con-python-en-fiuba-5388946"&gt;Experiencia de la materia algoritmos con python&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://blip.tv/reingart/cooperativas-econom%C3%ADa-social-y-software-libre-5389238"&gt;Cooperativas, economía social y software libre&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://blip.tv/reingart/maquina-de-voto-electr%C3%B3nico-y-sistema-de-recuento-con-ubuntu-python-y-postgresql-"&gt;Maquina de voto electrónico&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 <entry>
   <title>Torneos de programaciÃ³n</title>
   <link href="http://malev.com.ar/torneos-de-programacion" />
   <updated>2011-07-11T00:00:00-03:00</updated>
   <id>http://malev.com.ar/torneos-de-programacion</id>
   <content type="html">&lt;h1&gt;Torneos de programaciÃ³n&lt;/h1&gt;

&lt;p&gt;Varias &lt;strong&gt;comunidades de software libre&lt;/strong&gt; que promocionan distintos lenguajes de programación suelen organizar &lt;strong&gt;torneos de programación&lt;/strong&gt;. Con el fin de promocionar el lenguaje o plataforma, innovar con tecnologías nuevas o simplemente &lt;strong&gt;divertirse&lt;/strong&gt;. Tienen una línea común, un grupo o una única persona debe desarrollar una aplicación desde cero en un tiempo fijo y luego, la comunidad o un grupo de personas votan y eligen la aplicación ganadora.
Existen torneos de lo más variados y para todos los gustos. Aquí voy a nombrar algunos relacionados con los lenguajes que suelo usar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://www.pyweek.org/"&gt;PyWeek&lt;/a&gt;: Quizás uno de los más viejos, la idea es desarrollar un juego en una semana. El torneo se larga 2 veces por año y dura una semana de desarrollo. Parece muy muy divertido y por supuesto sus concursantes usan &lt;strong&gt;python&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://railsrumble.com/"&gt;The Rails Rumble&lt;/a&gt;: La idea es construir una aplicación web usando &lt;strong&gt;Ruby on Rails&lt;/strong&gt; en 48hs. Más que interesante y en la página se pueden ver algunas de las aplicaciones que salieron durante este concurso y la verdad que muchas sorprenden de lo buenas que estan.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://djangodash.com"&gt;Django dash&lt;/a&gt;: Muy similar a la anterior, pero aquí tenemos que usar &lt;strong&gt;django&lt;/strong&gt;. Esta larga en este mes, por si les interesa y también cuenta con un listado enorme de aplicaciones que realizaron los concursantes en torneos anteriores.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Hasta aquí con los concursos en inglés.
La gente que está organizando la &lt;a href="http://ar.pycon.org/2011"&gt;PyConAr en Junín&lt;/a&gt; (que por cierto pinta genial), proponen este año el concurso: &lt;a href="http://python.org.ar/pyar/PyConApp"&gt;PyConApp&lt;/a&gt; a realizarse en la misma &lt;strong&gt;PyCon&lt;/strong&gt; en vivo! El objetivo es construir una aplicación en &lt;strong&gt;python&lt;/strong&gt; en 3hs en grupos de no más de 4 personas. La idea es más que tentadora!
El último concurso que les quiero comentar es la &lt;a href="http://rallyonrails.com/"&gt;Rally on Rails&lt;/a&gt;, organizado por miembros de la comunidad &lt;a href="http://rubysur.org/"&gt;RubySur&lt;/a&gt;. Aquí nos proponen codear toda una aplicación &lt;strong&gt;rails&lt;/strong&gt; en 48 horas con un equipo también de hasta 4 personas. Nos van a juzgar el diseño, la integridad, innovación y utilidad. Las inscripciones ya comenzaron y tenemos hasta el 16 de Julio para anotarnos.
Por último les comento que pienso participar del último listado con unos compañeros del trabajo. De ser así, voy a estar bloggeando más al respecto.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>HTML - Zen coding</title>
   <link href="http://malev.com.ar/html-zen-coding" />
   <updated>2011-06-28T00:00:00-03:00</updated>
   <id>http://malev.com.ar/html-zen-coding</id>
   <content type="html">&lt;h1&gt;HTML - Zen coding&lt;/h1&gt;

&lt;p&gt;Como habrán notado por varios de mis posts, soy bastante reacio al uso de IDEs para programar y aunque Robert Martin nos recomiende lo contrario [1], todavía no ha logrado convencerme jeje.
Bien, partiendo de que uso un editor bastante básico para codear, no hay nada más molesto que escribir HTML en el mismo. Este lenguaje tiene tags muy molestos que hay que abrirlos y cerrarlos usando los símbolos de mayor y menor. La verdad bastante doloroso. Al menos así era hasta que encontré ZenCoding [2].&lt;/p&gt;

&lt;p&gt;Zencoding es un plugin para editores que nos permite escribir HTML de una manera fantástica, por ejemplo, en nuestro editor tiramos:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;#content&lt;/strong&gt; y luego presionamos Ctrl + E y obtenemos:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;content&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Hasta aquí nada nuevo, nada que un editor con un poquito de pilas no pueda hacer, lo interesante es cuando queremos armar estructuras más complejas, por ejemplo:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ul.list&gt;li*4&lt;/strong&gt; y luego presionamos Ctrl + E y obtenemos:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;list&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Guau!! y lo mejor es que esto no es todo, hay muchos muchos ejemplos en [2] y en [3]. También hay se lo puede usar en CSS y anda en un montón de editores, si quieren ver cuántos, solo visiten [4].&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[1] &lt;a href="http://www.youtube.com/watch?v=mslMLp5bQD0"&gt;http://www.youtube.com/watch?v=mslMLp5bQD0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[2] &lt;a href="http://code.google.com/p/zen-coding/"&gt;http://code.google.com/p/zen-coding/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[3] &lt;a href="http://www.sitepoint.com/blogs/2010/05/11/how-to-code-like-a-zen-master/"&gt;http://www.sitepoint.com/blogs/2010/05/11/how-to-code-like-a-zen-master/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[4] &lt;a href="http://code.google.com/p/zen-coding/downloads/list"&gt;http://code.google.com/p/zen-coding/downloads/list&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 <entry>
   <title>Pyday en GonzÃ¡les CatÃ¡n</title>
   <link href="http://malev.com.ar/pyday-en-gonzales-catan" />
   <updated>2011-06-15T00:00:00-03:00</updated>
   <id>http://malev.com.ar/pyday-en-gonzales-catan</id>
   <content type="html">&lt;h1&gt;Pyday en GonzÃ¡les CatÃ¡n&lt;/h1&gt;

&lt;p&gt;Así es! Se viene un nuevo PyDay, creo que nunca hable del PyDay aquí, pero PyAr[1] nos dice:&lt;/p&gt;

&lt;blockquote&gt;Un PyDay es una jornada sobre el lenguaje Python de 1 día, con el formato de mini-conferencia pero un poco más simplificado y desestructurado, incluyendo en general charlas y talleres introductorios.&lt;/blockquote&gt;


&lt;p&gt;&lt;a href="http://www.pyday.com.ar/catan2011"&gt;&lt;img src="/images/posts/2011/06/logocatan-214x300.png" title="PyDay" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Este &lt;strong&gt;PyDay&lt;/strong&gt; en particular, cuyo lema es &lt;strong&gt;"Python en el mundo real"&lt;/strong&gt;, se va a realizar el día 16 de Julio de 2011 de 9 a 19hs en el Instituto Superior Tecnológico Blaise Pascal. Se verán temas como: &lt;strong&gt;Software Libre&lt;/strong&gt;, Desarrollo Web (&lt;strong&gt;web2py&lt;/strong&gt;, &lt;strong&gt;django&lt;/strong&gt;), &lt;strong&gt;Videojuegos&lt;/strong&gt;, Aplicaciones "Visuales" (&lt;strong&gt;wx&lt;/strong&gt;, &lt;strong&gt;gtk&lt;/strong&gt;, &lt;strong&gt;qt&lt;/strong&gt;), Proyectos relacionados y casos de éxito (factura electrónica, voto electrónico), Cooperativas, Economía Social y oportunidades laborales.&lt;/p&gt;

&lt;p&gt;También va a contar con la presencia de Docentes, Profesionales, Alumnos y Entusiastas de diferentes puntos del Gran Buenos Aires y de varias provincias del Interior del País.&lt;/p&gt;

&lt;p&gt;También les cuento que voy a estar presentando una charla en el mismo. La charla se titula: &lt;strong&gt;Modelo de Objetos de Python - Usos&lt;/strong&gt; y la estaré dando a las 14.00hs.&lt;/p&gt;

&lt;p&gt;Y por último, como casi todos los eventos de PyAr habrá un segmento para charlas relámpago[2], así que si se animan también pueden presentar una mini charla!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Cómo llegar?&lt;/strong&gt;
Aquí las instrucciones: &lt;a href="http://www.pyday.com.ar/catan2011/conference/venue"&gt;http://www.pyday.com.ar/catan2011/conference/venue&lt;/a&gt; y no se olviden de inscribirse antes!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[1] http://python.org.ar/pyar/PyDay&lt;/li&gt;
&lt;li&gt;[2] http://www.pyday.com.ar/catan2011/conference/lightning&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 <entry>
   <title>Objects in Javascript</title>
   <link href="http://malev.com.ar/objects-in-javascript" />
   <updated>2011-06-13T00:00:00-03:00</updated>
   <id>http://malev.com.ar/objects-in-javascript</id>
   <content type="html">&lt;h1&gt;Objects in Javascript&lt;/h1&gt;

&lt;p&gt;En una entrevista cuando buscaba trabajo me hicieron algunas preguntas teóricas acerca de &lt;strong&gt;objetos&lt;/strong&gt; (no pude responder casi ninguna), pero recuerdo una que me dejo pensando mucho tiempo: ¿Todos los lenguajes orientados a objetos tienen &lt;strong&gt;clases&lt;/strong&gt;? Yo dije que sí, pero resultó que no :( . &lt;strong&gt;Javascript&lt;/strong&gt; es justamente un lenguaje orientado a objetos que no tiene clases. Vamos a ver un poco:
&lt;strong&gt;Objetos en Javascript&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){})&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Wow todo es un objeto entonces!! (bueno, casi) También  vemos en la última línea del ejemplo que javascript cuenta con funciones anónimas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Y cómo armamos nuestros objetos?&lt;/strong&gt;
 Simple, lo obtenemos a partir del objeto "padre" &lt;strong&gt;Objetc&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Atributos:&lt;/span&gt;
&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Un método&lt;/span&gt;
&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;multiplication&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Otra forma es declarar un objeto literal&lt;/strong&gt;
Aquí vemos un ejemplo donde no solo creamos un objetos, si no que además le añadimos atributos y hasta un método.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="nx"&gt;marcosObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Marcos&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;nickname&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;malev&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;favoriteSongs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;yesterday&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;help&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="nx"&gt;talks&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;hi there, my na8me is &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Object constructor&lt;/strong&gt;
También podemos crear un objeto a partir de otro objeto constructor. Nota: por convención los objetos constructores se nombran con el primer carácter en mayúsculas.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;talk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;hi, my name is &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Volvemos a usar a keyword new&lt;/span&gt;
&lt;span class="nx"&gt;ana&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Ana&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;ana&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;talk&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Esta forma de declarar objetos funciona, pero es muy costosa en cuando a memoria. Por cada objeto que hacemos desde el constructor Person, declaramos el método talk, es decir que tenemos varios métodos talk en memoria y todos hacen lo mismo. Una mejor aproximación es añadir el método talk al prototipo de Person:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jump&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;I am jumping&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Ahora, este nuevo método "jump" estará habilitado en todos los objetos que se hayan construido a partir del constructor Person y los objetos que se construirán en el futuro. Aquí una salvedad, NO podemos agregar un método o atributo a un objeto literal de la misma manera:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="no"&gt;Rhino&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="n"&gt;release&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="mi"&gt;2010&lt;/span&gt; &lt;span class="mi"&gt;09&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;
&lt;span class="n"&gt;js&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;persona&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;object&lt;/span&gt; &lt;span class="no"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;js&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;persona&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prototype&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;js&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;uncaught&lt;/span&gt; &lt;span class="no"&gt;JavaScript&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Cannot&lt;/span&gt; &lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="n"&gt;property&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;age&amp;quot;&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;undefined&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;0&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Agregando un método o atributo a un objeto literal:&lt;/strong&gt;
Justamente lo interesante de la programación con objetos prototipados es que podemos tener objetos que se comportan de manera particular, es decir que tienen un comportamiento extra. Una forma de manejar ese tema es justamente añadiendo métodos a un objeto ya existente.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="nx"&gt;ana&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;work&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Something&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;ana&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;go&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;moving&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Closures&lt;/strong&gt;
En javascript solo las funciones pueden generar nuevos &lt;strong&gt;namescopes&lt;/strong&gt;, estas también permiten recordar los objetos que almacenan, de esta manera podemos hacer:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="nx"&gt;funciton&lt;/span&gt; &lt;span class="nx"&gt;getCounter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getCounter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// 1&lt;/span&gt;
&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;En el ejemplo vemos que estamos retornando una función. Esto es así por que en javascript las funciones son funciones de primer clase (&lt;strong&gt;first-class functions&lt;/strong&gt;), es decir son objetos con los que podemos trabajar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Cómo probar los ejemplos?&lt;/strong&gt;
En lo personal los estoy probando con la consola de javascript de Firebug en Firefox o en Rhino.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;http://mckoss.com/jscript/object.htm&lt;/li&gt;
&lt;li&gt;http://docs.jquery.com/Types#Options&lt;/li&gt;
&lt;li&gt;http://www.codeproject.com/kb/aspnet/JsOOP1.aspx&lt;/li&gt;
&lt;li&gt;http://www.crockford.com/javascript/inheritance.html&lt;/li&gt;
&lt;li&gt;http://eloquentjavascript.net/contents.html&lt;/li&gt;
&lt;li&gt;http://fingernailsinoatmeal.com/post/292301859/metaprogramming-ruby-vs-javascript&lt;/li&gt;
&lt;li&gt;http://www.youtube.com/watch?v=seX7jYI96GE&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 <entry>
   <title>Using Ruby modules in Rails</title>
   <link href="http://malev.com.ar/using-ruby-modules-in-rails" />
   <updated>2011-05-09T00:00:00-03:00</updated>
   <id>http://malev.com.ar/using-ruby-modules-in-rails</id>
   <content type="html">&lt;h1&gt;Using Ruby modules in Rails&lt;/h1&gt;

&lt;p&gt;El título quizás no sea muy feliz, porque la verdad que es que todo el tiempo estamos usando módulos en Rails. De hecho en Rails 3 podríamos decir que el génesis de cada aplicación rails está contenida en un módulo:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;# config/application.rb&lt;/span&gt;
&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Grouppet&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Application&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Application&lt;/span&gt;
    &lt;span class="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Volviendo a los módulos, ya he hablado de ellos en [1], y en otro post, que ya fue corregido por el [1], así que no vale la pena citarlo aquí.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Qué es un módulo en Ruby?&lt;/strong&gt;
Son modos de agrupamiento de métodos, clases y constantes. Tienen dos beneficios: proveen un namespace previniendo choques de nombres y soportan mezclado o mixins de una manera fácil [2]. En contraste con las clases, los módulos no pueden: ser instanciados o tener subclases[3]. Por último y aprovechando al lenguaje, un módulo es un objeto.
Aquí, un ejemplo robado de [4]:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Trig&lt;/span&gt;
  &lt;span class="no"&gt;PI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1416&lt;/span&gt;
  &lt;span class="c1"&gt;# class methods&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;Trig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;sin(&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)&amp;quot;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;Trig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# también se podría definir como self.cos(x)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;cos(&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)&amp;quot;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="no"&gt;Trig&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;PI&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 3.1416&lt;/span&gt;
&lt;span class="no"&gt;Trig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#=&amp;gt; cos(90)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Modules mixin (mezcla de módulos)&lt;/strong&gt;
Los módulos pueden ser incluidos (usando &lt;strong&gt;include&lt;/strong&gt;) dentro de las clases y con esto los mezclamos (o al menos eso dice Dave Thomas). Ya he hablado sobre esto en [1], el ejemplo posterior sería como un repaso.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Trig&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;sin(&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)&amp;quot;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Matematica&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Trig&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;mat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Matematica&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;mat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; sin(90)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Podemos hacer algo similar usando la palabra clave &lt;strong&gt;extend&lt;/strong&gt; pero para agregar métodos de clase:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Matematica2&lt;/span&gt;
  &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;Trig&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="no"&gt;Matematica&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; sin(90)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;In a nutshell&lt;/strong&gt;
Por un lado lo módulos nos permiten agregar funcionalidad a nuestras clases, algunos los clasifican como la forma que tiene Ruby de soportar herencia múltiple (yo no me siento calificado para hacer esa aseguración). Pero hay un poco más, el código de los módulos que incluimos puede interactuar con el código de nuestra clase. Eso permite hacer cosas fantásticas como: (el ejemplo es de [5])&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SizeMatters&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Comparable&lt;/span&gt;
  &lt;span class="kp"&gt;attr&lt;/span&gt; &lt;span class="ss"&gt;:str&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;&amp;lt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;anOther&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;anOther&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;inspect&lt;/span&gt;
    &lt;span class="vi"&gt;@str&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;s1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;SizeMatters&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Z&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;s2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;SizeMatters&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;YY&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;s3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;SizeMatters&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;XXX&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;s4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;SizeMatters&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;WWWW&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;s5&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;SizeMatters&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;VVVVV&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;s1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;s2&lt;/span&gt;                       &lt;span class="c1"&gt;#=&amp;gt; true&lt;/span&gt;
&lt;span class="n"&gt;s4&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;between?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;           &lt;span class="c1"&gt;#=&amp;gt; false&lt;/span&gt;
&lt;span class="n"&gt;s4&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;between?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;           &lt;span class="c1"&gt;#=&amp;gt; true&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="n"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s1&lt;/span&gt; &lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;sort&lt;/span&gt;   &lt;span class="c1"&gt;#=&amp;gt; [Z, YY, XXX, WWWW, VVVVV]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Bien, ¿qué hicimos aquí? Al incluir el módulo &lt;strong&gt;Comparable&lt;/strong&gt;[5] en nuestra clase le dimos a nuestra clase la capacidad de ordenarse (método &lt;strong&gt;sort&lt;/strong&gt;). El único detalle es que nuestra clase debe poder responder al método "&amp;lt;=&gt;", definido en el interior de la misma. ¿Cómo debe responder ese método? Los objetos de nuestra clase van a ser mayores, menores o iguales de acuerdo a cómo queremos nosotros que se comporten. El método &amp;lt;=&gt; debe devolver 1 si el primer elemento es mayor, -1 si es menor o 0 si son iguales.
También podríamos incluir Eumerable[6] y hacer que nuestros objetos sean iterables por ejemplo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Volviendo al mundo rails&lt;/strong&gt;
Mi curiosidad por los módulos viene desde que uso clearance como gema de autenticación en mis proyectos. Clearance incluye métodos en un modelo y en los controladores:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Clearance&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ApplicationController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActionController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Clearance&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Authentication&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;El código fuente de estos módulos se puede navegar en github [7] y [8], en ambos casos podemos ver la inclusión de métodos de clase y de instancia y cómo el buen uso de módulos nos permite (en realidad a los muchachos de thoughtbot) generar excelentes plugins para nuestras aplicaciones rails.
Ahora me pueden decir: yo no escribo gemas ni plugis. ¿Para qué quiero los módulos en rails? La gente de Stac escribió un artículo [9] sobre como organizar modelos cuando estos empiezan a crecer de manera desenfrenada y empiezan a convertirse un desastre. El artículo expone como usar &lt;strong&gt;mixins&lt;/strong&gt; para poder organizar nuestros métodos por funcionalidad y así tener código mucho más legible y ordenado.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;# lib/models/user/friendship_methods.rb&lt;/span&gt;
&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Models&lt;/span&gt;
  &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;User&lt;/span&gt;
    &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;FriendshipMethods&lt;/span&gt;
      &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Concern&lt;/span&gt;
      &lt;span class="n"&gt;included&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:friendships&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:foreign_key&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:initiator_id&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;InstanceMethods&lt;/span&gt;
        &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;befriend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;friend&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# app/models/user.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Models&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;FriendshipMethods&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Explicar que hace &lt;strong&gt;ActiveSupport::Concern&lt;/strong&gt; escapa la idea de este post, pero pueden buscar info en [10], aunque creo que el código y los comentarios del propio método &lt;strong&gt;concern&lt;/strong&gt; se explican por si solo [11]. Recomendación: leer el código fuente a veces está bueno!
También podríamos usar módulos para compartir código entre modelos. Un buen ejemplo sería un sitio que admite comentarios en varios modelos (post, page, etc). Por un lado podríamos usar herencia polimórfica, pero ahí tendríamos que guardar todo en la misma tabla, por otro lado podríamos definir los métodos comunes en un módulo e importarlo en los modelos en donde los necesitamos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[1] http://blog.malev.com.ar/2010/11/30/include-in-ruby/&lt;/li&gt;
&lt;li&gt;[2] Programming Ruby - Dave Thomas&lt;/li&gt;
&lt;li&gt;[3] http://www.rubyist.net/~slagell/ruby/modules.html&lt;/li&gt;
&lt;li&gt;[4] http://rubylearning.com/satishtalim/modules_mixins.html&lt;/li&gt;
&lt;li&gt;[5] http://www.ruby-doc.org/core/classes/Comparable.html&lt;/li&gt;
&lt;li&gt;[6] http://www.ruby-doc.org/core/classes/Enumerable.html&lt;/li&gt;
&lt;li&gt;[7] https://github.com/thoughtbot/clearance/blob/master/lib/clearance/authentication.rb&lt;/li&gt;
&lt;li&gt;[8] https://github.com/thoughtbot/clearance/blob/master/lib/clearance/user.rb&lt;/li&gt;
&lt;li&gt;[9] http://wearestac.com/blog/2011/05/organise_your_models&lt;/li&gt;
&lt;li&gt;[10] http://en.ihower.tw/post/454873995/rails3-activesupport-concern&lt;/li&gt;
&lt;li&gt;[11] https://github.com/rails/rails/blob/master/activesupport/lib/active_support/concern.rb&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 <entry>
   <title>Playing with screen</title>
   <link href="http://malev.com.ar/playing-with-screen" />
   <updated>2011-04-19T00:00:00-03:00</updated>
   <id>http://malev.com.ar/playing-with-screen</id>
   <content type="html">&lt;h1&gt;Playing with screen&lt;/h1&gt;

&lt;p&gt;En el pycamp [1], vi mucha gente usando &lt;strong&gt;screen&lt;/strong&gt; para manejar su terminal. Luego de ponerme a investigar un poquito descubrí que se puede hacer cosas bastante interesantes con este nuevo programilla. Pero, antes, de qué estoy hablando? &lt;strong&gt;GNU Screen&lt;/strong&gt; es un programa informático multiplexor de terminales desarrollado por el proyecto GNU. [2]&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Qué cosas tiene de bueno?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Muy configurable&lt;/li&gt;
&lt;li&gt;Permite dividir la pantalla&lt;/li&gt;
&lt;li&gt;Permite organizar muchas terminales virtuales&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;El último punto es el más interesante, ya que nos permite automatizar tareas que hacemos en nuestra consola. Digamos por ejemplo que tenemos una aplicación en rails 3. En la misma abrimos: Unicorn (server), una consola de rails, spork y watchr para nuestros test y por último queremos hacer un &lt;strong&gt;tail -f al log&lt;/strong&gt;. Hacer todo esto siempre puede ser un poco molesto. La solución, obviamente: screen:&lt;/p&gt;

&lt;p&gt;Primero una introducción: abrimos &lt;strong&gt;screen&lt;/strong&gt; con ...&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;screen&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;En principio no hay grandes cambios, pero si nos pasamos al modo comando: &lt;strong&gt;Ctrl + A&lt;/strong&gt;, las cosas empiezan a mejorar. Para crear crear una segunda instancia de la terminal (Ctrl +A c) y navegamos entre ellas con n (next) o p (previous), siempre en el modo comando. También podemos dividir una ventana de manera horizontal. Para esto, entramos a modo comando (Ctrl + A) y escribimos &lt;strong&gt;:split&lt;/strong&gt;. Vemos que se dividió nuestra pantalla. Con "Ctrl+A tab" nos paseamos entre las mitades, y presionamos "c" para crear una nueva terminal en cualquiera de las divisiones.
Hasta aquí nada del otro mundo, pero luego de ver una presentación de Tim Charper, pude ver como automatizar tareas comunes de nuestros entornos de desarrollo. Empezamos con un poco de configuración:
&lt;strong&gt;/home/malev/.screerc&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;# Remap escape char to C-\&lt;/span&gt;
&lt;span class="c1"&gt;# escape \034\034&lt;/span&gt;
&lt;span class="n"&gt;vbellwait&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;
&lt;span class="n"&gt;startup_message&lt;/span&gt; &lt;span class="n"&gt;off&lt;/span&gt;
&lt;span class="n"&gt;shell&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;-/bin/bash&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;defscrollback&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;
&lt;span class="n"&gt;chdir&lt;/span&gt;

&lt;span class="n"&gt;caption&lt;/span&gt; &lt;span class="n"&gt;always&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;%{-u wk} %L=%-Lw%45&amp;gt;%{+ Gk} %n%f* %t %{-}%+Lw%-0&amp;lt; %=%{ck} %H | %M %d %c &amp;quot;&lt;/span&gt;

&lt;span class="n"&gt;bind&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="n"&gt;focus&lt;/span&gt; &lt;span class="n"&gt;down&lt;/span&gt;
&lt;span class="n"&gt;bind&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="n"&gt;focus&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt;
&lt;span class="n"&gt;bind&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;focus&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt;
&lt;span class="n"&gt;bind&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;focus&lt;/span&gt; &lt;span class="n"&gt;bottom&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Este archivo hace algunas cosas interesante: elimina el cartel de bienvenida y mapea las teclas j y k como en vim para una navegación más simple. También nos configura b y t para pasarnos entre divisiones de manera más simple. Luego, dentro del directorio de una aplicación que estemos usando agregamos:
/home/malev/code/grouppet/screen&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="c1"&gt;# why use stuff instead of exec? Because if the process dies, the screen&lt;/span&gt;
&lt;span class="c1"&gt;# session will die with it, leaving you unable to see the backtrace. Also,&lt;/span&gt;
&lt;span class="c1"&gt;# it&amp;#39;s easier to restart that way. But, your choice :)&lt;/span&gt;
&lt;span class="n"&gt;setenv&lt;/span&gt; &lt;span class="no"&gt;ROOT&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;$HOME/code/grouppet&amp;quot;&lt;/span&gt;

&lt;span class="n"&gt;screen&lt;/span&gt;
&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;server&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;stuff&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;cd $ROOT&lt;/span&gt;&lt;span class="se"&gt;\015&lt;/span&gt;&lt;span class="s2"&gt;clear&lt;/span&gt;&lt;span class="se"&gt;\015&lt;/span&gt;&lt;span class="s2"&gt;unicorn&lt;/span&gt;&lt;span class="se"&gt;\015&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="n"&gt;screen&lt;/span&gt;
&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;logs&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;stuff&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;cd $ROOT&lt;/span&gt;&lt;span class="se"&gt;\015&lt;/span&gt;&lt;span class="s2"&gt;clear&lt;/span&gt;&lt;span class="se"&gt;\015&lt;/span&gt;&lt;span class="s2"&gt;tail -f log/development.log&lt;/span&gt;&lt;span class="se"&gt;\015&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="n"&gt;screen&lt;/span&gt;
&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;spork&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;stuff&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;cd $ROOT&lt;/span&gt;&lt;span class="se"&gt;\015&lt;/span&gt;&lt;span class="s2"&gt;clear&lt;/span&gt;&lt;span class="se"&gt;\015&lt;/span&gt;&lt;span class="s2"&gt;spork&lt;/span&gt;&lt;span class="se"&gt;\015&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="n"&gt;screen&lt;/span&gt;
&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;watchr&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;stuff&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;cd $ROOT&lt;/span&gt;&lt;span class="se"&gt;\015&lt;/span&gt;&lt;span class="s2"&gt;clear&lt;/span&gt;&lt;span class="se"&gt;\015&lt;/span&gt;&lt;span class="s2"&gt;rake watchr&lt;/span&gt;&lt;span class="se"&gt;\015&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="n"&gt;screen&lt;/span&gt;
&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;console&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;stuff&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;cd $ROOT&lt;/span&gt;&lt;span class="se"&gt;\015&lt;/span&gt;&lt;span class="s2"&gt;clear&lt;/span&gt;&lt;span class="se"&gt;\015&lt;/span&gt;&lt;span class="s2"&gt;rails c&lt;/span&gt;&lt;span class="se"&gt;\015&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="n"&gt;screen&lt;/span&gt;
&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;shell&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;stuff&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;cd $ROOT&lt;/span&gt;&lt;span class="se"&gt;\015&lt;/span&gt;&lt;span class="s2"&gt;clear&lt;/span&gt;&lt;span class="se"&gt;\015&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;La primer línea útil indica donde estamos parados. Luego crea varias screens y en cada una corre un comando: &lt;strong&gt;unicorn&lt;/strong&gt;, los logs, &lt;strong&gt;spork&lt;/strong&gt;, &lt;strong&gt;watchr&lt;/strong&gt;, la consola y por último un shell limpio. Esto me permite tener mi entorno listo para empezar a trabajar con solo ejecutar:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="n"&gt;cd&lt;/span&gt;&lt;span class="sr"&gt; /home/m&lt;/span&gt;&lt;span class="n"&gt;alev&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;grouppet&lt;/span&gt;
&lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Nota: Por supuesto podemos crear un alias para este comando y así tener todo más simple todavía.
&lt;strong&gt;Algunos comando útiles&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;C-a D : Sale de la terminal&lt;/li&gt;
&lt;li&gt;C-a :quit : Sale de screen&lt;/li&gt;
&lt;li&gt;C-a " : Muestra todas las screen abiertas&lt;/li&gt;
&lt;li&gt;C-a ? : Muestra ayuda&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;strong&gt;Más información:&lt;/strong&gt;
Quick reference: http://aperiodic.net/screen/quick_reference&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[1] http://blog.malev.com.ar/2011/03/31/pycamp-2011/&lt;/li&gt;
&lt;li&gt;[2] http://es.wikipedia.org/wiki/GNU_Screen&lt;/li&gt;
&lt;li&gt;[3] http://www.gnu.org/software/screen/&lt;/li&gt;
&lt;li&gt;[4] http://www.debian-administration.org/articles/34&lt;/li&gt;
&lt;li&gt;[5] http://www.gnu.org/software/screen/manual/screen.html&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 
</feed>
