<?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; refactoring</title>
	<atom:link href="http://www.gazer.com.ar/tag/refactoring/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>Refactoring de &#8220;Fat Methods&#8221; &#8211; Episodio 5</title>
		<link>http://www.gazer.com.ar/2009/03/18/refactoring-de-fat-methods-episodio-5/</link>
		<comments>http://www.gazer.com.ar/2009/03/18/refactoring-de-fat-methods-episodio-5/#comments</comments>
		<pubDate>Wed, 18 Mar 2009 14:30:00 +0000</pubDate>
		<dc:creator>Gazer</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[refactoring]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.gazer.com.ar/?p=1040</guid>
		<description><![CDATA[Pasar programadores PHP a Ruby no siempre es una tarea trivial, mayormente porque lo primero que tratan de hacer es escribir código en lugar de pensar que es lo que quieren hacer . No es que me queje, a todos nos pasa que resolvemos el problema como primero sale (más aún cuando las fechas de [...]]]></description>
			<content:encoded><![CDATA[<p>Pasar programadores PHP a Ruby no siempre es una tarea trivial, mayormente porque lo primero que tratan de hacer es escribir código en lugar de pensar que es lo que quieren hacer <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . No es que me queje, a todos nos pasa que resolvemos el problema como primero sale (más aún cuando las fechas de entrega son apretadas <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>El otro día queriendo modificar un código me encuentro con este before_filter en un controller :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> setprofile
  <span style="color:#0066ff; font-weight:bold;">@viewer</span> = <span style="color:#0000FF; font-weight:bold;">false</span>
  <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#006600; font-weight:bold;">&#40;</span>!params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'id'</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&amp;&amp;</span> !params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'profile_id'</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0066ff; font-weight:bold;">@profile</span> = <span style="color:#0066ff; font-weight:bold;">@passport</span>
  <span style="color:#9966CC; font-weight:bold;">else</span>
    <span style="color:#9966CC; font-weight:bold;">if</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'profile_id'</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      pid = params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'profile_id'</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    <span style="color:#9966CC; font-weight:bold;">else</span>
      pid = params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'id'</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#0066ff; font-weight:bold;">@profile</span> = Passport.<span style="color:#9900CC;">find_by_id</span><span style="color:#006600; font-weight:bold;">&#40;</span>pid<span style="color:#006600; font-weight:bold;">&#41;</span>			
    <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#006600; font-weight:bold;">&#40;</span>!@profile<span style="color:#006600; font-weight:bold;">&#41;</span> 
      redirect_to<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:controller</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'my3dg'</span>, <span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'show'</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:#0000FF; font-weight:bold;">false</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#006600; font-weight:bold;">&#40;</span>@profile.<span style="color:#9900CC;">id</span> != <span style="color:#0066ff; font-weight:bold;">@passport</span>.<span style="color:#9900CC;">id</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0066ff; font-weight:bold;">@viewer</span> = <span style="color:#0000FF; font-weight:bold;">true</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></pre></td></tr></table></div>

<p>Lo primero que pense &#8220;uff, que paja, que complicado&#8221; hasta que miré mejor la estructura y ahí comprendí que en realidad era muy simple, solo que estaba escrito de forma complicada. Lo primero que me gustó de Ruby cuando empecé a entenderlo fue el uso de &#8220;||&#8221; para reemplazar esos molestos if anidados cuando tengo más de una opción. &#8220;Si no está a, poner a en el valor default&#8221;. En ruby es un simple &#8220;a || valor_default&#8221; (ojo con los valores de verdad en ruby).</p>
<p>Lo otro que veo mucho (incluso en los trabajos que corrijo en la facultad) es utilizar un if para después setear una variable en true o false, cuando casi todos los lenguajes aceptan expresiones booleanas del lado derecho de la igualdad.</p>
<p>Refactorizando el método anterior obtenemos el siguiente código :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> setprofile
  <span style="color:#0066ff; font-weight:bold;">@profile</span> = Passport.<span style="color:#9900CC;">find_by_id</span><span style="color:#006600; font-weight:bold;">&#40;</span>params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'profile_id'</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">||</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'id'</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;">||</span> <span style="color:#0066ff; font-weight:bold;">@passport</span>
  <span style="color:#0066ff; font-weight:bold;">@viewer</span> = <span style="color:#0066ff; font-weight:bold;">@profile</span>.<span style="color:#9900CC;">id</span> != <span style="color:#0066ff; font-weight:bold;">@passport</span>.<span style="color:#9900CC;">id</span>
  redirect_to<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:controller</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'my3dg'</span>, <span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'show'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#0066ff; font-weight:bold;">@profile</span>
  <span style="color:#0000FF; font-weight:bold;">return</span> <span style="color:#0000FF; font-weight:bold;">false</span> <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#0066ff; font-weight:bold;">@profile</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>

<p>Como nota, uso find_by_id porque retorna nil en caso de no encontrar el registro, en cambio find tira una excepción RecordNotFound, de esa forma puedo acoplar otro &#8220;||&#8221; para setear el valor default (@passport es la credencial del usuario loggeado en este caso).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gazer.com.ar/2009/03/18/refactoring-de-fat-methods-episodio-5/feed/</wfw:commentRss>
		<slash:comments>1</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>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>Refactoring de &#8220;Fat Methods&#8221; &#8211; Episodio 3</title>
		<link>http://www.gazer.com.ar/2008/10/30/refactoring-de-fat-methods-episodio-3/</link>
		<comments>http://www.gazer.com.ar/2008/10/30/refactoring-de-fat-methods-episodio-3/#comments</comments>
		<pubDate>Thu, 30 Oct 2008 11:44:09 +0000</pubDate>
		<dc:creator>Gazer</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[observer]]></category>
		<category><![CDATA[refactoring]]></category>

		<guid isPermaLink="false">http://www.gazer.com.ar/?p=358</guid>
		<description><![CDATA[En el Episodio 1 trabajé el método Matches#create y había dejado una parte a la que Des preguntó por qué la ignoraba. En ese momento no quería extender mucho más el post por lo que en esta oportunidad vamos a completar el refactoring pendiente. El código que habíamos logrado en ese momento es el siguiente: [...]]]></description>
			<content:encoded><![CDATA[<p>En el <a href="http://www.gazer.com.ar/2008/10/02/refactoring-de-fat-methods-episodio-1/">Episodio 1</a> trabajé el método <code>Matches#create</code> y había dejado una parte a la que <a href="http://www.gazer.com.ar/2008/10/02/refactoring-de-fat-methods-episodio-1/#comment-32897">Des</a> preguntó por qué la ignoraba. En ese momento no quería extender mucho más el post por lo que en esta oportunidad vamos a completar el refactoring pendiente.</p>
<p>El código que habíamos logrado en ese momento es el siguiente:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#9966CC; font-weight:bold;">def</span> create
    <span style="color:#0066ff; font-weight:bold;">@match</span> = current_user.<span style="color:#9900CC;">matches</span>.<span style="color:#9900CC;">create</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;">:match</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    <span style="color:#0066ff; font-weight:bold;">@notifications</span> = <span style="color:#0066ff; font-weight:bold;">@match</span>.<span style="color:#9900CC;">owner</span>.<span style="color:#9900CC;">friends</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>f<span style="color:#006600; font-weight:bold;">|</span> f.<span style="color:#9900CC;">notify_new_matches</span>? <span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">collect</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&amp;</span>email<span style="color:#006600; font-weight:bold;">&#41;</span>
    Emailer.<span style="color:#9900CC;">deliver_match_created</span><span style="color:#006600; font-weight:bold;">&#40;</span>@match, <span style="color:#0066ff; font-weight:bold;">@notifications</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;">@notifications</span>.<span style="color:#9900CC;">any</span>?
&nbsp;
    flash<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:success</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;El partido fue creado.&quot;</span>
    redirect_to matches_path
  <span style="color:#9966CC; font-weight:bold;">rescue</span>
    render <span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'new'</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Lo que nos quedaba terminar era cómo mejorar el envío de las notificaciones para aquellos amigos que tenían activa dicha opción. Como primer paso vamos a separar la lógica del mailer de manera que no quede mezclado en el controller, y ya que estamos, que no importa donde se cree un partido el email salga igual sin la necesidad de copiar y pegar código.</p>
<p>Una opción es usar un callback <code>after_create</code> como ya hicimos en el post pasado, pero a mi no me gusta mezclar en los modelos lógica que no tiene que ver con la persistencia. La razón es que esta tarea de enviar emails no es algo propio de un modelo, no debería tener esa responsabilidad. Pero dejarla en el controller sería &#8220;irresponsable&#8221; <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> .</p>
<p>Una opción, no muy acertada, podría ser usa un filtro que se ejecute después del <code>create</code> (<code>after_filter</code>) pero quizás no siempre tendríamos la posibilidad de ejecutar un filtro. La mejor opción es utilizar un <code>Observer</code> para mirar al modelo <code>Match</code>, y cuando uno nuevo es creado, ejecutar nuestro código.</p>
<p>Los Observers se registran a si mismos a un modelo dado escuchando los callbacks que nosotros definamos. Estos callbacks son los mismos que existen en <code>ActiveRecord</code>, siendo algunos : after_create, before_create, after_save, etc&#8230;</p>
<p>Como vemos, el <code>Observer</code> es casi lo mismo (a nivel práctico claro está) que usar los callbacks de <code>ActiveRecord</code> pero sin tener que mezclar acciones que no son propias de los modelos. Muchas veces uno se olvida que existen ya que generalmente se los utiliza para las estrategias de invalidación de cache (que puntualmente estos observers se llaman Sweepers).</p>
<p>El código del observer quedaría ahora :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#008000; font-style:italic;"># app/model/match_observer.rb</span>
  <span style="color:#9966CC; font-weight:bold;">class</span> MatchObserver <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_create<span style="color:#006600; font-weight:bold;">&#40;</span>contact<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0066ff; font-weight:bold;">@notifications</span> = <span style="color:#0066ff; font-weight:bold;">@match</span>.<span style="color:#9900CC;">owner</span>.<span style="color:#9900CC;">friends</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>f<span style="color:#006600; font-weight:bold;">|</span> f.<span style="color:#9900CC;">notify_new_matches</span>? <span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">collect</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&amp;</span>:email<span style="color:#006600; font-weight:bold;">&#41;</span>
      Emailer.<span style="color:#9900CC;">deliver_match_created</span><span style="color:#006600; font-weight:bold;">&#40;</span>@match, <span style="color:#0066ff; font-weight:bold;">@notifications</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;">@notifications</span>.<span style="color:#9900CC;">any</span>?
    <span style="color:#9966CC; font-weight:bold;">end</span>
 <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Como se ve, en ningún lugar hacemos referencia al modelo observado. Esto es porque Rails lo infiere automáticamente a partir del nombre del <code>Observer</code>. Claro está que si por alguna razón usamos un nombre que no permita inferirlo lo podemos especificar.</p>
<p>Lo único que faltaría es decirle a Rails que existe el <code>Observer</code>, para que lo cargue y lo registre con la clase correspondiente. Para eso debemos agregar en nuestros environment lo siguiente :
</pre>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  config.<span style="color:#9900CC;">active_record</span>.<span style="color:#9900CC;">observers</span> = <span style="color:#ff3333; font-weight:bold;">:match_observer</span></pre></div></div>

<p>Ahora si, veamos como quedó nuestro controlador totalmente refactorizado :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#008000; font-style:italic;"># Dentro de matches_controllers.rb</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> create
    <span style="color:#0066ff; font-weight:bold;">@match</span> = current_user.<span style="color:#9900CC;">matches</span>.<span style="color:#9900CC;">create</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;">:match</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    flash<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:success</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;El partido fue creado.&quot;</span>
&nbsp;
    redirect_to matches_path
  <span style="color:#9966CC; font-weight:bold;">rescue</span>
    render <span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'new'</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Ahora si nuestro controlador está bastante mejor. Para la próxima entrega vamos a como mejorar las asociaciones de los modelos para poder cambiar el <code>match.owner.friends.select</code> que no es para nada prolijo.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gazer.com.ar/2008/10/30/refactoring-de-fat-methods-episodio-3/feed/</wfw:commentRss>
		<slash:comments>1</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>
		<item>
		<title>Refactoring de &#8220;Fat Methods&#8221; &#8211; Episodio 1</title>
		<link>http://www.gazer.com.ar/2008/10/02/refactoring-de-fat-methods-episodio-1/</link>
		<comments>http://www.gazer.com.ar/2008/10/02/refactoring-de-fat-methods-episodio-1/#comments</comments>
		<pubDate>Thu, 02 Oct 2008 12:45:14 +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=323</guid>
		<description><![CDATA[Luego de escribir mucho código uno comienza a mirar a ver que hacen los de al lado, y al mirar se da cuenta de lo mal que uno escribe código cuando comienza con un nuevo lenguaje . Algo de eso me pasa hoy en día con ¡Falta Uno!. En el camino de emprolijar las cosas [...]]]></description>
			<content:encoded><![CDATA[<p>Luego de escribir mucho código uno comienza a mirar a ver que hacen los de al lado, y al mirar se da cuenta de lo mal que uno escribe código cuando comienza con un nuevo lenguaje <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Algo de eso me pasa hoy en día con <a href="http://www.falta-uno.com.ar" target="_blank">¡Falta Uno!</a>.</p>
<p>En el camino de emprolijar las cosas para liberar el código tuve la necesita de poner a refactorizar el código porque hay partes que no son nada bonito. Voy a tratar de plasmar en los siguientes posts algunas lecciones aprendidas junto con el paso a paso del refactoring del código.</p>
<p>Antes que nada y como buena práctica es ideal tener buenos test sobre los que se va a refactorizar ya que es muy fácil romper alguna funcionalidad que se <em>suponía</em> que andaba. Si bien para los ejemplos acá voy a ignorar esta <em><strong>buena práctica</strong></em>, no se los aconsejo <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>Vamos a empezar con el método <code>create</code> de controlador <code>Matches</code>, encargado de crear un nuevo partido :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#9966CC; font-weight:bold;">def</span> create
    <span style="color:#0066ff; font-weight:bold;">@match</span> = current_user.<span style="color:#9900CC;">matches</span>.<span style="color:#9900CC;">create</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;">:match</span><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;">if</span> <span style="color:#0066ff; font-weight:bold;">@match</span>.<span style="color:#9900CC;">errors</span>.<span style="color:#9900CC;">empty</span>?
      Player.<span style="color:#9900CC;">create</span> <span style="color:#ff3333; font-weight:bold;">:match</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@match</span>, <span style="color:#ff3333; font-weight:bold;">:user</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> current_user
&nbsp;
      <span style="color:#0066ff; font-weight:bold;">@notifications</span> = <span style="color:#0066ff; font-weight:bold;">@match</span>.<span style="color:#9900CC;">owner</span>.<span style="color:#9900CC;">friends</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>f<span style="color:#006600; font-weight:bold;">|</span> f.<span style="color:#9900CC;">notify_new_matches</span>? <span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">collect</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&amp;</span>:email<span style="color:#006600; font-weight:bold;">&#41;</span>
      Emailer.<span style="color:#9900CC;">deliver_match_created</span><span style="color:#006600; font-weight:bold;">&#40;</span>@match, <span style="color:#0066ff; font-weight:bold;">@notifications</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;">@notifications</span>.<span style="color:#9900CC;">any</span>?
&nbsp;
      flash<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:success</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;El partido fue creado.&quot;</span>
      redirect_to matches_path
    <span style="color:#9966CC; font-weight:bold;">else</span>
      render <span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'new'</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">rescue</span>
    render <span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'new'</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Asusta un poco, ¿no?. Para entender el problema, veamos primero como que involucra crear un nuevo partido :</p>
<ul>
<li>Crear el partido</li>
<li>Anotar al usuario que creó el partido en uno de los equipos</li>
<li>Notificar a todos los amigos que se creó un nuevo partido</li>
</ul>
<p>Dado esto, pasemos a analizar los problemas. La primer pregunta que habría que hacerse es : ¿Quién es el responsable de anotar al jugador?, ¿Tiene sentido que un usuario pueda crear un partido sin que esté anotado?. En el contexto nuestro, la respuesta a la última pregunta es &#8220;No&#8221;, solo porque así lo defino yo <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Entonces podemos responder a la primer pregunta : El <code>Match</code> debería ser el responsable de anotar al dueño del partido cuando es creado.</p>
<p>Para lograr esto último lo que debemos hacer es mover la lógica de creación del <code>Player</code> dentro de un callback en el modelo <code>Match</code>, quedando algo así :</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>
  <span style="color:#9966CC; font-weight:bold;">def</span> after_create
    Player.<span style="color:#9900CC;">create</span> <span style="color:#ff3333; font-weight:bold;">:match</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">self</span>, <span style="color:#ff3333; font-weight:bold;">:user</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> owner
  <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 nos aseguramos que se cumpla lo pedido sin correr el riesgo de que se puedan crear matches sin que el owner este anotado inicialmente. También ganaríamos en el caso de que exista alguna otra forma de crear un partido, por ejemplo si agregáramos la posibilidad de crear un partido enviando un email, no tendríamos la necesidad de repetir la lógica inicial en dos lugares diferentes.</p>
<p>Y ahora nuestro controlador queda algo cómo :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#9966CC; font-weight:bold;">def</span> create
    <span style="color:#0066ff; font-weight:bold;">@match</span> = current_user.<span style="color:#9900CC;">matches</span>.<span style="color:#9900CC;">create</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;">:match</span><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;">if</span> <span style="color:#0066ff; font-weight:bold;">@match</span>.<span style="color:#9900CC;">errors</span>.<span style="color:#9900CC;">empty</span>?
      <span style="color:#0066ff; font-weight:bold;">@notifications</span> = <span style="color:#0066ff; font-weight:bold;">@match</span>.<span style="color:#9900CC;">owner</span>.<span style="color:#9900CC;">friends</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>f<span style="color:#006600; font-weight:bold;">|</span> f.<span style="color:#9900CC;">notify_new_matches</span>? <span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">collect</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&amp;</span>:email<span style="color:#006600; font-weight:bold;">&#41;</span>
      Emailer.<span style="color:#9900CC;">deliver_match_created</span><span style="color:#006600; font-weight:bold;">&#40;</span>@match, <span style="color:#0066ff; font-weight:bold;">@notifications</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;">@notifications</span>.<span style="color:#9900CC;">any</span>?
&nbsp;
      flash<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:success</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;El partido fue creado.&quot;</span>
      redirect_to matches_path
    <span style="color:#9966CC; font-weight:bold;">else</span>
      render <span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'new'</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">rescue</span>
    render <span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'new'</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Lo siguiente es limpiar un poco lo lógica del modelo. Una cosa que molesta a la vista son las dos llamadas a <code>render</code>, ¿son realmente necesarias? La respuesta en NO. Con el <code>rescue</code> lo que hacemos es que dada una <code>Exception</code> vuelva al formulario de creación, lo mismo que si el partido no es válido, por lo que simplemente podríamos haber usado el método <code>create!</code> que lanza una <code>Exception</code> si el modelo no es válido evitándonos así el molesto <code>if</code>. Quedando ahora :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#9966CC; font-weight:bold;">def</span> create
    <span style="color:#0066ff; font-weight:bold;">@match</span> = current_user.<span style="color:#9900CC;">matches</span>.<span style="color:#9900CC;">create</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;">:match</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    <span style="color:#0066ff; font-weight:bold;">@notifications</span> = <span style="color:#0066ff; font-weight:bold;">@match</span>.<span style="color:#9900CC;">owner</span>.<span style="color:#9900CC;">friends</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>f<span style="color:#006600; font-weight:bold;">|</span> f.<span style="color:#9900CC;">notify_new_matches</span>? <span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">collect</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&amp;</span>:email<span style="color:#006600; font-weight:bold;">&#41;</span>
    Emailer.<span style="color:#9900CC;">deliver_match_created</span><span style="color:#006600; font-weight:bold;">&#40;</span>@match, <span style="color:#0066ff; font-weight:bold;">@notifications</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;">@notifications</span>.<span style="color:#9900CC;">any</span>?
&nbsp;
    flash<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:success</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;El partido fue creado.&quot;</span>
    redirect_to matches_path
  <span style="color:#9966CC; font-weight:bold;">rescue</span>
    render <span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'new'</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Que si lo comparan con la versión inicial es mucho más legible. &#8220;Fat model, skinny controllers&#8221; es la clave a seguir. Todavía queda por mejorar la forma en que se genera la lista de emails de los amigos que desean recibir la notificación, pero no es algo que me moleste de momento.</p>
<p>En otras entregas seguiré mostrando el resto del refactoring de otro métodos que son aún peores que este <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/02/refactoring-de-fat-methods-episodio-1/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

