<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[4Trabes]]></title>
  <link href="http://4trabes.com/atom.xml" rel="self"/>
  <link href="http://4trabes.com/"/>
  <updated>2017-12-13T20:55:55+01:00</updated>
  <id>http://4trabes.com/</id>
  <author>
    <name><![CDATA[Trabe Soluciones S.L.]]></name>
    <email><![CDATA[contact@trabesoluciones.com]]></email>
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Manteniendo los logs a raya]]></title>
    <author><name>David</name></author>
    <link href="http://4trabes.com/2015/10/22/manteniendo-los-logs-a-raya/"/>
    <updated>2015-10-22T10:10:00+02:00</updated>
    <id>http://4trabes.com/2015/10/22/manteniendo-los-logs-a-raya</id>
    <content type="html"><![CDATA[<p>Si hay algo que detesto de mi máquina de desarrollo es encontrarme con que los logs de las aplicaciones
Rails han crecido hasta ocupar cientos de megas. La configuración por defecto de Rails asume que todo
el log irá a un fichero y que es el usuario el que configura como quiere que se gestionen la rotación en producción
(en Trabe solemos usar <a href="http://linux.die.net/man/8/logrotate">logrotate</a>).</p>

<p>Hay varias opciones para mantener a raya los logs en desarrollo. La primera es configurar en
<code>config/environments/development.rb</code> el <code>Logger</code> de Rails para que rote los ficheros:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">config</span><span class="o">.</span><span class="n">logger</span> <span class="o">=</span> <span class="no">Logger</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">config</span><span class="o">.</span><span class="n">paths</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">first</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="o">.</span><span class="n">megabytes</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>Con estos parametros nuestro fichero de log rotaría al alcanzar 2 megas y no almacenaríamos ficheros antiguos (así es como
me gusta a mi, pero en la <a href="http://ruby-doc.org/stdlib-2.1.0/libdoc/logger/rdoc/Logger.html">documentación de la clase Logger</a>
podéis ver que hay más opciones de rotación.</p>

<p>Otra posibilidad es utilizar un servicio de loggin del operativo, por ejemplo usar <code>syslog</code> y configurarlo como prefiramos.</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>config.logger = SyslogLogger.new</span></code></pre></td></tr></table></div></figure>


<p>Esta opción es más flexible ya que nos permite tener fuera de la aplicación la configuración (así cada desarrollador puede ponerla
a su gusto). De todos modos, al igual que en el primer caso, esto nos obliga a acordarnos de configurar el logger cada vez que
creamos una nueva aplicación y eso es &#8220;demasiado esfuerzo&#8221;. Mi solución favorita es no tocar nada en las aplicaciones Rails y utilizar un
servicio de rotación de logs como se hace en producción: lograte en Linux y newsyslog en Mac OSX, configurado de tal modo que se roten todos
los logs de las aplicaciones que estoy desarrollando.</p>

<p>Con lograte, añadimos un fichero en la carpeta <code>/etc/logrotate.d/</code> tal que así:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>/home/david/code/*/log/*.log {
</span><span class='line'>  size 2M
</span><span class='line'>  rotate 0
</span><span class='line'>  create 640 david users
</span><span class='line'>  copytruncate
</span><span class='line'>  missingok
</span><span class='line'>}</span></code></pre></td></tr></table></div></figure>


<p>y si usamos <a href="http://www.freebsd.org/cgi/man.cgi?newsyslog.conf(5)">newsyslog</a> lo añadimos a la carpeta <code>/etc/newsyslog.d/</code>:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class=''><span class='line'># logfilename                  [owner:group]    mode count size    when  flags [/pid_file] [sig_num]
</span><span class='line'>/Users/david/code/**/log/*.log david:staff      640  0     2048    *     GN</span></code></pre></td></tr></table></div></figure>


<p>Easy peasy lemon squeezy ;)</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Welcome Clara and welcome back Lucas]]></title>
    <author><name>David</name></author>
    <link href="http://4trabes.com/2015/04/23/welcome-clara-and-welcome-back-lucas/"/>
    <updated>2015-04-23T09:00:00+02:00</updated>
    <id>http://4trabes.com/2015/04/23/welcome-clara-and-welcome-back-lucas</id>
    <content type="html"><![CDATA[<p>Este post de bienvenida llega con un poco de retraso. Unos días en el caso de
Clara, un par de semanas en el de Lucas.</p>

<p>Clara se une a la <a href="http://trabesoluciones.com/equipo">familia Trabe</a> para
realizar unas prácticas de tres meses tras los que esperamos que se quede con
nosotros todo el tiempo que quiera. De momento viene a aprender y a echar una
mano al lado Java de Trabe.</p>

<p>A Lucas ya habíamos tenido el privilegio de
<a href="http://4trabes.com/2008/11/04/lucas-sin-matricula-pero-con-nomina-es-decir-ya-somos-siete/">tenerlo entre nosotros allá por el 2008</a>,
antes de que se
<a href="http://4trabes.com/2011/08/16/farewell-lucas/">fuese a vivir una aventura vital</a>
por Sudamérica y el Sudeste Asiático durante casi dos años. Ahora ha vuelto para demostrar que
segundas partes sí pueden ser buenas y nos echará una mano con nuestros
desarrollos Ruby on Rails y JavaScript.</p>

<p>Os damos las gracias a los dos por apuntaros a la aventura Trábica.
Esperamos que lo paséis bien y aprendamos y crezcamos todos juntos.</p>

<p>Y como sois dos, toca poner dos gifs animados de Jake! :D</p>

<div class="image">
<img src="http://4trabes.com/assets/jake4.gif" width="480" title="Happy Jake"/>
</div>


<br/>


<div class="image">
<img src="http://4trabes.com/assets/jake3.gif" width="480" title="Happy Jake"/>
</div>


<br/>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Trävidad]]></title>
    <author><name>Óscar</name></author>
    <link href="http://4trabes.com/2014/12/31/Happy-2015/"/>
    <updated>2014-12-31T12:36:00+01:00</updated>
    <id>http://4trabes.com/2014/12/31/Happy-2015</id>
    <content type="html"><![CDATA[<p>2014 se nos escapa de las manos señores!! La Trävidad está en su momento culmen!</p>

<p><img class="center" src="http://4trabes.com/assets/arbol.jpg" width="500" title="Pedazo árbol que nos hemos currado" ></p>

<p>Como siempre en Trabe, 2014 ha sido un año intenso que nos ha traido algún <a href="http://4trabes.com/2014/07/18/farewell-fuco/">hasta luego</a> y un par de bienvenidas: <a href="http://4trabes.com/2014/09/22/welcome-ceci/">una</a> y <a href="http://4trabes.com/2014/08/07/welcome-roman/">dos</a>. Por lo demás, hemos seguido participando en charlas, eventos y todo lo que habéis ido viendo <a href="http://4trabes.com/archives/#year2014">en el blog</a></p>

<p>Para acabar el año, como es tradición, lo hemos montado muy bien ;)</p>

<table>
<thead>
<tr>
<th></th>
<th>               </th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td> <img class="left" src="http://4trabes.com/assets/2014Box.jpg" width="440" title="Qué será será?" >  <img class="left" src="http://4trabes.com/assets/2014BoxOpen.jpg" width="440" title="Oh! Manos a la obra!" > </td>
</tr>
</tbody>
</table>


<p>Feliz 2015 a todos!!</p>

<p><img class="center" src="http://4trabes.com/assets/cheers.gif" title="Cheers mates!" ></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Every day tmux]]></title>
    <author><name>David</name></author>
    <link href="http://4trabes.com/2014/10/13/every-day-tmux/"/>
    <updated>2014-10-13T10:00:00+02:00</updated>
    <id>http://4trabes.com/2014/10/13/every-day-tmux</id>
    <content type="html"><![CDATA[<p>Este post está dirigido a aquellos desarrolladores que de vez en cuando tienen que lanzar procesos largos
en máquinas remotas y que desconocen <a href="http://tmux.sourceforge.net/">tmux</a> (o cualquier otro tipo de
<a href="http://en.wikipedia.org/wiki/Terminal_multiplexer">multiplexador de terminal</a>).</p>

<p>Lo que nos interesa de tmux es la posibilidad de iniciar una sesión de shell y desconectarnos (<em>detach</em>) de ella para
volver a recuperarla más adelante. Por ejemplo: abrir una sesión SSH, lanzar un proceso largo dentro
de tmux y cerrar la conexión para, más adelante, volver a conectarnos y recuperar la sesión. Es habitual que
las conexiones SSH tengan <em>timeouts</em> y si no estamos atentos, se cierren matando nuestros procesos y alterando nuestra
presión arterial. ¡tmux al rescate!.</p>

<p>Un ejemplo de sesión de trabajo usando tmux podría ser así:</p>

<pre><code>david@localhost $ ssh david@remotehost
david@remotehost $ tmux new-session -s big_work
david@remotehost (tmux) $ ./launch_big_work.sh
Starting BIG work. ETA 4h
# detach pulsando en el teclado [C-b] d
[detached]
david@remotehost $ exit
logout
Connection to remotehost closed.
david@localhost $

# 4 horas después...
david@localhost $ ssh david@remotehost
david@remotehost $ tmux attach -t big_work
Starting BIG work. ETA 4h.
Work done. Yay!
david@remotehost (tmux) $ exit
david@remotehost $ exit
logout
Connection to remotehost closed.
david@localhost $
</code></pre>

<p>No hay nada especial que hacer, solo tener instalado tmux en la máquina remota y fijarse en que la combinación de teclas
para hacer <em>detach</em> es <code>Ctrl+b</code> y después <code>d</code>, que parece lo mismo que <code>Ctrl+b+d</code> pero no lo es :D</p>

<p>Es super práctico y no cuesta nada recordarlo. Merece la pena :)</p>

<p>Para ir un paso más allá, podéis tener en vuestras máquinas remotas unos alias para facilitar la gestión
de sesiones. En mi caso me gusta usar estos (que son los que también uso en mi máquina local):</p>

<pre><code>tmn='tmux new-session -s'
tma='tmux -2 attach -t'
tmk='tmux kill-session -t'
tml='tmux list-sessions'
</code></pre>

<p>Espero que os sea de ayuda. Probadlo. Os gustará :)</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Material de nuestras charlas en las XIII Xornadas Libres]]></title>
    <author><name>David</name></author>
    <link href="http://4trabes.com/2014/10/09/material-de-nuestras-charlas-en-las-xiii-xornadas-libres/"/>
    <updated>2014-10-09T11:00:00+02:00</updated>
    <id>http://4trabes.com/2014/10/09/material-de-nuestras-charlas-en-las-xiii-xornadas-libres</id>
    <content type="html"><![CDATA[<p>Hemos dejado colgadas las transparencias de nuestras charlas en las
<a href="http://gpul.es/e/2014/xornadas-libres/">XIII Xornadas Libres</a> organizadas por el <a href="http://gpul.es/">GPUL</a>.
La conferencia de Thymeleaf está a punto de comenzar mientras escribo este post, la charla de Javascript,
comenzará dos horas más tarde, así que llegamos a tiempo por si alguien quiere seguir el material desde su
portatil :).</p>

<ul>
<li><a href="http://trabe-teaching.github.io/thymeleaf-101">Thymeleaf 101</a></li>
<li><a href="http://trabe-teaching.github.io/js-del-espagueti-a-la-lasanha">JS: del espagueti a la lasaña, paso a paso</a></li>
</ul>


<p>Esperamos que os parezcan unas charlas interesantes. Nos vemos en la FIC.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Charlas de Trabe en las XIII Xornadas Libres]]></title>
    <author><name>David</name></author>
    <link href="http://4trabes.com/2014/09/29/charlas-de-trabe-en-las-xiii-xornadas-libres/"/>
    <updated>2014-09-29T11:00:00+02:00</updated>
    <id>http://4trabes.com/2014/09/29/charlas-de-trabe-en-las-xiii-xornadas-libres</id>
    <content type="html"><![CDATA[<p>Entre el 8 y el 10 de Octubre se celebran en A Coruña las <a href="http://gpul.es/e/2014/xornadas-libres/">XIII Xornadas Libres</a>
organizadas por el <a href="http://gpul.es/">GPUL</a>, en las que Trabe va participar con dos charlas:
Marcos impartirá &#8220;Thymeleaf 101&#8221;, una introducción a <a href="http://www.thymeleaf.org/">Thymeleaf</a>,
un motor de <em>natural templating</em> Java del que somos <em>early adopters</em> y que está atrapando el
interés de la comunidad Spring; Asís y yo, impartiremos &#8220;JS: del espagueti a la lasaña, paso
a paso&#8221;, en la que intentaremos ayudar en lo que podamos a que podáis racionalizar vuestro
código JavaScript.</p>

<p>La inscripción a las jornadas es gratuita y ya está abierta. Si estáis interesados, inscribíos,
las plazas son limitadas.</p>

<p>Nos vemos en las jornadas :)</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Welcome Ceci]]></title>
    <author><name>David</name></author>
    <link href="http://4trabes.com/2014/09/22/welcome-ceci/"/>
    <updated>2014-09-22T20:00:00+02:00</updated>
    <id>http://4trabes.com/2014/09/22/welcome-ceci</id>
    <content type="html"><![CDATA[<p>Hace poco más de un mes le dábamos la <a href="http://4trabes.com/2014/08/07/welcome-roman">bienvenida a Román</a>
y ya nos toca dar la bienvenida a un nuevo miembro del equipo de Trabe otra vez (dos incorporaciones en
tan poco tiempo es todo un record).</p>

<p>En este caso se trata de Cecilia (Ceci para los amigos), que ha estado haciendo su Trabajo de Fin de
Grado en <a href="http://trabesoluciones.com">Trabe</a> y, tras recibir una estupenda matrícula de honor, se va
a quedar con nosotros para echarnos una mano. En su proyecto estuvo trabajando con <a href="http://redis.io">Redis</a>
y <a href="http://www.sideqik.com">Sidekiq</a>; y la experiencia que ha adquirido nos va a venir muy bien para
proyectos que estamos desarrollando actualmente.</p>

<p>Esperamos que Ceci siga aprendiendo mucho con nosotros; y estamos seguros de que ella nos enseñará muchas
cosas y que juntos aprenderemos muchas más.</p>

<p>Ceci, que disfrutes de tu aventura Trábica. Welcome! :)</p>

<div class="image">
<img src="http://4trabes.com/assets/jake2.gif" title="Happy Jake"/>
</div>



]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Welcome Román]]></title>
    <author><name>David</name></author>
    <link href="http://4trabes.com/2014/08/07/welcome-roman/"/>
    <updated>2014-08-07T09:22:00+02:00</updated>
    <id>http://4trabes.com/2014/08/07/welcome-roman</id>
    <content type="html"><![CDATA[<p>Siempre me alegra poder dar la bienvenida a un nuevo miembro de <a href="http://www.trabesoluciones.com/equipo">la familia Trabe</a>; en este caso,
le damos la bienvenida a <a href="http://github.com/rcoedo">Román</a>, que viene a echarnos una mano con el desarrollo de aplicaciones Java. Su carta
de presentación es un Google Summer of Code 2014: <a href="https://github.com/jclouds/jclouds-labs-aws">Amazon Glacier support for jClouds</a>. Esperamos
que aprenda mucho con nosotros; y estamos seguros de que nos enseñará muchas cosas y que juntos aprenderemos muchas más.
Román, esperamos que disfrutes de la Trabe Aventura. Welcome! :)</p>

<div class="image">
<img src="http://4trabes.com/assets/jake1.gif" title="Happy Jake"/>
</div>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Se busca estudiante para proyecto de fin de carrera: Pizarreitor]]></title>
    <author><name>David</name></author>
    <link href="http://4trabes.com/2014/07/21/se-busca-estudiante-para-proyecto-de-fin-de-carrera-pizarreitor/"/>
    <updated>2014-07-21T10:00:00+02:00</updated>
    <id>http://4trabes.com/2014/07/21/se-busca-estudiante-para-proyecto-de-fin-de-carrera-pizarreitor</id>
    <content type="html"><![CDATA[<p>En capítulos anteriores de este blog (<a href="http://4trabes.com/2014/07/20/se-busca-estudiante-para-proyecto-de-fin-de-carrera-thymeleaf-dot-rb">&#8220;Haz tu proyecto de fin de carrera en Trabe: Thymeleaf.rb&#8221;</a>)
me propuse buscar un estudiante de informática que quisiese hacer su proyecto de fin de carrera con nosotros. En el
capítulo de hoy vuelvo de nuevo a la carga con otra idea que se nos ha ocurrido para hacer un proyecto a partir de
Septiembre.</p>

<p>En este caso, se trataría de realizar un aplicación móvil (nombre provisional: &#8220;Pizarreitor&#8221; xD), que cubriría una
necesidad de Trabe: subir fotos a nuestras tarjetas de <a href="https://trello.com">Trello</a>. Desde hace más de un año estamos
usando Trello como herramienta de gestión de proyectos y una de las
funcionalidades que ofrece la herramienta es adjuntar archivos a las tarjetas. Otra cosa que hacemos es pintar
diagramas en el encerado o en papel, y para adjuntarlos como documentación solemos sacar una foto con el móvil,
enviarnos la imágen por correo y adjuntarla al Trello. Esto también se puede hacer con la propia
<a href="https://itunes.apple.com/us/app/trello-organize-anything/id461504587">app móvil de Trello</a> pero es necesario bucear
por varios menús hasta encontrar la opción adecuada. Lo que nos gustaría es tener una aplicación que nos permita sacar
una foto y utilizando el <a href="https://trello.com/docs/">API de Trello</a> adjuntarla a una tarjeta de un proyecto de
manera sencilla.</p>

<p>La aplicación podría ser desarrollada para iOS (iOS8 y Swift) y/o Android, y podrían incluirse otras funcionalidades
como procesado de fotos (por ejemplo limpiar y realzar la foto de la pizarra), por lo tanto el tamaño del proyecto se
podría ajustar.</p>

<p>Si alguien está interesado, sólo tiene que enviar un correo a <a href="&#109;&#x61;&#105;&#108;&#116;&#x6f;&#x3a;&#x63;&#111;&#110;&#x74;&#97;&#99;&#116;&#x6f;&#64;&#x74;&#114;&#x61;&#98;&#x65;&#x73;&#x6f;&#108;&#117;&#x63;&#x69;&#x6f;&#110;&#101;&#x73;&#46;&#x63;&#x6f;&#x6d;">&#x63;&#x6f;&#110;&#x74;&#x61;&#x63;&#116;&#111;&#x40;&#116;&#x72;&#x61;&#x62;&#x65;&#115;&#x6f;&#108;&#x75;&#x63;&#105;&#111;&#110;&#x65;&#x73;&#46;&#x63;&#111;&#109;</a>.</p>

<p>¿Quién se anima?</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Se busca estudiante para proyecto de fin de carrera: Thymeleaf.rb]]></title>
    <author><name>David</name></author>
    <link href="http://4trabes.com/2014/07/20/se-busca-estudiante-para-proyecto-de-fin-de-carrera-thymeleaf-dot-rb/"/>
    <updated>2014-07-20T08:42:00+02:00</updated>
    <id>http://4trabes.com/2014/07/20/se-busca-estudiante-para-proyecto-de-fin-de-carrera-thymeleaf-dot-rb</id>
    <content type="html"><![CDATA[<p>A veces es bueno recordar en este blog qué cosas hacemos en <a href="http://www.trabesoluciones.com">Trabe</a>, como por ejemplo,
llevar proyectos de fin de carrera de estudiantes de la <a href="http://www.fic.udc.es">Facultad de Informática de la UDC</a> o
trabajar con <a href="http://www.thymeleaf.org">Thymeleaf</a>, la librería de <em>natural templating</em> que está rompiendo la pana en
el mundo Spring.</p>

<p>Si juntamos ambas cosas, surge la posibilidad de que uno o varios estudiantes puedan realizar un proyecto relacionado
con Thymeleaf en Trabe a partir de Septiembre.</p>

<p>La idea que manejo es crear una versión de Thymeleaf para Ruby (de ahí el original nombre de Thymeleaf.rb). Esta versión
se basará en las funcionalidades de Thymeleaf 2.1 pero no copiará la implementación. Lo importante en este proyecto es
crear la infraestructura necesaria (incluído el soporte de testing y benchmarking) y crear una implementación lo más
sencilla posible sin preocuparnos del rendimiento. La acompañaríamos de otra librería (thymeleaf-rails) que nos permita
usar thymeleaf.rb como motor de plantillas en aplicaciones Rails.</p>

<p>¿Qué nos aporta esto? Pues creo que varias cosas, entre otras: dar visibilidad al proyecto Thymeleaf en la comunidad RoR
o tener un motor de plantillas común para los <em>stacks</em> Java y RoR que usamos en Trabe.</p>

<p>Creo que puede ser un proyecto interesante con el que se puede aprender mucho, así que si alguien está interesado, sólo
tiene que enviar un correo a <a href="&#109;&#97;&#105;&#x6c;&#116;&#111;&#58;&#x63;&#x6f;&#110;&#116;&#97;&#x63;&#116;&#111;&#64;&#116;&#114;&#x61;&#x62;&#101;&#x73;&#111;&#108;&#117;&#99;&#105;&#111;&#x6e;&#x65;&#115;&#x2e;&#x63;&#111;&#109;">&#99;&#111;&#x6e;&#x74;&#x61;&#x63;&#x74;&#111;&#64;&#x74;&#114;&#97;&#98;&#x65;&#x73;&#x6f;&#x6c;&#117;&#x63;&#x69;&#x6f;&#x6e;&#x65;&#x73;&#46;&#x63;&#x6f;&#109;</a>.</p>

<p>¿Quién se anima?</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Farewell Fuco]]></title>
    <author><name>David</name></author>
    <link href="http://4trabes.com/2014/07/18/farewell-fuco/"/>
    <updated>2014-07-18T20:28:00+02:00</updated>
    <id>http://4trabes.com/2014/07/18/farewell-fuco</id>
    <content type="html"><![CDATA[<p>Desde hace unas semanas <a href="https://github.com/madtrick">Fuco</a> ya no forma parte de
<a href="http://www.trabesoluciones.com">Trabe Soluciones</a>, y como ya es costumbre, me gustaría escribir un post para decirle
hasta luego. Tras tres años fabulosos junto a nosotros el amor lo ha llevado a tierras germanas donde los señores de
<a href="https://www.contentful.com">Contentful</a> van a poder disfrutar de su grata compañía y excepcionales habilidades
técnicas.</p>

<p>Querido Fuco, han sido tres años llenos de risas en los que hemos aprendido un montón de cosas gracias a ti (y no sólo
me refiero a la <a href="http://en.wikipedia.org/wiki/Tarring_and_feathering">jovial tradición medieval de la brea y la pluma</a>
xD). Has ayudado a Trabe a ser mejor empresa tanto a nivel tecnológico como humano y por eso, en nombre de todos los
Trábicos, quiero darte las gracias.</p>

<p>Te echamos mucho de menos, pero sabemos que vas a ser muy feliz y vas a disfrutar mucho de tu aventura. Trabe es tu
casa y su puerta siempre está abierta para ti. Vete enfriando las cervezas que pronto iremos por Berlín a que nos
enseñes las maravillas de tu nuevo hogar :)</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[El reto del SmartDev]]></title>
    <author><name>David</name></author>
    <link href="http://4trabes.com/2014/06/09/el-reto-del-smartdev/"/>
    <updated>2014-06-09T15:49:00+02:00</updated>
    <id>http://4trabes.com/2014/06/09/el-reto-del-smartdev</id>
    <content type="html"><![CDATA[<p>Del viernes 5 al domingo 8 de junio se celebró el <a href="http://www.smartweekend.es">Smart Weekend</a> en el coliseum de A Coruña. Dentro de este evento Trabe participó como patrocinador en el <a href="http://www.smartweekend.es/#/dev">SmartDev</a>, una competición de desarrollo para la que propusimos un reto de desarrollo de frontend con HTML5, CSS3 y Javascript. Se trataba de desarrollar un pequeño y simple framework de presentaciones (cuelgo aquí las <a href="http://4trabes.com/assets/smartdev_2014_competicion_frontend_normas.pdf">instrucciones</a> por si alguien tiene curiosidad o ganas de probar en su tiempo libre).</p>

<p>Los ganadores del reto: Francisco y Juán Carlos, se llevaron cada uno una bonita Nexus 7 Wifi de 16Gb (que no están los tiempos para ir tirando gigas por ahí :D). Gracias por participar. Esperamos que os animéis a liberar vuestro proyecto, Rubik, cuando lo hayáis pulido :)</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Trabe necesita programadores]]></title>
    <author><name>David</name></author>
    <link href="http://4trabes.com/2014/06/02/trabe-busca-programadores/"/>
    <updated>2014-06-02T12:46:00+02:00</updated>
    <id>http://4trabes.com/2014/06/02/trabe-busca-programadores</id>
    <content type="html"><![CDATA[<p>Estamos buscando gente a la que le guste programar. Necesitamos cubrir dos perfiles: un programador Ruby on Rails y un programador Java. Lo que nos gustaría es que pudiese trabajar desde el primer día (o casi) con nuestros stacks básicos. A saber:</p>

<p><strong>Rails</strong></p>

<ul>
<li>Ruby 2</li>
<li>Ruby on Rails 4</li>
<li>MySQL</li>
</ul>


<p><strong>Java</strong></p>

<ul>
<li>Java 7</li>
<li>Spring MVC</li>
<li>Hibernate</li>
<li>Oracle</li>
</ul>


<p>Tanto con Rails como con Java, utilizamos HTML5, CSS3 y Javascript para la capa vista (también usamos Coffescript, SASS y LESS). Además solemos usar Twitter Bootstrap como base.</p>

<p>Valoraremos positivamente el conocimiento de otras tecnologías y herramientas que usamos (Git, Thymeleaf, AngularJS, Backbone, etc.) y la capacidad para desarrollar aplicaciones móviles Android o iOs.</p>

<h2>Qué te ofrecemos</h2>

<p>Un puesto de trabajo con un sueldo competitivo, seguro médico, horario flexible, jornada de verano, posibilidad de teletrabajar, oficina en el centro (zona plaza de Galicia), equipamiento de calidad, ambiente distendido y mucho más.</p>

<h2>Envíanos un correo</h2>

<p>Si crees que este trabajo es para ti, envianos un correo a <a href="mailto:rrhh@trabesoluciones.com">rrhh@trabesoluciones.com</a> y cuentanos quién eres, a qué te dedicas, qué sabes hacer, por qué te gustaría trabajar con nosotros y por qué crees que eres la persona que buscamos. Nos encanta la sinceridad y siempre valoramos tanto el conocimiento como el interés. Si puedes, no olvides enseñarnos algo que hayas hecho (proyectos en los que hayas participado, código <em>Open Source</em>, etc.).</p>

<p>Esperamos vuestros correos. Prometemos responder a todos :)</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Material de nuestras últimas charlas]]></title>
    <author><name>David</name></author>
    <link href="http://4trabes.com/2014/04/07/material-de-nuestras-ultimas-charlas/"/>
    <updated>2014-04-07T20:38:00+02:00</updated>
    <id>http://4trabes.com/2014/04/07/material-de-nuestras-ultimas-charlas</id>
    <content type="html"><![CDATA[<p>El otro día unos fans (jajajaja) me preguntaron dónde podían encontrar las transparencias (o slides, que es más cool) de las últimas charlas que Asís y yo hemos estado impartiendo. Pongo enlaces a todas ellas por si alguien más está interesado (las dos primeras son parecidas). Enjoy!</p>

<ul>
<li><a href="http://trabe-teaching.github.io/software-development-at-trabe">Software Development at Trabe</a></li>
<li><a href="http://trabe-teaching.github.io/surviving-software-development">Surviving Software Development</a></li>
<li><a href="http://trabe-teaching.github.io/el-javascript-acabara-con-nosotros">El Javascript acabará con nosotros</a></li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Alias de shell para Bitbucket]]></title>
    <author><name>David</name></author>
    <link href="http://4trabes.com/2013/09/24/alias-de-shell-para-bitbucket/"/>
    <updated>2013-09-24T13:43:00+02:00</updated>
    <id>http://4trabes.com/2013/09/24/alias-de-shell-para-bitbucket</id>
    <content type="html"><![CDATA[<p>El otro día, Fuco nos envío una referencia a un <a href="https://twitter.com/igrigorik/status/382019904930459648">tweet de Ilya Grigorik</a> que a su vez referenciaba a un <a href="https://gist.github.com/igrigorik/6666860">Gist</a> con un alias de shell muy práctico para quien tiene repositorios en GitHub. En Trabe usamos GitHub para los proyectos <em>open source</em> y Bitbucket para los proyectos privados (los motivos podemos dejarlos para otro post), así que tenemos nuestra propia versión del script. Para el que tenga interés, he dejado un <a href="https://gist.github.com/davidbarral/6683804">Gist con la versión para ZSH y MacOS X</a> que usamos en Trabe. Tiene varios alias que nos permiten realizar las operaciones más habituales:</p>

<ul>
<li>Ir a la página resumen del proyecto</li>
<li>Ir al código fuente de una rama</li>
<li>Ver un commit</li>
<li>Ver las <em>pull requests</em> abiertas</li>
<li>Crear una nueva <em>pull request</em></li>
</ul>


<p>Adaptarlo a Bash y a otros operativos queda como ejercicio para el lector ;)</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Trabe busca programador]]></title>
    <author><name>David</name></author>
    <link href="http://4trabes.com/2013/05/13/trabe-busca-programador/"/>
    <updated>2013-05-13T18:09:00+02:00</updated>
    <id>http://4trabes.com/2013/05/13/trabe-busca-programador</id>
    <content type="html"><![CDATA[<p>Buscamos a una persona que le guste programar.  Necesitamos que sepa desarrollar software utilizando JEE o Ruby on Rails. No buscamos jefes de proyecto, analistas funcionales o arquitectos software. Lo que necesitamos es un buen programador.</p>

<p>Solemos desarrollar aplicaciones web desde cero, así que nuestro candidato perfecto tendría esta pinta:</p>

<ul>
<li>Tiene experiencia desarrollando con Java. Domina Spring e Hibernate. Domina Spring MVC y ha trabajado con Struts. También conoce Wicket y Play! framework.</li>
<li>Tiene experiencia desarrollando con Ruby on Rails versiones 2 y 3 (ahora está probando la versión 4). Conoce Sinatra y hace scripts de shell en Ruby.</li>
<li>Domina Javascript (the good parts). Conoce en profundidad jQuery y algún framework MVC tipo Backbone. Puede programar en CoffeeScript.</li>
<li>Sabe montar una vista web: HTML5, CSS3 y usa algún preprocesador (SASS o LESS). También conoce HTML4, XHTML, CSS2 y toda esa basura obsoleta.</li>
<li>Es capaz de crear APIs REST dignas con Java o con Ruby.</li>
<li>Conoce el protocolo HTTP y sus principales particularidades.</li>
<li>Desarrolla para una plataforma movil: iOS o Android. Mejor, desarrolla para las dos.</li>
<li>Es capaz de configurar y mantener un servidor Unix/Linux (Apache, Tomcat, Pound, Bind, MySQL, Oracle y más).</li>
<li>Sabe lo que es el control de versiones. Domina Git.</li>
<li>Entiende por qué es interesante automatizar todos sus flujos de trabajo (como el despliegue de aplicaciones o el entorno de desarrollo).</li>
<li>Sabe que es importante testear el software y lo hace.</li>
<li>Es capaz de escribir un documento técnico de manera correcta y precisa.</li>
<li>Tiene dominio de inglés suficiente para ser capaz de entender documentación y puede participar en foros técnicos cuando es necesario para buscar ayuda.</li>
</ul>


<p>No te asustes. Nadie en Trabe tiene este perfil y sabemos que es muy dificil encontrar a alguien que lo cumpla. Buscamos gente que venga a sumar y mejore nuestro equipo.</p>

<p>Lo que ofrecemos es un contrato fijo con un sueldo competitivo, seguro médico, horario flexible, jornada de verano, posibilidad de teletrabajar, oficina en el centro, ambiente distendido y mucho más.</p>

<p>Si crees que este es un trabajo para ti, no nos envíes un CV estándar (tu foto, tus datos y todo eso), envíanos un correo a <a href="mailto:rrhh@trabesoluciones.com">rrhh@trabesoluciones.com</a> y cuéntanos por qué te interesa el trabajo, qué experiencia tienes, qué te gusta, qué te disgusta y por qué. Si puedes enseñarnos algo que hayas hecho, mucho mejor. Puede ser un proyecto que has realizado en otra empresa y que sea público, un proyecto personal o una librería open-source. Dinos qué cumples del candidato ideal y no te tires de la moto: sabemos que nadie va a encajar al 100%.</p>

<p>Si tienes alguna duda pon un comentario en el post o envianos un correo. Gracias.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Prácticas de verano en Trabe]]></title>
    <author><name>David</name></author>
    <link href="http://4trabes.com/2013/05/13/practicas-de-verano-en-trabe/"/>
    <updated>2013-05-13T18:00:00+02:00</updated>
    <id>http://4trabes.com/2013/05/13/practicas-de-verano-en-trabe</id>
    <content type="html"><![CDATA[<p>Buscamos a alumnos de últimos años de Ingeniería Informática o Grado en Informática que quieran aprender a desarrollar aplicaciones web en JEE o Ruby on Rails en Trabe. Lo que esperamos de vosotros es:</p>

<ul>
<li>Que sepáis algo de Java, Spring, Hibernate y algún framework MVC.</li>
<li>Que sepáis algo de Ruby on Rails.</li>
<li>Que sepáis lo que es HTML5, CSS3 y JavaScript.</li>
</ul>


<p>No hace falta que seáis unas máquinas (aunque estaría bien xD). La idea es que paséis el verano en nuestra oficina (en el centro de Coruña) trabajando con nosotros
en proyectos reales, aprendiendo todo lo que hace falta para desarrollar una aplicación web. El horario y la remuneración lo negociaremos en función de vuestra
experiencia previa (aunque no es necesaria, esto son unas prácticas) y disponibilidad. Tenemos bastante flexibilidad.</p>

<p>Si os interesa, no nos enviéis un CV estándar. Preferimos que nos contéis en un correo dirigido a <a href="mailto:rrhh@trabesoluciones.com">rrhh@trabesoluciones.com</a> qué estáis estudiando y si ya tenéis alguna experiencia profesional (ya hemos dicho que no es necesaria ¿verdad?), qué os interesa, qué os disgusta, qué queréis aprender, etc.</p>

<p>No os tiréis de la moto. Sed sinceros. Valoraremos tanto el conocimiento como el interés. Si podéis, enseñadnos algo que hayáis hecho antes en otras prácticas/empleo, un proyecto personal
o alguna aportación a proyectos open source. Os dará puntos.</p>

<p>Esperamos vuestros correos.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Remote authentication with devise]]></title>
    <author><name>fuco</name></author>
    <link href="http://4trabes.com/2012/10/31/remote-authentication-with-devise/"/>
    <updated>2012-10-31T10:00:00+01:00</updated>
    <id>http://4trabes.com/2012/10/31/remote-authentication-with-devise</id>
    <content type="html"><![CDATA[<p><a href="http://devise.plataformatec.com.br/">Devise</a> is great. It simplifies lots of tasks related to resource management: authentication, registration, confirmation, etc; and it does it in a clean and highly configurable way. But it is only this great if you are managing your resources locally. Devise has adapters only for models backed up with <a href="http://api.rubyonrails.org/classes/ActiveRecord/Base.html">ActiveRecord</a> or <a href="http://mongoid.org/en/mongoid/index.html">MongoId</a> which means that if you&#8217;re using resources provided by an external webservice you can&#8217;t use Devise.</p>

<p>But don&#8217;t despair.</p>

<h2>Extending Devise</h2>

<p>First of all we have to get a <strong>basic</strong> idea of how Devise authenticates your resources. This explanation might be a bit rough so I&#8217;m going to use the following diagram to ease the explanation (kudos to <a href="https://twitter.com/asischao">asischao</a> for his help).</p>

<p><img src="http://4trabes.com/assets/devise_diagram.jpg" alt="The workflow of a request" /></p>

<ol>
<li>A request to authenticate a resource is received in the Rails app and it matches a route generated by <a href="https://github.com/plataformatec/devise/blob/master/lib/devise/rails/routes.rb#L192">devise_for</a>.</li>
<li>The request is handled (by default) by the <a href="https://github.com/plataformatec/devise/blob/master/app/controllers/devise/sessions_controller.rb">SessionsController</a>, provided by Devise, which delegates the authentication to <a href="https://github.com/hassox/warden">Warden</a></li>
<li>Warden uses one of the <a href="https://github.com/plataformatec/devise/tree/master/lib/devise/strategies">strategies</a> provided by Devise to determine if the resource can be authenticated or not.</li>
</ol>


<p>The output of this process is an authenticated resource. Or not.</p>

<p>So, from this list of steps it seems that we have the following spots to work on:</p>

<ul>
<li>Configure our resource to enable remote authentication.</li>
<li>Create an strategy that authenticates the resources with the external webservice.</li>
</ul>


<h3>Configuring the resource</h3>

<p>Lets assume that our resource is a <a href="http://blog.jayfields.com/2007/10/ruby-poro.html"><em>PORO</em></a> called <code>User</code></p>

<figure class='code'><figcaption><span>User PORO </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">class</span> <span class="nc">User</span>
</span><span class='line'>  <span class="kp">attr_accessor</span> <span class="ss">:id</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>Devise requires some functionallity that we usually have for free when using <code>ActiveRecord</code> resources. As this is not the case we have to do some plumbing: include some <code>ActiveModel</code> modules and extend the class using <code>Devise::Models</code>.</p>

<figure class='code'><figcaption><span>Preparation</span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">class</span> <span class="nc">User</span>
</span><span class='line'>  <span class="kp">include</span> <span class="no">ActiveModel</span><span class="o">::</span><span class="no">Validations</span> <span class="c1">#required because some before_validations are defined in devise</span>
</span><span class='line'>  <span class="kp">extend</span> <span class="no">ActiveModel</span><span class="o">::</span><span class="no">Callbacks</span> <span class="c1">#required to define callbacks</span>
</span><span class='line'>  <span class="kp">extend</span> <span class="no">Devise</span><span class="o">::</span><span class="no">Models</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">define_model_callbacks</span> <span class="ss">:validation</span> <span class="c1">#required by Devise</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>At this point we are ready to configure Devise.</p>

<figure class='code'><figcaption><span>Enable Devise</span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">class</span> <span class="nc">User</span>
</span><span class='line'>  <span class="n">devise</span> <span class="ss">:remote_authenticatable</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Authentication module</h3>

<p>To understand a bit better what we are doing here take a look at the following Devise modules:</p>

<ul>
<li><a href="https://github.com/plataformatec/devise/blob/master/lib/devise/models/authenticatable.rb">Devise::Models::Authenticatable</a>. This module holds all the common bits related to authentication. For now we are only interested in the methods <code>serialize_into_session</code> and <code>serialize_from_session</code>.</li>
<li><a href="https://github.com/plataformatec/devise/blob/master/lib/devise/models/database_authenticatable.rb">Devise::Models::DatabaseAuthenticatable</a>. This module keeps all the logic used when authenticating a resource stored in a database.</li>
</ul>


<p>We have to create a module that performs at least three tasks:</p>

<ul>
<li>Authenticate the resouce using the remote webservice.</li>
<li>Return an array of data that will be used to store a reference to the resource in the session.</li>
<li>Use this session data to re-build the resource.</li>
</ul>


<figure class='code'><figcaption><span>Authenticate using the remote resource</span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">module</span> <span class="nn">Devise</span>
</span><span class='line'>  <span class="k">module</span> <span class="nn">Models</span>
</span><span class='line'>    <span class="k">module</span> <span class="nn">RemoteAuthenticatable</span>
</span><span class='line'>      <span class="kp">extend</span> <span class="no">ActiveSupport</span><span class="o">::</span><span class="no">Concern</span>
</span><span class='line'>
</span><span class='line'>      <span class="k">def</span> <span class="nf">remote_authentication</span><span class="p">(</span><span class="n">authentication_hash</span><span class="p">)</span>
</span><span class='line'>        <span class="c1"># Your logic to authenticate with the external webservice</span>
</span><span class='line'>      <span class="k">end</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p><code>Devise::Models::RemoteAuthenticatable#remote_authentication</code> will be used later (in the Warden strategy) to authenticate the resource using the remote webservice. This method performs almost the same function as <code>Devise::Models::DatabaseAuthenticatable#valid_pasword?</code> in the sense that they both have to return a resource instance if the creedentials are valid or false otherwise.</p>

<figure class='code'><figcaption><span>Serialize/Deserialize </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">module</span> <span class="nn">Devise</span>
</span><span class='line'>  <span class="k">module</span> <span class="nn">Models</span>
</span><span class='line'>    <span class="k">module</span> <span class="nn">RemoteAuthenticatable</span>
</span><span class='line'>      <span class="kp">extend</span> <span class="no">ActiveSupport</span><span class="o">::</span><span class="no">Concern</span>
</span><span class='line'>
</span><span class='line'>      <span class="k">module</span> <span class="nn">ClassMethods</span>
</span><span class='line'>        <span class="k">def</span> <span class="nf">serialize_from_session</span><span class="p">(</span><span class="nb">id</span><span class="p">)</span>
</span><span class='line'>          <span class="n">resource</span> <span class="o">=</span> <span class="nb">self</span><span class="o">.</span><span class="n">new</span>
</span><span class='line'>          <span class="n">resource</span><span class="o">.</span><span class="n">id</span> <span class="o">=</span> <span class="nb">id</span>
</span><span class='line'>          <span class="n">resource</span>
</span><span class='line'>        <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">def</span> <span class="nf">serialize_into_session</span><span class="p">(</span><span class="n">record</span><span class="p">)</span>
</span><span class='line'>          <span class="o">[</span><span class="n">record</span><span class="o">.</span><span class="n">id</span><span class="o">]</span>
</span><span class='line'>        <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>      <span class="k">end</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>We overwrite <code>Devise::Models::ClassMethods#serialize_into_session</code> and <code>Devise::Models::ClassMethods#serialize_from_session</code> because their implementation is tied to resources using some kind of database backup. In this methods you just have to return an array with data that you&#8217;ll use later to re-build the resource instance.</p>

<p>The full code (with comments) of <code>Devise::Models::RemoteAuthenticatable</code> is on this <a href="https://gist.github.com/3916999">gist</a></p>

<h3>Creating an strategy</h3>

<p>Strategies contains the logic used by Warden to authenticate users. They must define an <strong>authenticate!</strong> method, where the request will be processed. Inside this method you can take several actions:</p>

<ul>
<li><code>halt!</code> which halts the cascading of strategies.</li>
<li><code>fail!</code> fails the strategy. Calls halt!</li>
<li><code>success!</code> log in a user.</li>
<li>And other actions. Take a look at the <a href="https://github.com/hassox/warden/wiki/Strategies">documentation</a></li>
</ul>


<p>Because of the conventions used by Devise, the strategy name has to be the same as the name of the module used to authenticate the resource.</p>

<figure class='code'><figcaption><span>Warden strategy for Devise</span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'>  <span class="k">module</span> <span class="nn">Devise</span>
</span><span class='line'>    <span class="k">module</span> <span class="nn">Strategies</span>
</span><span class='line'>      <span class="k">class</span> <span class="nc">RemoteAuthenticatable</span> <span class="o">&lt;</span> <span class="no">Authenticatable</span>
</span><span class='line'>        <span class="k">def</span> <span class="nf">authenticate!</span>
</span><span class='line'>          <span class="n">auth_params</span> <span class="o">=</span> <span class="n">authentication_hash</span>
</span><span class='line'>          <span class="n">auth_params</span><span class="o">[</span><span class="ss">:password</span><span class="o">]</span> <span class="o">=</span> <span class="n">password</span>
</span><span class='line'>
</span><span class='line'>          <span class="n">resource</span> <span class="o">=</span> <span class="n">mapping</span><span class="o">.</span><span class="n">to</span><span class="o">.</span><span class="n">new</span>
</span><span class='line'>
</span><span class='line'>          <span class="k">return</span> <span class="nb">fail</span><span class="o">!</span> <span class="k">unless</span> <span class="n">resource</span>
</span><span class='line'>
</span><span class='line'>          <span class="k">if</span> <span class="n">validate</span><span class="p">(</span><span class="n">resource</span><span class="p">){</span> <span class="n">resource</span><span class="o">.</span><span class="n">remote_authentication</span><span class="p">(</span><span class="n">auth_params</span><span class="p">)</span> <span class="p">}</span>
</span><span class='line'>            <span class="n">success!</span><span class="p">(</span><span class="n">resource</span><span class="p">)</span>
</span><span class='line'>          <span class="k">end</span>
</span><span class='line'>        <span class="k">end</span>
</span><span class='line'>      <span class="k">end</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>  <span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>The previous code is pretty straightforward. We create a new resource and using <code>Devise::Models::RemoteAuthenticatable#remote_authentication</code> we authenticate it. If the authentication succeeds we mark the request as valid with <code>success!</code>.</p>

<p><a href="https://gist.github.com/3917079">Gist</a> with the code, and comments, of this strategy.</p>

<h2>Putting everything together</h2>

<p>So, to sum up, this solution is composed of:</p>

<ul>
<li><code>Devise::Models::RemoteAuthenticatable</code>, a module used by Devise to authenticate the resource.</li>
<li><code>Devise::Strategies::RemoteAuthenticatable</code>, a class implementing a Warden strategy.</li>
</ul>


<p>Finally, don&#8217;t forguet to configure Devise (in config/initializers/devise.rb) to use all the stuff we have done here : )</p>

<figure class='code'><figcaption><span>Configure Devise </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'>  <span class="n">config</span><span class="o">.</span><span class="n">warden</span> <span class="k">do</span> <span class="o">|</span><span class="n">manager</span><span class="o">|</span>
</span><span class='line'>     <span class="n">manager</span><span class="o">.</span><span class="n">strategies</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="ss">:remote</span><span class="p">,</span> <span class="no">Devise</span><span class="o">::</span><span class="no">Strategies</span><span class="o">::</span><span class="no">RemoteAuthenticatable</span><span class="p">)</span>
</span><span class='line'>     <span class="n">manager</span><span class="o">.</span><span class="n">default_strategies</span><span class="p">(</span><span class="ss">:scope</span> <span class="o">=&gt;</span> <span class="ss">:user</span><span class="p">)</span><span class="o">.</span><span class="n">unshift</span> <span class="ss">:remote</span>
</span><span class='line'>  <span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>



]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[How to: automatically config a cloned repo]]></title>
    <author><name>fuco</name></author>
    <link href="http://4trabes.com/2012/10/18/how-to-automatically-config-a-cloned-repo/"/>
    <updated>2012-10-18T10:13:00+02:00</updated>
    <id>http://4trabes.com/2012/10/18/how-to-automatically-config-a-cloned-repo</id>
    <content type="html"><![CDATA[<p><strong>Important</strong>: If the version of <a href="http://git-scm.com/">Git</a> you are running is under <em>1.7.7</em> this tip won&#8217;t run for you.</p>

<h2>The problem</h2>

<p>The other day I ran into a problem because of using the same computer for work and personal projects: I was commiting with the same user for both kind of projects, which I don&#8217;t want.</p>

<p>I want different <code>user.email</code> config setting for each type of project but I didn&#8217;t want to do it manually.</p>

<h2>The solution</h2>

<p>So I came up with a simple solution. It&#8217;s composed of four parts:</p>

<ul>
<li>A particular, but not fancy, dir layout.</li>
<li>A config file per each type of repo (personal or work).</li>
<li>A <em>bash</em> function.</li>
<li>A <em>git</em> alias.</li>
</ul>


<p>Using all this, as you&#8217;ll see, each time I clone a work or personal repo I end up with a different value of <code>user.email</code> depending on the type of project.</p>

<h3>Dirs layout</h3>

<p>Repos for personal and work projects must be contained into separated dirs so they have different config files. This is my layout:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="o">[</span>madtrick@madbook <span class="o">{</span> repos <span class="o">}</span> ruby-1.9.2-p180 <span class="o">]</span>
</span><span class='line'>&gt;&gt;tree -L 1 -a personal/
</span><span class='line'>personal/
</span><span class='line'>├── .gitconfig.clone
</span><span class='line'>├── cartos
</span><span class='line'>├── coello
</span><span class='line'>├── dotfiles
</span><span class='line'>...
</span></code></pre></td></tr></table></div></figure>




<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="o">[</span>madtrick@madbook <span class="o">{</span> repos <span class="o">}</span> ruby-1.9.2-p180 <span class="o">]</span>
</span><span class='line'>&gt;&gt;tree -L 1 -a trabe/
</span><span class='line'>trabe/
</span><span class='line'>├── .gitconfig.clone
</span><span class='line'>├── 4trabes
</span><span class='line'>└── trabenet
</span><span class='line'>...
</span></code></pre></td></tr></table></div></figure>


<h3>Config file</h3>

<p>The file <code>.gitconfig.clone</code> is where you place your specific bits of configuration. The syntax used is the same that you&#8217;ll use with <code>git config</code></p>

<p>For example, the <code>.gitconfig.clone</code> for my work projects is this:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>user.email<span class="o">=</span>farruco.sanjurjo@trabesoluciones.com
</span></code></pre></td></tr></table></div></figure>


<h3>Bash function</h3>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>  <span class="k">function </span>git_clone_config<span class="o">(){</span>
</span><span class='line'>    <span class="nb">local </span><span class="nv">options</span><span class="o">=</span><span class="s2">&quot;&quot;</span>
</span><span class='line'>    <span class="k">if</span> <span class="o">[[</span> -f <span class="nv">$PWD</span>/.gitconfig.clone <span class="o">]]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">      while </span><span class="nb">read </span>line ; <span class="k">do</span>
</span><span class='line'><span class="k">        </span><span class="nv">options</span><span class="o">=</span><span class="nv">$options</span><span class="s2">&quot; &quot;</span><span class="nv">$line</span>
</span><span class='line'>      <span class="k">done</span> &lt; <span class="nv">$PWD</span>/.gitconfig.clone
</span><span class='line'>      <span class="nb">echo</span> <span class="s2">&quot;$options&quot;</span>
</span><span class='line'>    <span class="k">fi</span>
</span><span class='line'>  <span class="o">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>When called, this function will look for a file called <code>.gitconfig.clone</code> in the current directory. If it exists, its lines will be returned (<em>echoed</em>).</p>

<h3>Git alias</h3>

<p>And to finish the git alias:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="o">[</span><span class="nb">alias</span><span class="o">]</span>
</span><span class='line'>  ...
</span><span class='line'>  <span class="nv">cl</span> <span class="o">=</span> !bash -ic <span class="s1">&#39;git_clone_config&#39;</span> | xargs -I configvalues git clone --config configvalues --
</span></code></pre></td></tr></table></div></figure>


<h2>Summary</h2>

<p>When this alias is used, <code>git cl REPO_URL</code>, the bash function will be run to look for the <code>.gitconfig.clone</code> file. If that file exists its lines will be read and used in <code>git clone --config CONFIG_LINES REPO_URL</code>. This way, when git initializes the cloned repo it&#8217;ll use the config options given with <code>--config</code> flag.</p>

<p>Currently I&#8217;m using this just for the <code>user.email</code> config setting but it could be used to apply any of the <a href="http://git-scm.com/docs/git-config">supported config settings</a>.</p>

<p>You can find my gitconfig file and other dot-stuff on my <a href="https://github.com/madtrick/dotfiles">dotfiles repo on Github</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Cerrando modales: ¿Quién cierra a quién?]]></title>
    <author><name>Asís &amp; Fuco</name></author>
    <link href="http://4trabes.com/2012/08/28/cerrando-modales-quien-cierra-a-quien/"/>
    <updated>2012-08-28T12:13:00+02:00</updated>
    <id>http://4trabes.com/2012/08/28/cerrando-modales-quien-cierra-a-quien</id>
    <content type="html"><![CDATA[<h3>Nota introductoria</h3>

<p>Los conceptos que vamos a tratar en este post los ejemplificamos con <a href="http://documentcloud.github.com/backbone/">Backbone</a>. Por si no lo conoces o no tienes muy claro que es, aquí te dejamos una brevisima introducción:</p>

<p><em>Backbone</em> es uno de los múltiples <em>frameworks</em> <em>Javascript</em> (<a href="http://addyosmani.github.com/todomvc/">1</a> y <a href="http://codebrief.com/2012/01/the-top-10-javascript-mvc-frameworks-reviewed/">2</a>) que implementan el paradigma <em>MVC</em> en el navegador. En Backbone el rol de controlador lo juegan los componentes que sus desarrolladores denominan <em>Views</em> (Backbone.View) y el papel de vistas se implementa con cualquiera de las librerías de <em>templating</em> existentes (Eco, Moustache, etc.). Por lo tanto, una vez dicho esto, ten en cuenta que cuando hablemos de vista probablemente nos refiramos a controladores. Sea como sea, intentaremos ser lo más claros posible :___ )</p>

<p>Actualización: Realmente no está tan claro que Backbone siga el paradigma <em>MVC</em> (<a href="http://addyosmani.github.com/backbone-fundamentals/#fundamentals">1</a>, <a href="http://lostechies.com/derickbailey/2011/12/23/backbone-js-is-not-an-mvc-framework/">2</a> y <a href="http://backbonejs.org/#FAQ-mvc">3</a>) pero durante el post seguiremos la convención de Vista =~ Plantilla HTML y Controlador =~ Backbone.View.</p>

<h3>Al tomate</h3>

<p>En Trabe estamos utilizando/probando Backbone en una aplicación en la que hay vistas que se van a mostrar tanto de manera modal como no modal. Como la lógica de estas vistas es independiente de si se están mostrando de manera modal o no, queremos separar la gestión de la ventana modal de su propio contenido y así facilitar la reutilización/refactorización/mantenimiento del código. Para explicarnos mejor vamos a utilizar el siguiente gráfico:</p>

<p><img class="center" src="http://4trabes.com/assets/modal_and_modalized_views.jpg" title="&#34;Vista modal y vista modalizada&#34;" alt="&#34;Vista modal y vista modalizada&#34;"></p>

<p>Habrá una vista de Backbone (ModalView en el gráfico) encargada de gestionar la ventana modal (abrir, cerrar, pelearse con el <em>plugin</em> que &#8220;pinta&#8221; el modal) y una vista modalizada (ModalizedView) que en el caso del gráfico gestiona un formulario.</p>

<p>Hasta aquí todo va muy bien, pero existe un punto en el que, digamos, chocan las responsibilidades de la <em>ModalView</em> y de la <em>ModalizedView</em>. ¿Quién cierra la vista modal? Si es <em>ModalizedView</em> la que cierra el modal, estamos asignándole lógica que no le corresponde con lo que luego será más difícil de mantener o reutilizar. Así que será <em>ModalView</em> la que se cierre a sí misma; pero ¿cómo le indicamos a la ventana modal que puede cerrarse? Podemos hacerlo utilizando:</p>

<ul>
<li>Una referencia a la vista modal</li>
<li>Eventos o promesas</li>
</ul>


<p>El código que utilizaríamos para mostrar la ventana modal sería algo así como:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='coffeescript'><span class='line'><span class="nv">modal = </span><span class="k">new</span> <span class="nx">ModalView</span><span class="p">(...)</span>
</span><span class='line'><span class="nv">modalized = </span><span class="k">new</span> <span class="nx">ModalizedView</span><span class="p">(...)</span>
</span><span class='line'>
</span><span class='line'><span class="nx">modal</span><span class="p">.</span><span class="nx">modalize</span><span class="p">(</span><span class="nx">modalized</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>Ahora veremos cómo implementar <strong>ModalizedView</strong> y <strong>ModalView</strong> utilizando cada opción.</p>

<h2>Referencia a la vista modal</h2>

<p>La vista a modalizar tiene una referencia a la vista modal. Cuando quiere cerrarla simplemente invoca un método en dicha vista.</p>

<figure class='code'><figcaption><span>Usando una referencia a la vista modal </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
</pre></td><td class='code'><pre><code class='coffeescript'><span class='line'><span class="k">class</span> <span class="nx">ModalizedView</span> <span class="k">extends</span> <span class="nx">Backbone</span><span class="p">.</span><span class="nx">View</span>
</span><span class='line'>  <span class="nv">handleDone : </span><span class="o">-&gt;</span>
</span><span class='line'>    <span class="c1"># The user is done, close the modal view!</span>
</span><span class='line'>    <span class="nx">@get</span><span class="p">(</span><span class="s1">&#39;modal_view&#39;</span><span class="p">).</span><span class="nx">close</span><span class="p">()</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nx">ModalView</span> <span class="k">extends</span> <span class="nx">Backbone</span><span class="p">.</span><span class="nx">View</span>
</span><span class='line'>  <span class="nv">modalize : </span><span class="nf">(view) -&gt;</span>
</span><span class='line'>    <span class="c1"># Show the view inside the modal</span>
</span><span class='line'>    <span class="c1"># ...</span>
</span><span class='line'>    <span class="c1"># Set a reference to the modal view</span>
</span><span class='line'>    <span class="nx">view</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;modal_view&#39;</span><span class="p">)</span> <span class="o">=</span> <span class="nx">modal_view</span>
</span><span class='line'>
</span><span class='line'>  <span class="nv">close : </span><span class="o">-&gt;</span>
</span><span class='line'>    <span class="c1"># Close modal window</span>
</span><span class='line'>
</span><span class='line'><span class="nv">modal = </span><span class="k">new</span> <span class="nx">ModalView</span><span class="p">(...)</span>
</span><span class='line'><span class="nv">modalized = </span><span class="k">new</span> <span class="nx">ModalizedView</span><span class="p">(...)</span>
</span><span class='line'>
</span><span class='line'><span class="nx">modal</span><span class="p">.</span><span class="nx">modalize</span><span class="p">(</span><span class="nx">modalized</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>En este caso los problemos que nos encontramos son los siguientes:</p>

<ul>
<li>Si cambiamos el API de la vista modal podemos afectar a las vistas que la utilicen.</li>
<li>Estamos añadiendo lógica que no le corresponde a la vista modalizada.</li>
<li>En el caso del ejemplo, el método <em>handleDone</em> no podría ser reutilizado, directamente, si la vista no es modal (no tendríamos una referencia al <em>modal_view</em> correspondiente).</li>
</ul>


<h2>Eventos o promesas</h2>

<p>La utilización de eventos y promesas comparte ventajas e inconvenientes. Entre las ventajas están:</p>

<ul>
<li>Desacoplan las dos vistas manteniéndolas independientes. O casi ;)</li>
<li>Tanto las promesas como los eventos pueden ser utilizadas no solo por la vista modal sino por otros componentes para tener constancia del estado de la vista modalizada.</li>
</ul>


<p>Y entre las desventajas:</p>

<ul>
<li>Ambas vistas tienen que adaptar un &#8220;protocolo&#8221; común (ya sea a través de los eventos o la promesa).</li>
<li>En ambos casos dependeremos de una librería que facilite la utilización de promesas o eventos (por ejemplo, <a href="http://jquery.com/">jQuery</a>).</li>
<li>La lógica correspondiente a lanzar un evento o resolver una promesa no está directamente relacionada con el contexto en el que se encuentra. Claro que este es el precio a pagar por las ventajas que ofrecen.</li>
</ul>


<h3>Eventos</h3>

<p>La vista a &#8220;modalizar&#8221; lanza un evento que la vista modal captura y como consecuencia se cierra.</p>

<figure class='code'><figcaption><span>Usando eventos</span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
</pre></td><td class='code'><pre><code class='coffeescript'><span class='line'><span class="k">class</span> <span class="nx">ModalizedView</span> <span class="k">extends</span> <span class="nx">Backbone</span><span class="p">.</span><span class="nx">View</span>
</span><span class='line'>  <span class="nv">handleDone : </span><span class="o">-&gt;</span>
</span><span class='line'>    <span class="c1"># The user is done, signal it using an event</span>
</span><span class='line'>    <span class="nx">@trigger</span> <span class="s2">&quot;modal:close&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nx">ModalView</span> <span class="k">extends</span> <span class="nx">Backbone</span><span class="p">.</span><span class="nx">View</span>
</span><span class='line'>  <span class="nv">modalize : </span><span class="nf">(view) -&gt;</span>
</span><span class='line'>    <span class="c1"># Show the view inside the modal</span>
</span><span class='line'>    <span class="nx">view</span><span class="p">.</span><span class="kc">on</span> <span class="s2">&quot;modal:close&quot;</span><span class="p">,</span> <span class="o">-&gt;</span>
</span><span class='line'>      <span class="c1"># Close modal window</span>
</span><span class='line'>
</span><span class='line'><span class="nv">modal = </span><span class="k">new</span> <span class="nx">ModalView</span><span class="p">(...)</span>
</span><span class='line'><span class="nv">modalized = </span><span class="k">new</span> <span class="nx">ModalizedView</span><span class="p">(...)</span>
</span><span class='line'>
</span><span class='line'><span class="nx">modal</span><span class="p">.</span><span class="nx">modalize</span><span class="p">(</span><span class="nx">modalized</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Promesas</h3>

<p>Por promesas nos referimos a los <a href="http://api.jquery.com/category/deferred-object/">Deferred/Promise</a> de <a href="http://jquery.com/">jQuery</a>. Una promesa es un objeto que &#8220;represents the eventual value returned from the single completion of an operation&#8221; (<a href="http://wiki.commonjs.org/wiki/Promises/A">CommonJS/Promises</a>).</p>

<p>Las vistas a modalizar tienen disponible una promesa que utilizan para indicar que ya han cumplido con su cometido. Esta promesa será utilizada por la vista modal para determinar cuándo tiene que cerrarse.</p>

<figure class='code'><figcaption><span>Usando promesas</span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
</pre></td><td class='code'><pre><code class='coffeescript'><span class='line'><span class="k">class</span> <span class="nx">ModalizedView</span> <span class="k">extends</span> <span class="nx">Backbone</span><span class="p">.</span><span class="nx">View</span>
</span><span class='line'>  <span class="nv">initialize : </span><span class="o">-&gt;</span>
</span><span class='line'>    <span class="vi">@_deferred  = </span><span class="nx">$</span><span class="p">.</span><span class="nx">Deferred</span><span class="p">()</span>
</span><span class='line'>    <span class="vi">@promise    = </span><span class="nx">@_deferred</span><span class="p">().</span><span class="nx">promise</span><span class="p">()</span>
</span><span class='line'>
</span><span class='line'>  <span class="nv">handleDone : </span><span class="o">-&gt;</span>
</span><span class='line'>    <span class="nx">@_deferred</span><span class="p">.</span><span class="nx">resolve</span><span class="p">()</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nx">ModalView</span> <span class="k">extends</span> <span class="nx">Backbone</span><span class="p">.</span><span class="nx">View</span>
</span><span class='line'>  <span class="nv">modalize : </span><span class="nf">(view) -&gt;</span>
</span><span class='line'>    <span class="c1"># Show the view inside the modal</span>
</span><span class='line'>    <span class="c1"># Attach a done callback which will close the modal window</span>
</span><span class='line'>    <span class="nx">view</span><span class="p">.</span><span class="nx">promise</span><span class="p">.</span><span class="nx">done</span> <span class="o">-&gt;</span>
</span><span class='line'>      <span class="c1"># close modal window</span>
</span><span class='line'>
</span><span class='line'><span class="nv">modal = </span><span class="k">new</span> <span class="nx">ModalView</span><span class="p">(...)</span>
</span><span class='line'><span class="nv">modalized = </span><span class="k">new</span> <span class="nx">ModalizedView</span><span class="p">(...)</span>
</span><span class='line'>
</span><span class='line'><span class="nx">modal</span><span class="p">.</span><span class="nx">modalize</span><span class="p">(</span><span class="nx">modalized</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<h2>¿Conclusiones?</h2>

<p>Las mejores soluciones son la del evento y la de la promesa. ¿Y entre estas dos? Nos gusta más la promesa porque lleva &#8220;de serie&#8221; la distinción entre una finalización &#8220;exitosa&#8221; (resolve/done) y una &#8220;fallida&#8221; (reject/fail), que en el caso de los modales es bastante común. Además, es un estándar de facto &#8211; al menos en jQuery &#8211; lo que nos permite aprovechar todas las herramientas asociadas.</p>
]]></content>
  </entry>
  
</feed>
