<?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>El Futirifoken &#187; ruby on rails</title>
	<atom:link href="http://www.gazer.com.ar/tag/ruby-on-rails/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.gazer.com.ar</link>
	<description>El arte de no decir nada ;-)</description>
	<lastBuildDate>Mon, 26 Dec 2011 19:56:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Procesando archivos en background con Rails</title>
		<link>http://www.gazer.com.ar/2010/09/08/procesando-archivos-en-background-con-rails/</link>
		<comments>http://www.gazer.com.ar/2010/09/08/procesando-archivos-en-background-con-rails/#comments</comments>
		<pubDate>Wed, 08 Sep 2010 16:42:29 +0000</pubDate>
		<dc:creator>Gazer</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby on rails]]></category>

		<guid isPermaLink="false">http://www.gazer.com.ar/?p=1297</guid>
		<description><![CDATA[Procesar archivos en paneles de administración es un bajón, sobre todo cuando son cada vez más grande y cada vez más. En uno de nuestros proyectos tenemos ya unos cinco archivos CSV diferentes a procesar donde cada uno cumple alguna función específica. Algunos de estos archivos superan los 5 Mb por upload, por lo que [...]]]></description>
			<content:encoded><![CDATA[<p>Procesar archivos en paneles de administración es un bajón, sobre todo cuando son cada vez más grande y cada vez más. En uno de nuestros proyectos tenemos ya unos cinco archivos CSV diferentes a procesar donde cada uno cumple alguna función específica. Algunos de estos archivos superan los 5 Mb por upload, por lo que se hizo necesario desacoplar el procesamiento del archivo del request que realiza el upload.</p>
<p>Para manejar procesos en background en rails hay muchas opciones buenas, algunas más complejas con colas de trabajo, workers distribuidos y otras cosas que nosotros no necesitamos. Lo importante para nosotros era encontrar alguno que permita :</p>
<ul>
<li>Procesar en background (obvio <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> )</li>
<li>Poder saber en que estado está el trabajo (% completado)</li>
<li>Al menos un proceso en background a la vez (si hay más que espere su turno, los uploads son semanales o mensuales por lo que no hay tanto solapamiento entre tareas como para justificar múltiples workers)</li>
</ul>
<p>Y nada más. Buscando y buscando caí con <a href="http://github.com/ncr/background-fu">BackgroundFu</a> que cumplía con lo necesario.</p>
<h3>Procesando los archivos</h3>
<p>Como todos los archivos son de texto con algún separador (algunos &#8216;;&#8217;, otros tabs o comas) empezamos por lo básico y crear una clase base que maneje algunos parámetros comunes.</p>
<p>En <a href="http://github.com/ncr/background-fu">BackgroundFu</a> uno puede encolar cualquier clase, por lo que nuestro worker es simplemente una clase con un método <code>process</code> (que también es arbitrario el nombre, podría ser cualquier otro).</p>
<p>Como el archivo que sube el usuario está en un directorio temporal, antes de mandar al proceso en background en necesario guardarlo en algún lugar seguro, para poder saber que al momento de procesarlo va a seguir estando, para ello encapsulamos este comportamiento en un método especial para encolar.</p>
<p>Nuestra completa termina siendo algo como (más adelante veremos en detalle algunas cosas) :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> FileWorker
  <span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#6666ff; font-weight:bold;">BackgroundFu::WorkerMonitoring</span>
&nbsp;
  attr_reader <span style="color:#ff3333; font-weight:bold;">:total_lines</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">enqueue</span><span style="color:#006600; font-weight:bold;">&#40;</span>file, <span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>
    filename = <span style="color:#996600;">&quot;#{RAILS_ROOT}/tmp/#{self.name}-#{Time.now.to_i}&quot;</span>
    <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>filename, <span style="color:#996600;">&quot;wb&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span> f.<span style="color:#9900CC;">write</span><span style="color:#006600; font-weight:bold;">&#40;</span>file.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
    Job.<span style="color:#9900CC;">enqueue</span>!<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">name</span>, :<span style="color:#996600;">'process'</span>, filename, <span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">id</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> process<span style="color:#006600; font-weight:bold;">&#40;</span>filename, <span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0066ff; font-weight:bold;">@lines</span> = <span style="color:#006666;">0</span>
    <span style="color:#0066ff; font-weight:bold;">@total_lines</span> = <span style="color:#996600;">`wc -l #{filename}`</span>.<span style="color:#9900CC;">to_i</span>
    record_progress<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    result = real_process<span style="color:#006600; font-weight:bold;">&#40;</span>filename, <span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    record_progress<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">100</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">unlink</span><span style="color:#006600; font-weight:bold;">&#40;</span>filename<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    result
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  protected
  <span style="color:#9966CC; font-weight:bold;">def</span> line_processed!
    <span style="color:#0066ff; font-weight:bold;">@lines</span> <span style="color:#006600; font-weight:bold;">+</span>= <span style="color:#006666;">1</span>
&nbsp;
    update<span style="color:#006600; font-weight:bold;">&#40;</span>@lines<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> update<span style="color:#006600; font-weight:bold;">&#40;</span>lines<span style="color:#006600; font-weight:bold;">&#41;</span>
    record_progress<span style="color:#006600; font-weight:bold;">&#40;</span>lines, <span style="color:#0066ff; font-weight:bold;">@total_lines</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Veamos un poco más en detalle algunas partes.</p>
<h3>Encolado</h3>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">enqueue</span><span style="color:#006600; font-weight:bold;">&#40;</span>file, <span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>
    filename = <span style="color:#996600;">&quot;#{RAILS_ROOT}/tmp/#{self.name}-#{Time.now.to_i}&quot;</span>
    <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>filename, <span style="color:#996600;">&quot;wb&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span> f.<span style="color:#9900CC;">write</span><span style="color:#006600; font-weight:bold;">&#40;</span>file.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
    Job.<span style="color:#9900CC;">enqueue</span>!<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">name</span>, :<span style="color:#996600;">'process'</span>, filename, <span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">id</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Este método es quien guarda en un lugar seguro el archivo. Utilizando el nombre de la clase actual (recuerden que este método está en una clase base, de donde luego vamos a heredar) y un timestamp por las dudas que se lleguen a hacer 2 uploads (cosa que en la práctica no pasa, pero por las dudas está).</p>
<p>Luego de guardar el archivo se encola el trabajo pasándole el archivo (el path completo) y cualquier otro argumento que se quiera.</p>
<p>Esto hará que luego el daemon de background instancia la clase &#8216;self.name&#8217; y llame al método process pasandole nuestros parámetros.</p>
<h3>Procesamiento</h3>
<p>El método genérico de procesamiento hace uso de un método que la clase base no tiene &#8216;real_process&#8217; que es el método que las clases hijas definarán para realizar el trabajo final :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#9966CC; font-weight:bold;">def</span> process<span style="color:#006600; font-weight:bold;">&#40;</span>filename, <span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0066ff; font-weight:bold;">@lines</span> = <span style="color:#006666;">0</span>
    <span style="color:#0066ff; font-weight:bold;">@total_lines</span> = <span style="color:#996600;">`wc -l #{filename}`</span>.<span style="color:#9900CC;">to_i</span>
    record_progress<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    result = real_process<span style="color:#006600; font-weight:bold;">&#40;</span>filename, <span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    record_progress<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">100</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">unlink</span><span style="color:#006600; font-weight:bold;">&#40;</span>filename<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    result
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>En este caso el método se encarga de saber cual es el total de lineas (de una manera tal vez no muy linda, pero que anda <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> ) y borrar el archivo al terminar el proceso.</p>
<h3>Un worker real</h3>
<p>Para que esto tenga sentido, debemos crear un worker que haga realmente algo, entonces por ejemplo podríamos tener un worker que sume puntos a los usuarios desde un archivo :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> UserPointProcessor <span style="color:#006600; font-weight:bold;">&lt;</span> FileWorker
  private
  <span style="color:#9966CC; font-weight:bold;">def</span> real_process<span style="color:#006600; font-weight:bold;">&#40;</span>file<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">transaction</span> <span style="color:#9966CC; font-weight:bold;">do</span>
      FasterCSV.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#40;</span>file<span style="color:#006600; font-weight:bold;">&#41;</span>, <span style="color:#ff3333; font-weight:bold;">:col_sep</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;<span style="color:#000099;">\t</span>&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>row<span style="color:#006600; font-weight:bold;">|</span>
         <span style="color:#008000; font-style:italic;"># Hacer algo con row</span>
&nbsp;
         line_processed!
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#996600;">&quot;Podemos retornar algun valor o status de exito&quot;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>De esta forma podemos ahora en algún controller hacer el encolado del trabajo :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#9966CC; font-weight:bold;">def</span> add_points
    <span style="color:#9966CC; font-weight:bold;">if</span> request.<span style="color:#9900CC;">post</span>?
      redirect_to admin_job_path<span style="color:#006600; font-weight:bold;">&#40;</span>UserPointProcessor.<span style="color:#9900CC;">enqueue</span><span style="color:#006600; font-weight:bold;">&#40;</span>params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:file</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">and</span> <span style="color:#0000FF; font-weight:bold;">return</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    render <span style="color:#996600;">'file_upload'</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>En este caso el template <code>file_upload</code> es un form con un <em>file field</em> para hacer el upload, sin ningún otro campo. La ruta <code>admin_job_path</code> nos la provee directamente <a href="http://github.com/ncr/background-fu">BackgroundFu</a>, generándonos también las vistas con AJAX para actualizar el estado, una linda barra de progreso que nos muestra el tiempo estimado para terminar entre otros datos útiles (o no tanto <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> ).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gazer.com.ar/2010/09/08/procesando-archivos-en-background-con-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Take A Photo &#8211; Demo</title>
		<link>http://www.gazer.com.ar/2009/07/01/take-a-photo-demo/</link>
		<comments>http://www.gazer.com.ar/2009/07/01/take-a-photo-demo/#comments</comments>
		<pubDate>Wed, 01 Jul 2009 04:34:36 +0000</pubDate>
		<dc:creator>Gazer</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[upload]]></category>

		<guid isPermaLink="false">http://www.gazer.com.ar/?p=1140</guid>
		<description><![CDATA[Hace unos meses publiqué un plugin para tomar fotos instantáneas desde una página web, usando Flash y un plugin para Ruby on Rails. Hoy me puse un rato a jugar y armé un demo donde se pueden tomar fotos (ojo que todo es público ) : TAP. Las fotos se borran una vez por día [...]]]></description>
			<content:encoded><![CDATA[<p>Hace unos meses publiqué un <a href="http://www.gazer.com.ar/2009/04/02/take-a-photo-fotos-instantaneas-desde-tu-web/">plugin para tomar fotos instantáneas</a> desde una página web, usando Flash y un plugin para Ruby on Rails.</p>
<p>Hoy me puse un rato a jugar y armé un demo donde se pueden tomar fotos (ojo que todo es público <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> ) : <a href="http://tap.gazer.com.ar/">TAP</a>.</p>
<p>Las fotos se borran una vez por día y acepta un máximo de 50 fotos por día (para evitar que me llenen el disco). Tengo algunos TODOs que iré viendo de resolver en los tiempos libres (como cambiar el tamaño de la foto, recortar, aplicar efectos, etc).</p>
<p>Necesita Flash 9 o superior y una web cam para que tenga sentido <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Todavía sigo peleando con el Flash player de Linux y la camarita, sorry :S.</p>
<p>Les recomiendo verlo en Firefox, no me gasté en ver si en IE el CSS no se rompe y no creo que lo haga nunca.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gazer.com.ar/2009/07/01/take-a-photo-demo/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Take A  Photo &#8211; Fotos instantáneas desde tu web</title>
		<link>http://www.gazer.com.ar/2009/04/02/take-a-photo-fotos-instantaneas-desde-tu-web/</link>
		<comments>http://www.gazer.com.ar/2009/04/02/take-a-photo-fotos-instantaneas-desde-tu-web/#comments</comments>
		<pubDate>Thu, 02 Apr 2009 19:58:49 +0000</pubDate>
		<dc:creator>Gazer</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[ruby on rails]]></category>

		<guid isPermaLink="false">http://www.gazer.com.ar/?p=1060</guid>
		<description><![CDATA[En la última semana estuve trabajando en agregar nuevas funcionalidades a un sitio de un cliente y entre los pedidos estaba una especie de Fotoblog para los usuarios (y bue, hay que pagar las cuentas a fin de mes ). La cosa salió rápido, usando Paperclip que guarda las imágenes que se suben, se muestra [...]]]></description>
			<content:encoded><![CDATA[<p>En la última semana estuve trabajando en agregar nuevas funcionalidades a un sitio de un cliente y entre los pedidos estaba una especie de Fotoblog para los usuarios (y bue, hay que pagar las cuentas a fin de mes <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> ).</p>
<p>La cosa salió rápido, usando Paperclip que guarda las imágenes que se suben, se muestra en orden, etc, nada del otro mundo. Pero hablando con el cliente surgió la idea de hacer que el usuario se pueda tomar una foto directamente desde la web usando su webcam, así que después de decir &#8220;<em>si, se debe poder hacer</em>&#8221; mentalmente me salió un &#8220;<em>doh!, que dije!</em>&#8220;. Lo último que se dijo en esa reunión fue &#8220;<em>Lo quiero</em>&#8221; <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> .</p>
<p>Ya había visto juegos flash que utilizan la webcam así que empecé por ahí, para ver como sacaban un frame del video, lo cual era muy fácil. Lo siguiente era serializarla. A falta de algo mejor hice un serializador de imágenes muy pedorro, pero que anda (aunque es lento), que envía por POST la información de cada pixel.</p>
<p>La parte de Ruby fue fácil y decidí encapsularla en un plugin de Rails para poder reutilizarlo luego o por si a alguien más le sirve <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Además se puede integrar con Paperclip o AttachmentFu para hacer la persistencia de la imagen en donde sea.</p>
<p>La única parte que usa Flash es el capturador de la cámara, porque otra no quedaba, pero luego el botón para tomar la foto y los eventos se manejan todo por Javascript.</p>
<p>El plugin tiene varios TODOs, pero por si a alguien le sirve está en <a href="http://github.com/Gazer/take-a-photo/tree/master">github</a>.</p>
<p><strong>Update</strong> : A falta de demo, algunas de las fotos tomadas con la aplicación de ejemplo que hice hoy durante Locos x rails.</p>
<p style="text-align: center;">
<a href='http://www.gazer.com.ar/2009/04/02/take-a-photo-fotos-instantaneas-desde-tu-web/take_a_photo1342-3/' title='take_a_photo1342-3'><img width="150" height="150" src="http://www.gazer.com.ar/wp-content/uploads/2009/04/take_a_photo1342-3-150x150.jpg" class="attachment-thumbnail" alt="take_a_photo1342-3" title="take_a_photo1342-3" /></a>
<a href='http://www.gazer.com.ar/2009/04/02/take-a-photo-fotos-instantaneas-desde-tu-web/take_a_photo1342-2/' title='take_a_photo1342-2'><img width="150" height="150" src="http://www.gazer.com.ar/wp-content/uploads/2009/04/take_a_photo1342-2-150x150.jpg" class="attachment-thumbnail" alt="take_a_photo1342-2" title="take_a_photo1342-2" /></a>
<a href='http://www.gazer.com.ar/2009/04/02/take-a-photo-fotos-instantaneas-desde-tu-web/take_a_photo1342-1/' title='take_a_photo1342-1'><img width="150" height="150" src="http://www.gazer.com.ar/wp-content/uploads/2009/04/take_a_photo1342-1-150x150.jpg" class="attachment-thumbnail" alt="take_a_photo1342-1" title="take_a_photo1342-1" /></a>
<a href='http://www.gazer.com.ar/2009/04/02/take-a-photo-fotos-instantaneas-desde-tu-web/take_a_photo1342-0/' title='take_a_photo1342-0'><img width="150" height="150" src="http://www.gazer.com.ar/wp-content/uploads/2009/04/take_a_photo1342-0-150x150.jpg" class="attachment-thumbnail" alt="take_a_photo1342-0" title="take_a_photo1342-0" /></a>
</p>
<p style="text-align: center;">
]]></content:encoded>
			<wfw:commentRss>http://www.gazer.com.ar/2009/04/02/take-a-photo-fotos-instantaneas-desde-tu-web/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Refactoring de &#8220;Fat Methods&#8221; &#8211; Episodio 4</title>
		<link>http://www.gazer.com.ar/2008/12/01/refactoring-de-fat-methods-episodio-4/</link>
		<comments>http://www.gazer.com.ar/2008/12/01/refactoring-de-fat-methods-episodio-4/#comments</comments>
		<pubDate>Mon, 01 Dec 2008 13:22:16 +0000</pubDate>
		<dc:creator>Gazer</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[refactoring]]></category>
		<category><![CDATA[ruby on rails]]></category>

		<guid isPermaLink="false">http://www.gazer.com.ar/?p=930</guid>
		<description><![CDATA[En la última entrega habíamos logrado separar las notificaciones del controlador. Una de las cosas que todavía me seguían molestando eran los métodos donde obtengo las direcciones de email, como por ejemplo : @notifications = @match.players.select &#123;&#124;p&#124; p.user.notify_new_match_comment? &#125;.collect &#123;&#124;p&#124; p.user.email&#125; Lo que busca esto es obtener los emails de los usuarios para notificar ante [...]]]></description>
			<content:encoded><![CDATA[<p>En la <a href="http://www.gazer.com.ar/2008/10/30/refactoring-de-fat-methods-episodio-3/">última</a> entrega habíamos logrado separar las notificaciones del controlador. Una de las cosas que todavía me seguían molestando eran los métodos donde obtengo las direcciones de email, como por ejemplo :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#0066ff; font-weight:bold;">@notifications</span> = <span style="color:#0066ff; font-weight:bold;">@match</span>.<span style="color:#9900CC;">players</span>.<span style="color:#CC0066; font-weight:bold;">select</span> <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>p<span style="color:#006600; font-weight:bold;">|</span> <span style="color:#CC0066; font-weight:bold;">p</span>.<span style="color:#9900CC;">user</span>.<span style="color:#9900CC;">notify_new_match_comment</span>? <span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">collect</span> <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>p<span style="color:#006600; font-weight:bold;">|</span> <span style="color:#CC0066; font-weight:bold;">p</span>.<span style="color:#9900CC;">user</span>.<span style="color:#9900CC;">email</span><span style="color:#006600; font-weight:bold;">&#125;</span></pre></div></div>

<p>Lo que busca esto es obtener los emails de los usuarios para notificar ante un evento dado (un nuevo partido creado, un nuevo comentario, una petición de amistad, etc). Me molesta principalmente porque se ven horribles mis controllers <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>La respuesta que motiva este episodio llegó por casualidad. Intentando solucionar un bug que tenía en uno de los plugins que uso (<a href="http://agilewebdevelopment.com/plugins/has_many_friends">has_many_friends</a>, que es feo pero cómodo para un proyecto como este de prueba) vi algo que no conocía : las asociaciones (has_many, has_one, etc) aceptan un bloque donde podemos agregar funcionalidad extra.</p>
<p>Entonces, por ejemplo, si yo quisiera que el ejemplo anterior pueda ser escrito como <code>@match.players.notificables</code> (si, el nombre no es de lo mejor, pero es a modo ilustrativo) simplemente debería agregar ese método como sigue :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Match <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  has_many <span style="color:#ff3333; font-weight:bold;">:players</span>  <span style="color:#9966CC; font-weight:bold;">do</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> notificables
      collect <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>p<span style="color:#006600; font-weight:bold;">|</span> <span style="color:#CC0066; font-weight:bold;">p</span>.<span style="color:#9900CC;">user</span>.<span style="color:#9900CC;">email</span> <span style="color:#9966CC; font-weight:bold;">if</span> !<span style="color:#CC0066; font-weight:bold;">p</span>.<span style="color:#9900CC;">user</span>.<span style="color:#9900CC;">email</span>.<span style="color:#9900CC;">blank</span>? <span style="color:#006600; font-weight:bold;">&amp;&amp;</span> <span style="color:#CC0066; font-weight:bold;">p</span>.<span style="color:#9900CC;">user</span>.<span style="color:#9900CC;">notify_new_match_comment</span>? <span style="color:#006600; font-weight:bold;">&#125;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Ejemplo de uso</span>
<span style="color:#0066ff; font-weight:bold;">@notifications</span> = <span style="color:#0066ff; font-weight:bold;">@match</span>.<span style="color:#9900CC;">players</span>.<span style="color:#9900CC;">notificables</span></pre></div></div>

<p>El método que agregamos trabaja directamente sobre la asociación, que en este caso es una colección de <code>Player</code>, por lo que el <code>collect</code> nos dará todos los emails de los usuarios que se anotaron al partido y tienen activa la opción de recibir notificaciones cuando alguien deja un comentario nuevo en ese partido.</p>
<p>Los métodos que agregamos pueden aceptar parámetros también, con lo cual podría aceptar un symbol con el tipo de permiso a verificar y tener todos los emails de los usuarios para un tipo de notificación dada. Ahora si se hace un refactor de las opciones de notificación de los usuarios tenemos centralizada la lógica en los modelos en lugar de tenerla en los controladores u observers.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gazer.com.ar/2008/12/01/refactoring-de-fat-methods-episodio-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reunión Mensual de Ruby Argentina</title>
		<link>http://www.gazer.com.ar/2008/11/22/reunion-mensual-de-ruby-argentina/</link>
		<comments>http://www.gazer.com.ar/2008/11/22/reunion-mensual-de-ruby-argentina/#comments</comments>
		<pubDate>Sat, 22 Nov 2008 03:44:04 +0000</pubDate>
		<dc:creator>Gazer</dc:creator>
				<category><![CDATA[Yo Estuve Ahí]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby on rails]]></category>

		<guid isPermaLink="false">http://www.gazer.com.ar/?p=886</guid>
		<description><![CDATA[Hoy anunciamos la próxima reunión mensual que se va a desarrollar la semana que viene. Cualquier interesado en dar alguna charla puede dejarme un comentario. El día 29/11 se presentará un conjunto de charlas y se lanzará el ciclo mensual de conferencias sobre Ruby y Ruby on Rails y organizado por Argentina on Rails y [...]]]></description>
			<content:encoded><![CDATA[<p>Hoy anunciamos la próxima reunión mensual que se va a desarrollar la semana que viene. Cualquier interesado en dar alguna charla puede dejarme un comentario.</p>
<p style="padding-left: 30px;">El día 29/11 se presentará un conjunto de charlas y se lanzará el ciclo mensual de conferencias sobre Ruby y Ruby on Rails y organizado por Argentina on Rails y Ruby Argentina.</p>
<p style="padding-left: 30px;">El evento se llevará a cabo entre las 11 y las 16hs, con un break para almorzar sobre las 13hs. Al momento contamos con la presencia de Luis Lavena, actual mainteiner del one-click installer de Ruby para Windows, Pedro Vistinin de Argentina on Rails. A medida que tengamos confirmación de los demás oradores la iremos comunicando.</p>
<p style="padding-left: 30px;">Luis hablará del rake-compiler y draco<br />
rake-compiler es una serie de tareas de rake que simplifican la compilacion de tanto extensiones como gemas en Ruby, cosa que hasta ahora viene bastante descuidada y caoticamente un desastre entre developers. Cositas lindas para que no tengan mas excusas de no hacer cosas para Windows&#8230;</p>
<p style="padding-left: 30px;">Pedro Visintin hablará de como hacerse freelance (trabajando con rails<br />
 <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  ) y no morir en el intento.
</p>
<p style="padding-left: 30px;">Si estás interesado en dar alguna charla referida a Ruby o Rails, mandá un mail  que veremos como proveerte un espacio en ésta o próximas ediciones del evento.</p>
<p style="padding-left: 30px;"><strong>Lugar</strong><br />
La cita es en la Facultad de Ingeniería de la UBA, Paseo Colón 850 en el Aula 402, 4to Piso. Capital Federal
</p>
<p style="padding-left: 30px;">La entrada es libre y gratuita y no requiere registración previa.</p>
<p style="padding-left: 30px;">Además, CaFeLug sorteará 2 libros de Ruby/Rails de la editorial O&#8217;Reilly entre los asistentes.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gazer.com.ar/2008/11/22/reunion-mensual-de-ruby-argentina/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Delegando atributos de ActiveRecord</title>
		<link>http://www.gazer.com.ar/2008/11/04/delegando-atributos-de-activerecord/</link>
		<comments>http://www.gazer.com.ar/2008/11/04/delegando-atributos-de-activerecord/#comments</comments>
		<pubDate>Tue, 04 Nov 2008 03:09:49 +0000</pubDate>
		<dc:creator>Gazer</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[active record]]></category>
		<category><![CDATA[refactoring]]></category>
		<category><![CDATA[ruby on rails]]></category>

		<guid isPermaLink="false">http://www.gazer.com.ar/?p=483</guid>
		<description><![CDATA[El otro día tratando de mejorar un modelo de una aplicación me topé con el problema de tener muchos atributos virtuales para poder acceder a atributos de un objeto relacionado y no caer en lo siguiente : class Player &#60; ActiveRecord::Base belongs_to :user &#160; def name user.name end &#160; def email user.email end &#160; # [...]]]></description>
			<content:encoded><![CDATA[<p>El otro día tratando de mejorar un modelo de una aplicación me topé con el problema de tener muchos atributos virtuales para poder acceder a atributos de un objeto relacionado y no caer en lo siguiente :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Player <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  belongs_to <span style="color:#ff3333; font-weight:bold;">:user</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> name
    user.<span style="color:#9900CC;">name</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> email
    user.<span style="color:#9900CC;">email</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># ... y varios más</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Esto no lo puedo evitar mucho ya que <code>Player</code> es una clase intermedia en una relación de N-M entre los usuarios y los partidos, y además contiene información necesaria para la lógica del modelo.</p>
<p>Tampoco era muy feliz tener por todos lados <em><a href="http://sis36.berkeley.edu/projects/streek/agile/bad-smells-in-code.html#Message+Chains">Message Chains</a></em>:</p>
</pre>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#0066ff; font-weight:bold;">@player</span>.<span style="color:#9900CC;">user</span>.<span style="color:#9900CC;">name</span>
<span style="color:#0066ff; font-weight:bold;">@player</span>.<span style="color:#9900CC;">user</span>.<span style="color:#9900CC;">email</span>
<span style="color:#008000; font-style:italic;"># etc ....</span></pre></div></div>

<p>Una de las recomendaciones que se usan en estos casos es <a href="http://www.refactoring.com/catalog/hideDelegate.html">Hide Delegate</a> para ocultarle al cliente de donde sale el dato realmente. Cabe aclarar que no siempre son un problema las llamadas encadenadas.</p>
<p>Recordando el anuncio de Rails 2.2 noté que al final hablaba de un delegate que tenía un nuevo feature. Buscando un rato por google encontré <a href="http://craigjolicoeur.com/blog/2007/05/activerecord-delegate-attributes/">este</a> post donde hablaba de un método delegate para hacer justamente esto que yo quería.</p>
<p>Lo extraño, que también menciona el autor es que no está documentado en la <a href="http://api.rubyonrails.org/">API</a> oficial de Rails aunque mirando el código veo que explica como usarla. Explícitamente dice :</p>
<blockquote><p>
Provides a delegate class method to easily expose contained objects' methods as your own
</p></blockquote>
<p>En la documentación también aclara que es útil tanto para atributos propios como para asociaciones entre diferentes instancias de ActiveRecord. La realidad es que por cómo está implementada funciona para cualquier objeto ruby que se nos ocurra.</p>
<p>El ejemplo con el que empezamos el post quedaría resumido a :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Player <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  belongs_to <span style="color:#ff3333; font-weight:bold;">:user</span>
  delegate <span style="color:#ff3333; font-weight:bold;">:name</span>, <span style="color:#ff3333; font-weight:bold;">:email</span>, ... , <span style="color:#ff3333; font-weight:bold;">:to</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:user</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Quedando mucho más corto el código, por lo tanto más fácil de mantener.</p>
<p>Tomando prestado los ejemplos del otro blog, también podemos hacer cosas con atributos que no son asociaciones, como por ejemplo una fecha :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># Forma abreviada</span>
<span style="color:#9966CC; font-weight:bold;">class</span> Content <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  delegate <span style="color:#ff3333; font-weight:bold;">:year</span>, <span style="color:#ff3333; font-weight:bold;">:month</span>, <span style="color:#ff3333; font-weight:bold;">:day</span>, <span style="color:#ff3333; font-weight:bold;">:to</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:published_at</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Forma desglosada</span>
<span style="color:#9966CC; font-weight:bold;">class</span> Content <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  delegate <span style="color:#ff3333; font-weight:bold;">:year</span>, <span style="color:#ff3333; font-weight:bold;">:to</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:published_at</span>
  delegate <span style="color:#ff3333; font-weight:bold;">:month</span>, <span style="color:#ff3333; font-weight:bold;">:to</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:published_at</span>
  delegate <span style="color:#ff3333; font-weight:bold;">:day</span>, <span style="color:#ff3333; font-weight:bold;">:to</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:published_at</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Podemos escribir</span>
<span style="color:#0066ff; font-weight:bold;">@content</span>.<span style="color:#9900CC;">year</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># en lugar de</span>
<span style="color:#0066ff; font-weight:bold;">@content</span>.<span style="color:#9900CC;">published_at</span>.<span style="color:#9900CC;">year</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.gazer.com.ar/2008/11/04/delegando-atributos-de-activerecord/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Lo que viene en Rails 2.2</title>
		<link>http://www.gazer.com.ar/2008/10/27/lo-que-viene-en-rails-2-2/</link>
		<comments>http://www.gazer.com.ar/2008/10/27/lo-que-viene-en-rails-2-2/#comments</comments>
		<pubDate>Mon, 27 Oct 2008 14:58:24 +0000</pubDate>
		<dc:creator>Gazer</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[active record]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[i18n]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby on rails]]></category>

		<guid isPermaLink="false">http://www.gazer.com.ar/?p=430</guid>
		<description><![CDATA[Hace poco se anunció el RC1 de lo que será la versión 2.2 de Ruby on Rails. Si bien la fecha de salida es &#8220;cuando esté lista&#8221;, ya se pueden utilizar para aquellos que gusten vivir &#8220;on the edge&#8221;. Para aquellos que quieran un rejunte completo de todo lo que se viene pueden ver el [...]]]></description>
			<content:encoded><![CDATA[<p>Hace poco se anunció el RC1 de lo que será la versión <a href="http://guides.rubyonrails.org/2_2_release_notes.html">2.2</a> de <a href="http://www.rubyonrails.com/">Ruby on Rails</a>. Si bien la fecha de salida es &#8220;cuando esté lista&#8221;, ya se pueden utilizar para aquellos que gusten vivir &#8220;on the edge&#8221;.</p>
<p>Para aquellos que quieran un rejunte completo de todo lo que se viene pueden ver el post : <a href="http://ryandaigle.com/articles/2008/10/25/what-s-new-in-edge-rails-rails-2-2-released-summary-of-features">What&#8217;s New in Edge Rails: Rails 2.2 Released &#8211; Summary of Feature.</a></p>
<p>Yo acá voy a comentar solo lo que tuve la oportunidad de probar y que me resultó útil.</p>
<h2 class="entry-title">I18n</h2>
<p>La verdad es que es una buena noticia, no para mi porque hago todo para un solo idioma <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> , pero algún día puede resultar útil. Lo único que a mi me deja con sabor a poco es la forma en que se hace que no me termina de gustar. Antes que nada quiero aclarar, porque ya vi la pregunta en un par de listas de correo, que esto localiza textos, no el contenido de una instancia de ActiveRecord. Si uno quiere que el contenido que cargan los usuarios sea traducido, es otra historia <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>Las traducciones se escriben en ruby o en archivos YAML, con &#8220;hashes&#8221; que pueden estar anidados (como si fueran &#8220;<em>namespaces</em>&#8220;) :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># lib/locale/en-US.rb</span>
<span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#996600;">'en-US'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span>
  <span style="color:#ff3333; font-weight:bold;">:hello_world</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;Hello World&quot;</span>,
  <span style="color:#ff3333; font-weight:bold;">:hello_flash</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;Hello Flash&quot;</span>
<span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># lib/locale/pirate.rb</span>
<span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#996600;">'pirate'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span>
  <span style="color:#ff3333; font-weight:bold;">:hello_world</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;Ahoy World&quot;</span>,
  <span style="color:#ff3333; font-weight:bold;">:hello_flash</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;Ahoy Flash&quot;</span>
<span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#125;</span></pre></div></div>

<p>Y luego en las vistas (o mailers o donde sea) en lugar de poner el texto se ingresa el symbol asociado al texto que cargamos en las traducciones, por ejemplo :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#006600; font-weight:bold;">&lt;</span>h1<span style="color:#006600; font-weight:bold;">&gt;&lt;</span> <span style="color:#006600; font-weight:bold;">%</span>=t <span style="color:#ff3333; font-weight:bold;">:hello_world</span> <span style="color:#006600; font-weight:bold;">%&gt;&lt;/</span>h1<span style="color:#006600; font-weight:bold;">&gt;</span></pre></div></div>

<p>Mi problema particular con este método es que estoy mucho más acostumbrado a cómo se hace con gettext (que no necesariamente es la mejor forma) donde se ponen todos los textos en inglés en la aplicación y después se escriben las traducciones.</p>
<p>Hay un demo online <a href="http://i18n-demo.phusion.nl/">acá</a>, que en estos momentos está caído, espero que para cuando lean esto ya este funcionando de nuevo.</p>
<h2 class="entry-title">Join Tables Conditions</h2>
<p>Esto es algo que realmente hacía falta. Vamos a ver la mejora con un ejemplo. Supongamos que tenemos los siguientes modelos :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Article <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  belongs_to <span style="color:#ff3333; font-weight:bold;">:user</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> User <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  has_many <span style="color:#ff3333; font-weight:bold;">:articles</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>y queremos obtener todos los usuarios que tengan al menos un artículo publicado. Para eso deberíamos hacer :
</pre>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">User.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span>, <span style="color:#ff3333; font-weight:bold;">:joins</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:article</span>,  <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;articles.published = ?&quot;</span>, <span style="color:#0000FF; font-weight:bold;">true</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>Con la nueva sintaxis es posible especificar este tipo de queries de una manera más amena como sigue :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">User.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span>, <span style="color:#ff3333; font-weight:bold;">:joins</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:article</span>, <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:articles</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:published</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span> <span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<h2>ActionMailer Layouts</h2>
<p>Algo que si me tocó vivir es tener varios emails HTML con un mismo formato y que cambiaba el contenido (Tu amigo te invitó, Tu nueva clave es, Ganaste un premio, etc). Con el mailer actual casi que hay que hacer un copy &#038; paste del marco y despuer cambiar para cada tipo de email la lógica de qué se muestra.</p>
<p>En rails 2.2 ahora vamos a tener layouts como los tenemos en ActionView, de manera de tenerlo una vez y si arreglamos o cambiamos algo cambia para todos.</p>
<h2>Memoization</h2>
<p>Es muy frecuente que uno agregue lógica simple de caching en los modelos para las variables de instancia como se ve en el siguiente ejemplo :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#9966CC; font-weight:bold;">class</span> User <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> full_name
      <span style="color:#0066ff; font-weight:bold;">@full_name</span> <span style="color:#006600; font-weight:bold;">||</span>= <span style="color:#996600;">&quot;#{first_name} #{last_name}&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Esto lo hacemos para evitar el overhead de crear el full_name si lo llegamos a usar varias veces en una misma vista, de manera que el string se crea en la primer llamada y en las siguientes solamente lo retorna.</p>
<p>Los puristas dicen que en realidad está mal, porque se está responsabilizando al método de algo que en realidad no debería importarle : la política de caching. ¿Suena exagerado? Seguramente <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>Para solucionar esto se agregó el método <code>memoize</code> que nos permite a agregar a un método común este tipo de lógica de manera separada :</p>
</pre>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#9966CC; font-weight:bold;">class</span> User <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> full_name
      <span style="color:#996600;">&quot;#{first_name} #{last_name}&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    memoize <span style="color:#ff3333; font-weight:bold;">:full_name</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Esto se encarga de que cuando llamemos a <code>@user.full_name</code> se comporte de la misma manera que el primer ejemplo, sin tener que modificar el método. También nos permite saltarnos el "cache", por ejemplo si en la lógica acabamos de cambiar el nombre de pila, debemos forzar para que el nombre completo cambie :</p>
</pre>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">   <span style="color:#0066ff; font-weight:bold;">@user</span> = User.<span style="color:#9900CC;">new</span> <span style="color:#ff3333; font-weight:bold;">:first_name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Test'</span>, <span style="color:#ff3333; font-weight:bold;">:last_name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Test'</span>
   <span style="color:#0066ff; font-weight:bold;">@user</span>.<span style="color:#9900CC;">full_name</span> <span style="color:#008000; font-style:italic;"># =&gt; Test Test</span>
   <span style="color:#0066ff; font-weight:bold;">@user</span>.<span style="color:#9900CC;">first_name</span> = <span style="color:#996600;">'Do'</span>
   <span style="color:#0066ff; font-weight:bold;">@user</span>.<span style="color:#9900CC;">full_name</span> <span style="color:#008000; font-style:italic;"># =&gt; Test Test</span>
   <span style="color:#0066ff; font-weight:bold;">@user</span>.<span style="color:#9900CC;">full_name</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">true</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#008000; font-style:italic;"># =&gt; Do Test</span></pre></div></div>

<h2>Y más</h2>
<p>Hay varios cambios más, como Thread Safety, ETag, partial GETs y demás que a mi por ahora no me interesan y por eso no me entiendo mucho más. Pueden consultar el anuncio oficial para ver de que se tratan o cómo pueden hacerle la vida más fácil <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gazer.com.ar/2008/10/27/lo-que-viene-en-rails-2-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Próxima reunión de Argentina on Rails</title>
		<link>http://www.gazer.com.ar/2008/10/25/proxima-reunion-de-argentina-on-rails/</link>
		<comments>http://www.gazer.com.ar/2008/10/25/proxima-reunion-de-argentina-on-rails/#comments</comments>
		<pubDate>Sun, 26 Oct 2008 02:34:03 +0000</pubDate>
		<dc:creator>Gazer</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[ruby on rails]]></category>

		<guid isPermaLink="false">http://www.gazer.com.ar/?p=438</guid>
		<description><![CDATA[El próximo sábado (1 de noviembre) nos estamos reuniendo para compartir, aprender y divertirnos un rato con ruby. El que quiera aparecer, que aparezca y si quiere avisar que va, mejor así calculo bien la cantidad de mates que tenemos que tener . La cita es en la facultad de ingeniería de la UBA, aula [...]]]></description>
			<content:encoded><![CDATA[<p>El próximo sábado (1 de noviembre) nos estamos reuniendo para compartir, aprender y divertirnos un rato con ruby. El que quiera aparecer, que aparezca y si quiere avisar que va, mejor así calculo bien la cantidad de mates que tenemos que tener <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>La cita es en la facultad de ingeniería de la UBA, aula 402 (4to piso) a partir de las 11hs. Más detalles de como se va a organizar la cosa <a href="http://blogs.onrails.com.ar/2008/10/21/proxima-reunion-1-de-noviembre">acá</a> (incluye un mapa para aquellos que no conozcan la facultad).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gazer.com.ar/2008/10/25/proxima-reunion-de-argentina-on-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Usando Rails.cache en 2.1.x</title>
		<link>http://www.gazer.com.ar/2008/10/21/usando-rails-cache/</link>
		<comments>http://www.gazer.com.ar/2008/10/21/usando-rails-cache/#comments</comments>
		<pubDate>Wed, 22 Oct 2008 01:46:00 +0000</pubDate>
		<dc:creator>Gazer</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[observer]]></category>
		<category><![CDATA[ruby on rails]]></category>

		<guid isPermaLink="false">http://www.gazer.com.ar/?p=400</guid>
		<description><![CDATA[Para uno de los sitios que tenemos montados llegó la hora de optimizar algunas partes para descargar la DB un poco. Lo primero (y por ahora único ) que se hizo fue cachear la instancia que representa a la Etapa actual del juego en memoria, para así no cargarla en cada request. El código original [...]]]></description>
			<content:encoded><![CDATA[<p>Para uno de los sitios que tenemos montados llegó la hora de optimizar algunas partes para descargar la DB un poco. Lo primero (y por ahora único <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> ) que se hizo fue cachear la instancia que representa a la Etapa actual del juego en memoria, para así no cargarla en cada request.</p>
<p>El código original era :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Stage <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">current</span>
    t = <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span>.<span style="color:#9900CC;">utc</span>
    find<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:first</span>, <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;start_at &lt; = ? AND end_at &gt;= ?&quot;</span>, t, t<span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>y lo cambiamos para usar el nuevo sistema de cache de Rails 2.1.x que realmente fue simplificado. Hay varios sitio donde hablan sobre el cache en 2.1, les recomiendo mirar el <a href="http://railscasts.com/episodes/115">screencast</a> de RailsCasts y <a href="http://ryandaigle.com/articles/2007/12/19/what-s-new-in-edge-rails-pluggable-controller-caching">este</a> y <a href="http://thewebfellas.com/blog/2008/6/9/rails-2-1-now-with-better-integrated-caching">este</a> post.</p>
<p>El código modificado quedó como se muestra a continuación.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># config.environment.rb</span>
config.<span style="color:#9900CC;">cache_store</span> = <span style="color:#ff3333; font-weight:bold;">:mem_cache_store</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># app/models/stage.rb</span>
<span style="color:#9966CC; font-weight:bold;">class</span> Stage <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">current</span>
    <span style="color:#0066ff; font-weight:bold;">@current</span> = Rails.<span style="color:#9900CC;">cache</span>.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'stage_current'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@current</span>.<span style="color:#0000FF; font-weight:bold;">nil</span>? <span style="color:#006600; font-weight:bold;">||</span> <span style="color:#0066ff; font-weight:bold;">@current</span>.<span style="color:#9900CC;">closed</span>?
      t = <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span>.<span style="color:#9900CC;">utc</span>
      <span style="color:#0066ff; font-weight:bold;">@current</span> = find<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:first</span>, <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;start_at &lt; = ? AND end_at &gt;= ?&quot;</span>, t, t<span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      Rails.<span style="color:#9900CC;">cache</span>.<span style="color:#9900CC;">write</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'stage_current'</span>, <span style="color:#0066ff; font-weight:bold;">@current</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#0066ff; font-weight:bold;">@current</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>La condición del <code>if</code> es necesaria por dos motivos : la primera por si el cache fue limpiado y la segunda para invalidar el valor guardado actualmente si la etapa eterminó, para que la nueva etapa pase a ocupar el cache.</p>
<p>En este caso estamos usando MemCache como CacheStore ya que se comparte entre más de un webserver y simplifica expirar el cache.</p>
<p>Lo único que resta es expirar el cache en caso de que cambie el modelo, que además de la fecha de finalización contiene textos que son usados en la web (como las bases y condiciones, premios, etc). Para eso creamos un Observer que se encargue de eso cuando una etapa es guardada y además es la etapa actual (si no, no tiene sentido hacer nada) :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># app/models/stage_observer.rb</span>
<span style="color:#9966CC; font-weight:bold;">class</span> StageObserver <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Observer</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> after_save<span style="color:#006600; font-weight:bold;">&#40;</span>stage<span style="color:#006600; font-weight:bold;">&#41;</span>
    Rails.<span style="color:#9900CC;">cache</span>.<span style="color:#9900CC;">delete</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'stage_current'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> stage.<span style="color:#9900CC;">is_current</span>?
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># config/environment.rb</span>
config.<span style="color:#9900CC;">active_record</span>.<span style="color:#9900CC;">observers</span> = <span style="color:#ff3333; font-weight:bold;">:stage_observer</span></pre></div></div>

<p>Con esto bajó bastante el uso de la DB (prácticamente no se puede hacer nada en el sitio sin consultar la etapa actual). Ahora tengo que ver que le pasa a la DB que a veces respondes después de 3 segs :S, pero eso ya escapa a programar <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.gazer.com.ar/2008/10/21/usando-rails-cache/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Refactoring de &#8220;Fat Methods&#8221; &#8211; Episodio 2</title>
		<link>http://www.gazer.com.ar/2008/10/09/refactoring-de-fat-methods-episodio-2/</link>
		<comments>http://www.gazer.com.ar/2008/10/09/refactoring-de-fat-methods-episodio-2/#comments</comments>
		<pubDate>Thu, 09 Oct 2008 21:31:01 +0000</pubDate>
		<dc:creator>Gazer</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[refactoring]]></category>
		<category><![CDATA[ruby on rails]]></category>

		<guid isPermaLink="false">http://www.gazer.com.ar/?p=334</guid>
		<description><![CDATA[Continuando con esta serie de ejemplos de como refactorizar métodos de controladores vamos a seguir ahora con uno que cuando lo volví a ver apestaba feo feo. El método en cuestión tiene por objetivo que el usuario actual se suscriba (es decir, anote) para jugar un partido determinado. Para eso el siguiente código es el [...]]]></description>
			<content:encoded><![CDATA[<p>Continuando con esta serie de ejemplos de como refactorizar métodos de controladores vamos a seguir ahora con uno que cuando lo volví a ver apestaba <em>feo feo</em>.</p>
<p>El método en cuestión tiene por objetivo que el usuario actual se <em>suscriba</em> (es decir, anote) para jugar un partido determinado. Para eso el siguiente código es el que está siendo ejecutado actualmente :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#008000; font-style:italic;"># app/controllers/matches_controllers.rb</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> subscribe
    flash<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:notice</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;Ya formás parte del equipo!&quot;</span> <span style="color:#9966CC; font-weight:bold;">and</span> \
        redirect_to match_path<span style="color:#006600; font-weight:bold;">&#40;</span>@match<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">and</span> \
        <span style="color:#0000FF; font-weight:bold;">return</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@match</span>.<span style="color:#9900CC;">has_player</span>? current_user
&nbsp;
    flash<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:error</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;El equipo está completo.&quot;</span> \
      <span style="color:#9966CC; font-weight:bold;">and</span> redirect_to match_path<span style="color:#006600; font-weight:bold;">&#40;</span>@match<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">and</span> <span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#0000FF; font-weight:bold;">return</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@match</span>.<span style="color:#9900CC;">available_places</span><span style="color:#006600; font-weight:bold;">&#40;</span>params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:team</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">to_i</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&lt;</span> = <span style="color:#006666;">0</span>
&nbsp;
    <span style="color:#0066ff; font-weight:bold;">@match</span>.<span style="color:#9900CC;">players</span>.<span style="color:#9900CC;">create</span> <span style="color:#ff3333; font-weight:bold;">:user</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> current_user, <span style="color:#ff3333; font-weight:bold;">:team</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:team</span><span style="color:#006600; font-weight:bold;">&#93;</span>
&nbsp;
    redirect_to match_path<span style="color:#006600; font-weight:bold;">&#40;</span>@match<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Lo feo del problema se puede ver desde dos perspectivas : una que es una excusa y otra que es la razón de la desprolijidad. La excusa para este código tan horrible es que en caso de no poder agregar el jugador al equipo elegido tengo que mostrar un mensaje de error y redireccionar. Pero el <code>redirect_to</code> lo que hace es setear un header nada más, es decir que no hace un return auto-mágico, y de no hacerlo yo el segundo <code>redirect_to</code> (ubicado al final del código) haría que se lance una <code>Exception</code> por haber reenviado los headers.</p>
<p>El problema real es que estoy delegando en el controlador la responsabilidad de la clase <code>Player</code> para determinar si es válido crear una instancia para un partido y usuario dado. </p>
<p>Es por eso que lo primero que debemos hacer es usar los <a href="http://api.rubyonrails.org/classes/ActiveRecord/Validations.html">validators</a> de Rails para esta tarea :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#008000; font-style:italic;"># app/models/player.rb</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> validate
    errors.<span style="color:#9900CC;">add_to_base</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;Ya formás parte del equipo!&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> match.<span style="color:#9900CC;">has_player</span>? user
    errors.<span style="color:#9900CC;">add_to_base</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;El equipo está completo.&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> match.<span style="color:#9900CC;">available_places</span><span style="color:#006600; font-weight:bold;">&#40;</span>team<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&lt;</span> = <span style="color:#006666;">0</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>En este caso los errores no dependen de un atributo, por lo que usamos <code>add_to_base</code> para que los errores digan lo que queremos. Este método <code>validate</code> es llamado por Rails al crear o actualizar una instancia de <code>Player</code>, y si hay algún error nunca llega a la DB.</p>
<p>Habiendo quitado la validación del controlador ahora podemos escribirlo de una forma más prolija y entendible :
</pre>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#008000; font-style:italic;"># app/controllers/matches_controllers.rb</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> subscribe
    <span style="color:#0066ff; font-weight:bold;">@player</span> = <span style="color:#0066ff; font-weight:bold;">@match</span>.<span style="color:#9900CC;">players</span>.<span style="color:#9900CC;">create</span> <span style="color:#ff3333; font-weight:bold;">:user</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> current_user, <span style="color:#ff3333; font-weight:bold;">:team</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:team</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">to_i</span>
&nbsp;
    flash<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:notice</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#0066ff; font-weight:bold;">@player</span>.<span style="color:#9900CC;">errors</span>.<span style="color:#9900CC;">full_messages</span>.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;, &quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@player</span>.<span style="color:#9900CC;">errors</span>.<span style="color:#9900CC;">any</span>?
&nbsp;
    redirect_to match_path<span style="color:#006600; font-weight:bold;">&#40;</span>@match<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Lovely <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Se crea un <code>Player</code> para el <code>Match</code>, se prepara una alerta visual en caso de que haya algún error y luego se redirige a la página del partido. Si ven el antes y el después creo que nadie me va a negar de la mejora <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>Por hoy es todo, hasta la próxima entrega!.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gazer.com.ar/2008/10/09/refactoring-de-fat-methods-episodio-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

