<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Rafa Garcia.net - Blog</title>
	<atom:link href="http://blog.rafagarcia.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.rafagarcia.net</link>
	<description>Desvaríos varios sobre ruby, rails, linux, capistrano, ... y muchas cosas más!</description>
	<lastBuildDate>Sun, 22 Aug 2010 13:35:01 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Comandos de autocompletado de Vim</title>
		<link>http://blog.rafagarcia.net/2010/08/21/comandos-de-autocompletado-de-vim/</link>
		<comments>http://blog.rafagarcia.net/2010/08/21/comandos-de-autocompletado-de-vim/#comments</comments>
		<pubDate>Sat, 21 Aug 2010 16:08:44 +0000</pubDate>
		<dc:creator>Rafa García</dc:creator>
				<category><![CDATA[vim]]></category>

		<guid isPermaLink="false">http://blog.rafagarcia.net/?p=145</guid>
		<description><![CDATA[Estos días estoy leyendo el libro &#8220;CSS the missing manual&#8221; y el autocompletado de Vim me viene de maravilla,  es capaz de autocompletar las propiedades y los valores. Esto es lo que me ha motivado a escribir el siguiente post. Vim tiene varios comandos de autocompletado, personalmente suelo usar omni completion y el comando que busca [...]]]></description>
			<content:encoded><![CDATA[<p>Estos días estoy leyendo el libro &#8220;CSS the missing manual&#8221; y el autocompletado de Vim me viene de maravilla,  es capaz de autocompletar las propiedades y los valores. Esto es lo que me ha motivado a escribir el siguiente post.</p>
<p>Vim tiene varios comandos de autocompletado, personalmente suelo usar omni completion y el comando que busca palabras del fichero actual pero hay otros que conviene conocerlos y <strong>habituarse a usarlos</strong>.</p>
<p>Estos comandos son llamados desde el modo de inserción con la combinación de teclas CTRL-X y luego CTRL-&lt;modo de autocompletado&gt;. Cuando empiezas a escribir una palabra invocas el comando, se abrirá un popup con las coincidencias de la palabra que hay justo delante del cursor y para moverte entre ellas CTRL-N para saltar a la siguiente(Next) y CTRL-P para volver a la previa (Previous).</p>
<p>Ahora que sabemos como manejarlo vamos a ver algunos de los diferentes modos:</p>
<p style="padding-left: 30px;"><strong>Omni completion</strong></p>
<p style="padding-left: 60px;">Para invocarlo CTRL-X_CTRL-O , este comando es &#8220;inteligente&#8221;(en cierta medida y según la configuración) porque las coincidencias que te ofrecerá estarán relacionadas con el contexto.</p>
<p style="padding-left: 60px;">Si abrimos un fichero con un script en Ruby, escribimos  &#8221;5.&#8221; (cinco punto) y seguido pulsamos CTRL-X_CTRL-O nos mostrará todos los operadores y métodos de la clase Integer. Por esto digo que tiene algo de inteligente.</p>
<p style="padding-left: 60px;">Ocurre algo por el estilo si usamos este modo con un fichero CSS:</p>
<p style="padding-left: 60px;"><a href="http://blog.rafagarcia.net/wp-content/uploads/2010/08/omni_css_web.png"><img class="aligncenter size-medium wp-image-146" title="omni_completion_css" src="http://blog.rafagarcia.net/wp-content/uploads/2010/08/omni_css_web-300x290.png" alt="Ejemplo de omni completion de un fichero css" width="300" height="290" /></a></p>
<p style="padding-left: 30px; text-align: center;"><em>Simplemente invoqué el comando y me mostró las coincidencias</em></p>
<p style="padding-left: 30px;"><strong>Autocompletado con palabras del fichero actual:</strong></p>
<p style="padding-left: 60px;">Para invocarlo CTRL-X_CTRL-N. Este comando no es inteligente, simplemente autocompleta la palabra buscándola entre las palabras claves de fichero actual.</p>
<p style="padding-left: 60px;">Imaginad que tenemos el siguiente texto y tenemos que desarrollar una tesis sobre ello:</p>
<p style="padding-left: 60px;">&#8220;﻿﻿El <a title="Músculo" href="http://es.wikipedia.org/wiki/M%C3%BAsculo">músculo</a> <strong>esternocleidomastoideo</strong> (<em>Sternocleidomastoideus</em>) es un músculo de la cara lateral del cuello, en la región anterolateral; largo, robusto, constituido en su tramo torácico por dos <em>manojos</em> o <em>cabezas</em>: la <strong>esternal</strong>, cilíndrica, y la<strong>clavicular</strong>, aplanada. Entre ambas dejan el triángulo de Sédillot, que permite un acceso a la vena yugular interna para establecer una vía.&#8221; &#8211; <em><a href="http://es.wikipedia.org/wiki/M%C3%BAsculo_esternocleidomastoideo" target="_blank">Texto sacado de la wikipedia</a>.</em></p>
<p style="padding-left: 60px;">Escribir la palabra esternocle&#8230; es largo y tortuoso, con este comando será menos tortuoso.</p>
<p style="padding-left: 30px;"><strong>Autocompletado con palabras del fichero actual y los incluidos:</strong></p>
<p style="padding-left: 60px;">Para invocarlo CTRL-X_CTRL-I. Este comando funciona exactamente igual al anterior pero además de buscar en el fichero local busca las palabras clave en los ficheros incluidos.</p>
<p style="padding-left: 60px;">Este comando según como tengas configurado &#8216;complete&#8217; funciona prácticamente igual que CTRL-N , personalmente uso este último porque es mas fácil de recordar y configurable.</p>
<p style="padding-left: 30px;"><strong>Autocompletado de una línea entera:</strong></p>
<p style="padding-left: 60px;">Para invocarlo CTRL-X_CTRL-L. Este comando no acostumbro a usarlo porque intento ser DRY, si lo usas mucho programando eres poco DRY <img src='http://blog.rafagarcia.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p style="padding-left: 60px;">Un ejemplo gráfico con un fichero CSS:</p>
<p style="padding-left: 60px; text-align: center;"><a href="http://blog.rafagarcia.net/wp-content/uploads/2010/08/autocompletado_linea_css_web.png"><img class="aligncenter size-medium wp-image-147" title="autocompletado_linea_css_web" src="http://blog.rafagarcia.net/wp-content/uploads/2010/08/autocompletado_linea_css_web-300x143.png" alt="Ejemplo de autocompletado de línea en un fichero CSS" width="300" height="143" /></a><em>Empecé a escribir la propiedad &#8220;font&#8221; e invoqué el comando.</em></p>
<p style="padding-left: 30px;"><strong>Autocompletado de tags:</strong></p>
<p style="padding-left: 60px;">Para invocarlo CTRL-X_CTRL-]. Este comando autocompleta el texto delante del cursor buscando la coincidencia en la lista de tags.</p>
<p style="padding-left: 60px;">La lista de tags hay que generarla previamente. En proyectos Rails usando  rails.vim tenemos el comando :Rtags o lo puedes hacer a mano con Exuberant Ctags. Este es un autocompletado que no uso así que no me viene a la cabeza un caso de uso concreto pero he pensado que podía ser útil a otras personas.</p>
<p style="padding-left: 30px;"><strong>Autocompletado de ficheros:</strong></p>
<p style="padding-left: 60px;">Para invocarlo CTRL-X_CTRL-F. Este comando autocompleta paths y ficheros desde el directorio en el que te encuentras actualmente. Funciona muy bien porque reconoce rutas relativas y absolutas.</p>
<p style="padding-left: 60px;">Un ejemplo gráfico con un fichero HTML:</p>
<p style="padding-left: 60px;"><a href="http://blog.rafagarcia.net/wp-content/uploads/2010/08/autocompletado_ficheros_html_web.png"><img class="aligncenter size-medium wp-image-149" title="autocompletado_ficheros_html" src="http://blog.rafagarcia.net/wp-content/uploads/2010/08/autocompletado_ficheros_html_web-300x77.png" alt="Ejemplo de autocompletado de ficheros en un fichero HTML" width="300" height="77" /></a></p>
<p style="padding-left: 60px; text-align: center;"><em>Invoqué autocompletado sin escribir nada</em></p>
<p style="padding-left: 30px;"> </p>
<p>Hay otros comandos de autocompletado que no he nombrado(por ej. las sugerencias de ortografía o el autocompletado de definiciones y macros). Si los queréis ver todos o profundizar sobre el tema os recomiendo la ayuda de Vim <strong>:help ins-completion</strong></p>
<p>¡Esto es todo por hoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rafagarcia.net/2010/08/21/comandos-de-autocompletado-de-vim/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Prompt dialog y capybara</title>
		<link>http://blog.rafagarcia.net/2010/06/11/prompt-dialog-y-capybara/</link>
		<comments>http://blog.rafagarcia.net/2010/06/11/prompt-dialog-y-capybara/#comments</comments>
		<pubDate>Fri, 11 Jun 2010 19:52:50 +0000</pubDate>
		<dc:creator>Rafa García</dc:creator>
				<category><![CDATA[rails]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[cucumber]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[test]]></category>

		<guid isPermaLink="false">http://blog.rafagarcia.net/?p=138</guid>
		<description><![CDATA[Escribiendo los tests de borrado de items de una aplicación me encontré con una cosa muy molesta al usar el driver de selenium. Al aparecer el diálogo de confirmación de borrado se quedaba esperando que alguien pulsara el botón de aceptar para empezar con el borrado. Casualmente en el stand up meeting matinal de hoy [...]]]></description>
			<content:encoded><![CDATA[<p>Escribiendo los tests de borrado de items de una aplicación me encontré con una cosa muy molesta al usar el driver de selenium. Al aparecer el diálogo de confirmación de borrado se quedaba esperando que alguien pulsara el botón de aceptar para empezar con el borrado.</p>
<p>Casualmente en el stand up meeting matinal de hoy uno de los chicos de Chile(<a href="http://blog.leosoto.com/" target="_blank">Leo</a>) tuvo el mismo problema y las soluciones han sido similares. Aquí os las dejo por si os ocurre lo mismo.</p>
<p>La versión para cucumber:</p>
<script src="http://gist.github.com/434446.js"></script>
<p>Y la solución para RSpec de <a href="http://blog.leosoto.com/" target="_blank">Leo</a>:</p>
<script src="http://gist.github.com/434460.js"></script>
<p><br class="spacer_" /></p>
<p>Si no usas selenium(el tag @javascript en cucumber) y usas la emulación de javascript de capybara(tag  ﻿@emulate_rails_javascript) la pulsación del botón aceptar en el diálogo de confirmación es automágica y no necesitas nada mas.</p>
<p><br class="spacer_" /></p>
<p>Saludos y que os vaya bonito.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rafagarcia.net/2010/06/11/prompt-dialog-y-capybara/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Capistrano: Submódulos de los submódulos</title>
		<link>http://blog.rafagarcia.net/2010/05/13/capistrano-submodulos-mas-submodulos-mas-submodulos/</link>
		<comments>http://blog.rafagarcia.net/2010/05/13/capistrano-submodulos-mas-submodulos-mas-submodulos/#comments</comments>
		<pubDate>Thu, 13 May 2010 02:49:43 +0000</pubDate>
		<dc:creator>Rafa García</dc:creator>
				<category><![CDATA[capistrano]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[submodulos]]></category>

		<guid isPermaLink="false">http://blog.rafagarcia.net/?p=135</guid>
		<description><![CDATA[Últimamente al &#8220;deployar&#8221; mi pet-project dejaba de funcionar la aplicación, passenger no arrancaba. Mirando los logs me di cuenta de que la dependencia de prawn y prawn-labels me estropeaban el deploy. Recomiendan instalar prawn (y prawn-labels) como submódulo y eso por suerte está contemplado en los despliegues con Capistrano, al menos parcialmente, añadiendo la siguiente [...]]]></description>
			<content:encoded><![CDATA[<p>Últimamente al &#8220;deployar&#8221; mi pet-project dejaba de funcionar la aplicación, passenger no arrancaba. Mirando los logs me di cuenta de que la dependencia de prawn y prawn-labels me estropeaban el deploy.</p>
<p>Recomiendan instalar prawn (y prawn-labels) como submódulo y eso por suerte está contemplado en los despliegues con Capistrano, al menos parcialmente, añadiendo la siguiente variable a nuestro deploy.rb:</p>
<p><code> set :git_enable_submodules, true </code> <em> </em></p>
<p><em>Ver fichero: capistrano/lib/capistrano/recipes/deploy/scm/git.rb</em></p>
<p>De todos modos al hacer un nuevo despliegue la cosa seguía fallando. Siguiendo el proceso a mano resulta que Capistrano solo hace el init y update de los submódulos &#8220;raíz&#8221;. Quiero decir que si estos tienen mas submódulos no son tenidos en cuenta.</p>
<p>Finalmente dándome un paseo por Internet encontré la solución, se trata de la gema <a href="http://github.com/morhekil/capistrano-deepmodules">capistrano-deepmodules de morhekil</a>.  La cosa es muy simple:</p>
<ol>
<li>Instalamos la gema &#8220;morhekil-capistrano-deepmodules&#8221;</li>
<li>Añadimos en nuestro deploy.rb: &#8220;require &#8216;capistrano/deepmodules&#8217;&#8221;</li>
<li>(Opcional) podemos quitar de nuestro deploy.rb: &#8220;set :git_enable_submodules, true&#8221;</li>
</ol>
<p><br class="spacer_" /></p>
<p>That&#8217;s all folks!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rafagarcia.net/2010/05/13/capistrano-submodulos-mas-submodulos-mas-submodulos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Git vía SSH y guebs.com</title>
		<link>http://blog.rafagarcia.net/2010/04/06/git-via-ssh-y-guebs-com/</link>
		<comments>http://blog.rafagarcia.net/2010/04/06/git-via-ssh-y-guebs-com/#comments</comments>
		<pubDate>Tue, 06 Apr 2010 15:46:03 +0000</pubDate>
		<dc:creator>Rafa García</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[git]]></category>

		<guid isPermaLink="false">http://blog.rafagarcia.net/?p=122</guid>
		<description><![CDATA[Montar un repositorio con Git y guebs.com es prácticamente lo mismo que en otros servidores, existe la sutil diferencia de que el puerto que se usa para SSH no es el estándar. Conectamos a nuestro servidor e iniciamos el repositorio con git: $ ssh usuario@rafagarcia.net -p 333 $ mkdir foo.git $ cd foo.git $ git [...]]]></description>
			<content:encoded><![CDATA[<p>Montar un repositorio con Git y guebs.com es prácticamente lo mismo que en otros servidores, existe la sutil diferencia de que el puerto que se usa para SSH no es el estándar.</p>
<p>Conectamos a nuestro servidor e iniciamos el repositorio con git:</p>
<p><code><br />
   $ ssh usuario@rafagarcia.net -p 333<br />
   $ mkdir foo.git<br />
   $ cd foo.git<br />
   $ git --bare init<br />
</code></p>
<p><em>Nota: Paso la opción &#8220;bare&#8221; para que en ese repositorio solo almacene los deltas y no los ficheros, si vas a navegar por los ficheros desde el servidor no la pongas.</em></p>
<p><br class="spacer_" /></p>
<p>Ahora para añadir ficheros desde nuestro repositorio local:</p>
<p><code><br />
  $ mkdir foo<br />
  $ cd foo<br />
  $ git init<br />
  $ touch README<br />
  $ git add README<br />
  $ git commit -m 'my first commit'<br />
  $ git remote add origin <strong>ssh://usuario@hostname:333/home/usuario/foo.git</strong><br />
  $ git push origin master<br />
</code></p>
<p><em>Nota: No olvidar poner el protocolo en la url (&#8220;ssh://&#8221;).</em></p>
<p><br class="spacer_" /></p>
<p>Esta información ha sido fusilada de los siguientes sitios(thanks!):</p>
<ul>
<li><a href="http://blog.commonthread.com/2008/4/14/setting-up-a-git-server " target="_blank">http://blog.commonthread.com/2008/4/14/setting-up-a-git-server </a></li>
<li><a href="http://www.bramschoenmakers.nl/en/node/720" target="_blank">http://www.bramschoenmakers.nl/en/node/720</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.rafagarcia.net/2010/04/06/git-via-ssh-y-guebs-com/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reinstalando el sistema</title>
		<link>http://blog.rafagarcia.net/2010/02/22/reinstalando-el-sistema/</link>
		<comments>http://blog.rafagarcia.net/2010/02/22/reinstalando-el-sistema/#comments</comments>
		<pubDate>Mon, 22 Feb 2010 11:41:18 +0000</pubDate>
		<dc:creator>Rafa García</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[sistemas]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://blog.rafagarcia.net/?p=104</guid>
		<description><![CDATA[Este fin de semana iba a hacer una copia de seguridad, instalé lucky backup, lo configuré, lo dejé trabajando y cuando volví mi sistema había cascado. Resulta que alguna opción de configuración le dijo que cambiara los permisos y usuarios de todos los directorios de mi sistema. Después de perder un rato con la consola [...]]]></description>
			<content:encoded><![CDATA[<p>Este fin de semana iba a hacer una copia de seguridad, instalé lucky backup, lo configuré, lo dejé trabajando y cuando volví mi sistema había cascado. Resulta que alguna opción de configuración le dijo que cambiara los permisos y usuarios de todos los directorios de mi sistema. Después de perder un rato con la consola de recuperación restaurando permisos opté por reinstalar.</p>
<p>La ventaja de tener la home en una partición separada en estos casos tiene un gran valor.</p>
<p>Por otra parte los datos que quería conservar eran:</p>
<ul>
<li>Algunos ficheros de configuración (/etc)</li>
<li>Mis bases de datos (/var/lib/mysql)</li>
<li>Gemas, paquetes autogenerados, librerías ruby,&#8230; (/usr/local)</li>
</ul>
<p><span id="more-104"></span></p>
<p>Antes de reinstalar saqué un listado de todos los paquetes que tenía instalados con el siguiente comando:</p>
<pre>  $ sudo dpkg --get-selections > MY_PACKAGES</pre>
<p><br class="spacer_" /></p>
<p>Ahora ya estaba preparado para reinstalar. Al reinstalar le dije que quería usar como home mi antigua partición, sin formatearla por supuesto <img src='http://blog.rafagarcia.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>Una vez reinstalado el sistema, restauré los repositorios de paquetes y de pasó aproveché a hacer limpieza (quité ppas que no usaba), con copiar el directorio etc/apt de la copia valía.</p>
<p>Como solo tenía añadidos PPAs los añadí a mano con el siguiente comando:</p>
<pre>  $ sudo add-apt-repository ppa:<nombre></pre>
<p><br class="spacer_" /></p>
<p>Dejé que el sistema actualizara todos los paquetes y mientras copié el directorio /usr/local dentro del nuevo sistema. Aquí tengo todas las gemas y librerías de Ruby, además en /usr/local/src guardo los fuentes y paquetes generados por mi, así que solo tuve que instalarlos de nuevo.</p>
<p><br class="spacer_" /></p>
<p>Ahora ya podía reinstalar todos los paquetes, para ello usé el siguiente script:</p>
<pre>  #!/bin/bash
<div id="_mcePaste">  # Get MY_PACKAGES then reinstall every package</div>
<div id="_mcePaste">  # To generate MY_PACKAGES: sudo dpkg --get-selections > MY_PACKAGES</div>
<div id="_mcePaste">  for pkg in `cat MY_PACKAGES | egrep -v deinstall | awk '{print $1}' | egrep -v '(dpkg|apt|ruby|sphinx)'`;do</div>
<div id="_mcePaste">    aptitude -y install $pkg</div>
<div id="_mcePaste">  done</div>
</pre>
<p><strong>Notas</strong>:</p>
<ul>
<li>Le pongo el parámetro &#8220;-y&#8221; para que responda yes a todas las preguntas</li>
<li>Hago install en vez de reinstall para instalar solo lo nuevo.</li>
<li>El último &#8220;egrep&#8221; excluye los paquetes que me creé yo para que no me los pise con los de la distribución.</li>
</ul>
<p>Al terminar la instalación de todos los paquetes solo me faltaba recuperar mis bases de datos. Para ello paré MySQL:</p>
<pre>  $ sudo /etc/init.d/mysql stop</pre>
<p>Copié todo directorio /var/lib/mysql al nuevo sistema y arranqué de nuevo mysql:</p>
<pre>  $ sudo /etc/init.d/mysql start</pre>
<p>Arrancó, pero me salía el error:</p>
<pre>'Access denied for user 'debian-sys-maint'@'localhost'</pre>
<p>Esto lo solucioné conectando con el cliente de MySQL y cambiándole el password a ese usuario:</p>
<pre>$ mysql -u root

> GRANT ALL PRIVILEGES ON *.* TO 'debian-sys-maint'@'localhost' IDENTIFIED BY PASSWORD '
<password>' WITH GRANT OPTION
</pre>
<div><strong>Nota</strong>: El password lo tienes en /etc/mysql/debian.cnf</div>
<p><br class="spacer_" /></p>
<div>Con esto ya está todo tal cual lo tenía antes de cargármelo.</div>
<p><br class="spacer_" /></p>
<div>Al mediodía probaré a hacer otra copia de seguridad, esta vez con grsync, deseadme suerte!</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.rafagarcia.net/2010/02/22/reinstalando-el-sistema/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Capistrano y deployments sin Rails</title>
		<link>http://blog.rafagarcia.net/2010/02/17/capistrano-y-deployments-sin-rails/</link>
		<comments>http://blog.rafagarcia.net/2010/02/17/capistrano-y-deployments-sin-rails/#comments</comments>
		<pubDate>Wed, 17 Feb 2010 12:38:58 +0000</pubDate>
		<dc:creator>Rafa García</dc:creator>
				<category><![CDATA[capistrano]]></category>

		<guid isPermaLink="false">http://blog.rafagarcia.net/?p=96</guid>
		<description><![CDATA[Siguiendo con la tónica de  &#8221;cosas de las que quise hablar en el taller de Capistrano y no pude &#8211; episodio 2&#8243;. A veces toca hacer deployment de aplicaciones que no tienen nada que ver con rails, el caso mas claro unas páginas estáticas(solo subir ficheros, sin migration, ni restart). Para eso Lee Hambley hizo [...]]]></description>
			<content:encoded><![CDATA[<p>Siguiendo con la tónica de  &#8221;cosas de las que quise hablar en el taller de Capistrano y no pude &#8211; episodio 2&#8243;.</p>
<p>A veces toca hacer deployment de aplicaciones que no tienen nada que ver con rails, el caso mas claro unas páginas estáticas(solo subir ficheros, sin migration, ni restart).</p>
<p>Para eso Lee Hambley hizo la gema <a href="http://github.com/leehambley/railsless-deploy/" target="_blank">railsless-deploy</a>, básicamente lo que hace es quitar las &#8220;railties&#8221; de Capistrano. Con esta gema y un pequeño cambio en tu fichero Capfile puedes &#8220;deployar&#8221; lo que quieras. <img src='http://blog.rafagarcia.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Por una vez no me voy a enrollar y a escribir paso a paso un ejemplo porque creo que con las explicaciones que hay en la página de <a href="http://github.com/leehambley/railsless-deploy/" target="_blank">la gema</a> es suficiente.</p>
<p><br class="spacer_" /></p>
<p>&#8220;Solo puede deployar uno&#8221; &#8211; Los inmortales</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rafagarcia.net/2010/02/17/capistrano-y-deployments-sin-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Redirección transparente a otro dominio por idioma con Apache</title>
		<link>http://blog.rafagarcia.net/2010/02/11/redireccion-transparente-a-otro-dominio-por-idioma-con-apache/</link>
		<comments>http://blog.rafagarcia.net/2010/02/11/redireccion-transparente-a-otro-dominio-por-idioma-con-apache/#comments</comments>
		<pubDate>Thu, 11 Feb 2010 17:33:44 +0000</pubDate>
		<dc:creator>Rafa García</dc:creator>
				<category><![CDATA[apache]]></category>

		<guid isPermaLink="false">http://blog.rafagarcia.net/?p=87</guid>
		<description><![CDATA[Hoy he necesitado hacer una redirección transparente (que el usuario no se entere de que lo estoy llevando a otro lado) según el idioma aceptado del navegador. Para entendernos, si el usuario iba a http://bar.com con su navegado en inglés debía redireccionarlo a http://en.foo.com pero sin cambiar la dirección del navegador. Lo primero que probé [...]]]></description>
			<content:encoded><![CDATA[<p>Hoy he necesitado hacer una redirección transparente (que el usuario no se entere de que lo estoy llevando a otro lado) según el idioma aceptado del navegador.</p>
<p><br class="spacer_" /></p>
<p>Para entendernos, si el usuario iba a http://bar.com con su navegado en inglés debía redireccionarlo a http://en.foo.com pero sin cambiar la dirección del navegador.</p>
<p><span id="more-87"></span></p>
<p>Lo primero que probé fue el típico:</p>
<pre>  ﻿RewriteCond %{HTTP:Accept-Language} ^en
  RewriteRule ^/$ http://en.foo.com [L]

  ﻿RewriteCond %{HTTP:Accept-Language} ^pt-BR
  RewriteRule ^/$ http://br.foo.com [L]

  ﻿RewriteCond %{HTTP:Accept-Language} ^pt
  RewriteRule ^/$ http://pt.foo.com [L]

  ...

  #Default Language
  RewriteRule ^/$ http://foo.com [L]
</pre>
<p>Esto hacía la redirección pero al ser a otro dominio la hacía como si le pasáramos el flag R (vamos que hacía: [R,L]). Mas info sobre esto <a href="http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html#rewriteoptions" target="_blank">aquí</a>.</p>
<p><br class="spacer_" /></p>
<p>La solución vino del módulo mod_proxy, y lo que he hecho ha sido usar el parámetro P (force proxy). La cosa ha quedado así:</p>
<pre>﻿RewriteCond %{HTTP:Accept-Language} ^en
  RewriteRule ^/$ http://en.foo.com/ [P,L]

  ﻿RewriteCond %{HTTP:Accept-Language} ^pt-BR
  RewriteRule ^/$ http://br.foo.com [P,L]

  ﻿RewriteCond %{HTTP:Accept-Language} ^pt
  RewriteRule ^/$ http://pt.foo.com [P,L]

  ...

  #Default language
  RewriteRule ^/$ http://foo.com [P,L]</pre>
<p><br class="spacer_" /></p>
<p>That&#8217;s all folks!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rafagarcia.net/2010/02/11/redireccion-transparente-a-otro-dominio-por-idioma-con-apache/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Capistrano y multistaging</title>
		<link>http://blog.rafagarcia.net/2010/01/09/capistrano-y-multistaging/</link>
		<comments>http://blog.rafagarcia.net/2010/01/09/capistrano-y-multistaging/#comments</comments>
		<pubDate>Sat, 09 Jan 2010 02:16:16 +0000</pubDate>
		<dc:creator>Rafa García</dc:creator>
				<category><![CDATA[capistrano]]></category>
		<category><![CDATA[multistage]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blog.rafagarcia.net/?p=82</guid>
		<description><![CDATA[Mientras veía caer los copos de nieve por la ventana, observando como cuajaban en el patio, me vino a la mente que este &#8220;viernes de Capistrano&#8221; tenía que ser diferente, no estaba/estoy lo suficiente inspirado para corregir bugs. Entonces he recordado que tengo una deuda pendiente con la gente que vino al taller de Capistrano [...]]]></description>
			<content:encoded><![CDATA[<p>Mientras veía caer los copos de nieve por la ventana, observando como cuajaban en el patio, me vino a la mente que este &#8220;viernes de Capistrano&#8221; tenía que ser diferente, no estaba/estoy lo suficiente inspirado para corregir bugs. Entonces he recordado que tengo una deuda pendiente con la gente que vino al taller de Capistrano en la Conferencia Rails. Hubo varios temas que quería haber tocado pero que tuve que eliminar por falta de tiempo. Así que vamos a por uno de esos temas, el multistaging.</p>
<p><span id="more-82"></span>Un ejemplo de entorno multistage podría ser el siguiente:</p>
<ul>
<li> mi máquina de desarrollo </li>
<li> un servidor de aceptación </li>
<li> un servidor de producción </li>
</ul>
<p>Supongamos que mi máquina de desarrollo la actualizo a mano y los otros dos stages los quiero hacer con Capistrano. Capistrano por defecto solo sabe &#8220;deployar&#8221; y no es capaz de diferenciar entre aceptación y producción. Para ayudarle a diferenciar entre los diferentes stages podemos seguir varias estrategias.</p>
<p>Vamos a empezar por el mas simple de los casos, supongamos que entre aceptación y producción lo único que cambian son los datos de los roles. Una solución muy simple podría ser añadir a nuestro deploy.rb lo siguiente:</p>
<pre>  if ENV['DEPLOY'].upcase == 'PRODUCTION'
    puts "*** Deployando en producción"
    role :web, "www.production.com"
    role :app, "app.production.com"
    role :db,  "db.production.com", :primary =&gt; true
  else
    puts "*** Deployando en staging"
    role :web, "www.staging.com"
    role :app, "app.staging.com"
    role :db,  "db.staging.com", :primary =&gt; true
  end
</pre>
<p>El código añadido es bastante simple, si la variable de entorno DEPLOY tiene el string &#8216;PRODUCTION&#8217; ejecutaremos el deploy en la máquina de producción, sino se irá a staging. La ejecución se haría de la siguiente manera:</p>
<pre>  $ DEPLOY=production cap deploy
</pre>
<p>Para probarlo sin tener que subir toda una aplicación a nuestros servidores podemos crear una tarea simple y estúpida como esta:</p>
<pre>  task :foo do
    run "uptime"
  end
</pre>
<p>Entonces ahora lo podemos probar de nuevo:</p>
<pre>  $ DEPLOY=production cap foo
  *** Deployando en producción
  ...

  $ cap foo
  *** Deployando en staging
  ...
</pre>
<p>Vale, funciona pero me chirría un poco, ¿no sería mejor hacerlo en el idioma de Capistrano? -aquí es donde todos al unísono debéis decir: SÍIIIIIIII. Entonces vamos a hacer algo parecido encadenando las tareas.</p>
<p>Si recordáis el día del taller os expliqué que con Capistrano podíamos definir varias tareas y llamarlas una detrás de otra, eso es lo que vamos a hacer. Vamos a considerar la configuración de cada stage una tarea diferente:</p>
<pre>  task :production do
    puts "*** Deployando en producción"
    role :web, "www.production.com"
    role :app, "app.production.com"
    role :db,  "db.production.com", :primary =&gt; true
  end

  task :staging do
    puts "*** Deployando en staging"
    role :web, "www.staging.com"
    role :app, "app.staging.com"
    role :db,  "db.staging.com", :primary =&gt; true
  end
</pre>
<p>Utilizando este método el deploy o la ejecución de tareas en un stage u otro se hace de manera mas natural(sin usar variables de entorno):</p>
<pre>  $ cap staging foo
  * executing `staging'
*** Deployando en staging
  * executing `foo'
  * executing "uptime"
    servers: ["localhost"]
Password:
    [localhost] executing command
 ** [out :: localhost] 01:39:08 up  2:25,  5 users,  load average: 0.01, 0.07, 0.05
    command finished
</pre>
<p>Si nos fijamos en el log de Capistrano vemos que primero ejecuta la tarea &#8220;staging&#8221; y luego ejecuta la tarea &#8220;foo&#8221;, que es lo que comentaba del encadenamiento de tareas.</p>
<p>Esta estrategia a mi me parece muy útil cuando los cambios que se necesitan para desplegar en producción y staging son mínimos. Considerando un cambio mínimo el cambio de variables.</p>
<p>Sin embarbo, esta estrategia no me parece limpia si ya se cambian tareas,callbacks, etc. entre stages. En tal caso cambiaría la estrategía y usaría la gema/plugin <a href="http://github.com/jamis/capistrano-ext" target="_blank">capistrano-ext</a>. Esta gema por dentro usa el mismo método que acabamos de utilizar pero llega un poco mas lejos.</p>
<p>Para usar este plugin solo hay que hacer 4 cosillas y una de ellas opcional <img src='http://blog.rafagarcia.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<blockquote><ol>
<li>Hacer un require de capistrano-ext</li>
<li>Definir los stages que vamos a usar</li>
<li>Definir el stage por defecto **OPCIONAL**</li>
<li>Escribir nuestras recetas por cada stage dentro de config/deploy/&lt;stage&gt;.rb</li>
</ol>
</blockquote>
<p>Vamos a hacer el require y definir los stages, escribimos en el inicio de nuestro deploy.rb:</p>
<pre>  require 'capistrano/ext/multistage'
  set :stages, %w(staging production)
</pre>
<p>No ha sido tan dificil ¿verdad?</p>
<p>Ahora siguiendo nuestro sencillo ejemplo vamos a escribir la receta de cada stage. En config/deploy/staging.rb escribimos:</p>
<pre>  puts "*** Deployando en staging"
  role :web, "localhost"
  role :app, "localhost"
  role :db,  "localhost", :primary =&gt; true
</pre>
<p>Y en config/deploy/production.rb:</p>
<pre>  puts "*** Deployando en producción"
  role :web, "localhost"
  role :app, "localhost"
  role :db,  "localhost", :primary =&gt; true
</pre>
<p>Lo probamos y vemos que funciona:</p>
<pre>  $ cap production foo
  * executing `production'
*** Deployando en producción
    triggering start callbacks for `foo'
  * executing `multistage:ensure'
  * executing `foo'
  * executing "uptime"
    servers: ["localhost"]
Password:
    [localhost] executing command
 ** [out :: localhost] 02:22:19 up  3:08,  5 users,  load average: 0.11, 0.10, 0.07
    command finished
</pre>
<p>Si no le pongo stage falla miserablemente:</p>
<pre>  $ cap foo
    triggering start callbacks for `foo'
  * executing `multistage:ensure'
No stage specified. Please specify one of: staging, production (e.g. `cap staging foo')
</pre>
<p>Para definir un stage por defecto entonces añadimos a nuestro deploy.rb:</p>
<pre>  require 'capistrano/ext/multistage'
  set :stages, %w(staging production)
  set :default_stage, 'staging'
</pre>
<p>Y ahora comprobamos que usamos staging por defecto:</p>
<pre>  $ cap foo
      triggering start callbacks for `foo'
    * executing `multistage:ensure'
  *** Defaulting to `staging'
    * executing `staging'
  *** Deployando en staging
    * executing `foo'
    * executing "uptime"
      servers: ["localhost"]
  Password:
      [localhost] executing command
   ** [out :: localhost] 02:29:17 up  3:15,  5 users,  load average: 0.03, 0.08, 0.08
      command finished
</pre>
<p>Esta última estrategia la recomiendo si hay demasiada diferencia a la hora de hacer un deploy entre los diferentes stages, por ej. si en staging tenéis montado el stack con mongrel y en producción con passenger. Otra situación podría ser cuando el deploy tiene muchas variables(además diferentes entre stages) y hace que se pierda la legibilidad de nuestro deploy.rb</p>
<p>Al usar esta estregia siempre procuro que las variables y tareas comunes se queden en el deploy.rb, y el resto vaya al fichero de configuración del stage. Si tuviésemos demasiadas tareas comunes las movería a otro fichero, todo sea por mantener la legibilidad. De todos modos cada cual lo puede hacer como le vaya bien <img src='http://blog.rafagarcia.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><strong>Nota:</strong> El deploy.rb que he usado para escribir este post solo contenía lo que os he ido indicado, para las pruebas que hemos hecho no es necesario definir la aplicación, el repositorio, tipo de scm,&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rafagarcia.net/2010/01/09/capistrano-y-multistaging/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Manifiesto “En defensa de los derechos fundamentales en internet”</title>
		<link>http://blog.rafagarcia.net/2009/12/03/manifiesto-%e2%80%9cen-defensa-de-los-derechos-fundamentales-en-internet%e2%80%9d/</link>
		<comments>http://blog.rafagarcia.net/2009/12/03/manifiesto-%e2%80%9cen-defensa-de-los-derechos-fundamentales-en-internet%e2%80%9d/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 12:32:54 +0000</pubDate>
		<dc:creator>Rafa García</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[derechos]]></category>
		<category><![CDATA[Internet]]></category>

		<guid isPermaLink="false">http://blog.rafagarcia.net/?p=80</guid>
		<description><![CDATA[Ante la inclusión en el Anteproyecto de Ley de Economía sostenible de modificaciones legislativas que afectan al libre ejercicio de las libertades de expresión, información y el derecho de acceso a la cultura a través de Internet, los periodistas, bloggers, usuarios, profesionales y creadores de Internet manifestamos nuestra firme oposición al proyecto, y declaramos que: [...]]]></description>
			<content:encoded><![CDATA[<p>Ante la inclusión en el Anteproyecto de Ley de Economía sostenible de modificaciones legislativas que afectan al libre ejercicio de las libertades de expresión, información y el derecho de acceso a la cultura a través de Internet, los periodistas, <em>bloggers</em>, usuarios, profesionales y creadores de Internet manifestamos nuestra firme oposición al proyecto, y declaramos que:</p>
<ol>
<li><span style="font-weight: bold;">Los derechos de autor no pueden situarse por encima de los derechos fundamentales de los ciudadanos</span>, como el derecho a la privacidad, a la seguridad, a la presunción de inocencia, a la tutela judicial efectiva y a la libertad de expresión.</li>
<li><span style="font-weight: bold;">La suspensión de derechos fundamentales es y debe seguir siendo competencia exclusiva del poder judicia</span>l. Ni un cierre sin sentencia. Este anteproyecto, en contra de lo establecido en el artículo 20.5 de la Constitución, pone en manos de un órgano no judicial -un organismo dependiente del ministerio de Cultura-, la potestad de impedir a los ciudadanos españoles el acceso a cualquier página web.</li>
<li><span style="font-weight: bold;">La nueva legislación creará inseguridad jurídica en todo el sector tecnológico español</span>, perjudicando uno de los pocos campos de desarrollo y futuro de nuestra economía, entorpeciendo la creación de empresas, introduciendo trabas a la libre competencia y ralentizando su proyección internacional.</li>
<li><span style="font-weight: bold;">La nueva legislación propuesta amenaza a los nuevos creadores y entorpece la creación cultural.</span> Con Internet y los sucesivos avances tecnológicos se ha democratizado extraordinariamente la creación y emisión de contenidos de todo tipo, que ya no provienen prevalentemente de las industrias culturales tradicionales, sino de multitud de fuentes diferentes.</li>
<li><span style="font-weight: bold;">Los autores</span>, como todos los trabajadores,<span style="font-weight: bold;"> tienen derecho a vivir de su trabajo con nuevas ideas creativas, modelos de negocio y actividades</span> asociadas a sus creaciones. Intentar sostener con cambios legislativos a una industria obsoleta que no sabe adaptarse a este nuevo entorno no es ni justo ni realista. Si su modelo de negocio se basaba en el control de las copias de las obras y en Internet no es posible sin vulnerar derechos fundamentales, deberían buscar otro modelo.</li>
<li>Consideramos que <span style="font-weight: bold;">las industrias culturales necesitan para sobrevivir alternativas modernas, eficaces, creíbles y asequibles y que se adecuen a los nuevos usos sociales, </span>en lugar de limitaciones tan desproporcionadas como ineficaces para el fin que dicen perseguir.</li>
<li><span style="font-weight: bold;">Internet debe funcionar de forma libre y sin interferencias políticas</span> auspiciadas por sectores que pretenden perpetuar obsoletos modelos de negocio e imposibilitar que el saber humano siga siendo libre.</li>
<li><span style="font-weight: bold;">Exigimos que el Gobierno garantice por ley la neutralidad de la Red en España,</span> ante cualquier presión que pueda producirse, como marco para el desarrollo de una economía sostenible y realista de cara al futuro.</li>
<li><span style="font-weight: bold;">Proponemos una verdadera reforma del derecho de propiedad intelectual </span>orientada a su fin: devolver a la sociedad el conocimiento, promover el dominio público y limitar los abusos de las entidades gestoras.</li>
<li><span style="font-weight: bold;"><span style="font-weight: normal;"><span style="font-weight: bold;">En democracia las leyes y sus modificaciones deben aprobarse tras el oportuno debate público</span> y habiendo consultado previamente a todas las partes implicadas. No es de recibo que se realicen cambios legislativos que afectan a derechos fundamentales en una ley no orgánica y que versa sobre otra materia.</span></span></li>
</ol>
<p><br class="spacer_" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rafagarcia.net/2009/12/03/manifiesto-%e2%80%9cen-defensa-de-los-derechos-fundamentales-en-internet%e2%80%9d/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tus gemas al día con gemcutter</title>
		<link>http://blog.rafagarcia.net/2009/11/12/tus-gemas-al-dia-con-gemcutter/</link>
		<comments>http://blog.rafagarcia.net/2009/11/12/tus-gemas-al-dia-con-gemcutter/#comments</comments>
		<pubDate>Thu, 12 Nov 2009 10:22:48 +0000</pubDate>
		<dc:creator>Rafa García</dc:creator>
				<category><![CDATA[ruby]]></category>
		<category><![CDATA[gems]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://blog.rafagarcia.net/?p=70</guid>
		<description><![CDATA[Con este post no os voy a descubrir nada nuevo a muchos pero aquí quedará para la posteridad. Ahora que tenemos gemcutter el &#8220;awesome gem hosting&#8221; (tal como se describen ellos mismos) debemos hacer que nuestro origen principal de gemas sea este. Esto lo hacemos de manera muy simple y en 3 pasos. 1. Actualizamos [...]]]></description>
			<content:encoded><![CDATA[<p>Con este post no os voy a descubrir nada nuevo a muchos pero aquí quedará para la posteridad.</p>
<p>Ahora que tenemos gemcutter el &#8220;awesome gem hosting&#8221; (tal como se describen ellos mismos) debemos hacer que nuestro origen principal de gemas sea este.</p>
<p>Esto lo hacemos de manera muy simple y en 3 pasos.</p>
<p><br class="spacer_" /></p>
<p>1. Actualizamos Rubygems a la última version:</p>
<p>$ sudo gem update &#8211;system</p>
<p>2. Instalamos la gema gemcutter:</p>
<p>$ sudo gem install gemcutter</p>
<p>3. Cambiamos el origen de las gemas con el comando:</p>
<p>$ sudo gem tumble</p>
<p><br class="spacer_" /></p>
<p>Esto es todo <img src='http://blog.rafagarcia.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p><br class="spacer_" /></p>
<p><strong>Actualización:</strong></p>
<p>Parece que eso no era todo.</p>
<p>Diego, <a href="http://diec123.blogspot.com/" target="_blank">un programador cualquiera</a> <img src='http://blog.rafagarcia.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  , me ha recordado de que os avise que la orden para actualizar Rubygems(paso 1) se usan 2 guiones que WordPress se ha emperrado en poner como si fuese uno largo.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rafagarcia.net/2009/11/12/tus-gemas-al-dia-con-gemcutter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
