<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Simples Ideias</title>
    <description>Blog do Nando Vieira sobre desenvolvimento web</description>
    <language>pt-BR</language>
    <link>http://simplesideias.com.br</link>
    <atom:link href="http://simplesideias.com.br/feed" rel="self" type="application/rss+xml"/>
    <pubDate>Mon, 10 Jun 2013 15:27:00 -0300</pubDate>
    <lastBuildDate>Mon, 10 Jun 2013 15:27:00 -0300</lastBuildDate>
    <item>
      <title>Um pouco mais sobre JavaScript modular</title>
      <description>
        <![CDATA[<p>No <a href="http://simplesideias.com.br/escrevendo-javascript-modular">último artigo</a> do Simples Ideias mostrei como uma implementação &quot;tradicional&quot; poderia ser implementada de um modo um pouco mais modular. O feedback positivo me motivou a escrever esta continuação, em um exemplo de refatoração de uma função que converte timestamps em objetos do tipo <code>Date</code>.</p>

<p>Este método pode receber diferentes tipos de objetos como argumento.</p>

<ul>
<li>Uma instância de <code>Date</code>.</li>
<li>Um <a href="http://en.wikipedia.org/wiki/Unix_time">UNIX Epoch Time</a>.</li>
<li>Uma string no formato <a href="http://www.w3.org/TR/NOTE-datetime">RFC 8601</a>.</li>
<li>Uma string no formato <a href="http://www.ietf.org/rfc/rfc2822.txt">RFC 2822</a>, formato aceito pela função <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse">Date.parse</a>.</li>
</ul>

<p>A primeira implementação que eu tinha era apenas uma função que fazia tudo isso.</p>
<pre class="language-javascript"><code>Utils.parseDate = function(timestamp) {
  var matches, date;
  var diff = 0;

  // we have a date, so just return it.
  if (timestamp.constructor === Date) {
    return timestamp;
  };

  matches = timestamp.toString().match(/(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2}):(\d{2}))?(Z|[+-]\d+)?/);

  if (matches) {
    for (var i = 1; i &lt;= 6; i++) {
      matches[i] = parseInt(matches[i], 10) || 0;
    }

    // month starts on 0
    matches[2] -= 1;

    date = new Date(Date.UTC(matches[1], matches[2], matches[3], matches[4], matches[5], matches[6]));

    // Check if timezone is available.
    matches = matches[7] &amp;&amp; timezone.match(/^([+-])(\d{2})(\d{2})/);

    if (matches) {
      diff += parseInt(matches[2], 10) * 60 * 60 * 1000;
      diff += parseInt(matches[3], 10) * 60 * 1000;
      diff *= matches[1] === &quot;-&quot; ? 1 : -1;
      date.setTime(date.getTime() + diff);
    }
  } else if (typeof(timestamp) == &quot;number&quot;) {
    // UNIX timestamp
    date = new Date();
    date.setTime(timestamp);
  } else if (timestamp.match(/\d+ \d+:\d+:\d+ [+-]\d+ \d+/)) {
    // a valid javascript format with timezone info
    date = new Date();
    date.setTime(Date.parse(timestamp))
  } else {
    // an arbitrary javascript string
    date = new Date();
    date.setTime(Date.parse(timestamp));
  }

  return date;
};
</code></pre>
<p>Embora a função não seja extremamente complicada, está fazendo mais do que deveria. A ideia aqui será extrair cada uma das condições em sua própria função construtora. Decidi criar um namespace chamado <code>DateParser</code>, que irá conter cada um dos adapters. O parsing do timestamp será feito na função <code>parse()</code>. Cada adapter pode estar em seu próprio arquivo, mas para facilitar este exemplo coloquei tudo junto.</p>
<pre class="language-javascript"><code>Module(&quot;DateParser.Date&quot;, function(Adapter){
  Adapter.fn.initialize = function(timestamp) {
    this.timestamp = timestamp;
  };

  // The DateParse.Date adapter will receive a Date instance,
  // so we just have to return it.
  Adapter.fn.parse = function() {
    return this.timestamp;
  };
});

Module(&quot;DateParser.Timestamp&quot;, function(Adapter){
  Adapter.fn.initialize = function(timestamp) {
    this.timestamp = timestamp;
  };

  // We received a UNIX time, so we can just set it
  // through Date#setTime function.
  Adapter.fn.parse = function() {
    var date = new Date();
    date.setTime(this.timestamp);
  };
});

Module(&quot;DateParser.ISO8601&quot;, function(Adapter){
  Adapter.FORMAT_REGEX = /(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2}):(\d{2}))?(Z|\+0000)?/;

  Adapter.fn.initialize = function(timestamp) {
    this.timestamp = timestamp;
  };

  Adapter.fn.parse = function() {
    var date;
    var matches = this.timestamp.match(Adapter.FORMAT_REGEX);
    var diff = 0;

    for (var i = 1; i &lt;= 6; i++) {
      matches[i] = parseInt(matches[i], 10) || 0;
    }

    var year     = matches[1]
      , month    = matches[2] - 1 // remember that months starts on zero
      , day      = matches[3]
      , hours    = matches[4]
      , minutes  = matches[5]
      , seconds  = matches[6]
      , timezone = matches[7]
    ;

    // Always set the date as UTC. We&#39;ll consider the
    // timezone later on when is available.
    date = new Date(Date.UTC(year, month, day, hours, minutes, seconds));

    // Check if timezone is available.
    matches = timezone &amp;&amp; timezone.match(/^([+-])(\d{2})(\d{2})/);

    if (matches) {
      diff += parseInt(matches[2], 10) * 60 * 60 * 1000;
      diff += parseInt(matches[3], 10) * 60 * 1000;
      diff *= matches[1] === &quot;-&quot; ? 1 : -1;
      date.setTime(date.getTime() + diff);
    }

    return date;
  };
});

Module(&quot;DateParser.RFC2822&quot;, function(Adapter){
  Adapter.fn.initialize = function(timestamp) {
    this.timestamp = timestamp;
  };

  Adapter.fn.parse = function() {
    var date = new Date();
    date.setTime(Date.parse(this.timestamp));
  };
});
</code></pre>
<p>A implementação da função <code>DateParser.parse()</code> vai mudar, pois precisaremos delegar o timestamp para cada um dos adapters. Vamos aproveitar para dar uma refatorada no modo como fazemos as condições.</p>
<pre class="language-javascript"><code>Module(&quot;DateParser&quot;, function(DateParser){
  DateParser.parse = function(timestamp) {
    if (timestamp.constructor === Date) {
      return DateParser.Date(timestamp).parse();
    }

    if (typeof(timestamp) === &quot;number&quot;) {
      return DateParser.Timestamp(timestamp).parse();
    }

    if (typeof(timestamp) === &quot;string&quot; &amp;&amp; DateParser.ISO8601.FORMAT_REGEX.match(timestamp)) {
      return DateParser.ISO8601(timestamp).parse();
    }

    return DateParser.RFC2822(timestamp).parse();
  };
}, {});
</code></pre>
<p>Muito mais simples! Mas ainda temos espaço para melhorar essa implementação. Primeiro vamos extrair as condicionais para cada adapter. Note abaixo que estou exibindo apenas a função <code>match()</code>.</p>
<pre class="language-javascript"><code>Module(&quot;DateParser.Date&quot;, function(Adapter){
  Adapter.fn.match = function() {
    return this.timestamp.constructor === Date;
  };
});

Module(&quot;DateParser.Timestamp&quot;, function(Adapter){
  Adapter.fn.match = function() {
    return typeof(this.timestamp) === &quot;number&quot;;
  };
});

Module(&quot;DateParser.ISO8601&quot;, function(Adapter){
  var FORMAT_REGEX = /(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2}):(\d{2}))?(Z|[+-]\d+)?/;

  Adapter.fn.match = function() {
    return this.timestamp.toString().match(FORMAT_REGEX);
  };
});

Module(&quot;DateParser.RFC2822&quot;, function(Adapter){
  // Always return true, since this will be the default adapter.
  Adapter.fn.match = function() {
    return true;
  };
});
</code></pre>
<p>Agora, podemos alterar a implementação do método <code>DateParser.parse</code> para usar a função <code>match()</code> definido em cada um dos adapters. Note que esta função foi definida na instância. Isso significa que vamos ter que instanciar o adapter durante o processo de descoberta que faremos em um loop.</p>

<p>Vamos precisar de um array que define a ordem dos adapters.</p>
<pre class="language-javascript"><code>Module(&quot;DateParser&quot;, function(DateParser){
  DateParser.parse = function(timestamp) {
    var adapters = [&quot;Date&quot;, &quot;Timestamp&quot;, &quot;ISO8601&quot;, &quot;RFC2822&quot;];
  };
}, {});
</code></pre>
<p>Nós iremos usar a função <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some">Array.prototype.some</a> para saber qual o adapter deve ser usado. Essa função para de ser executada quando um dos callbacks retornar <code>true</code>, o que é exatamente o precisamos fazer.</p>
<pre class="language-javascript"><code>Module(&quot;DateParser&quot;, function(DateParser){
  DateParser.parse = function(timestamp) {
    var adapters = [&quot;Date&quot;, &quot;Timestamp&quot;, &quot;ISO8601&quot;, &quot;RFC2822&quot;];
    var parser;

    adapters.some(function(name){
      // Retrieve the adapter and instantiate it with the
      // provided timestamp.
      parser = DateParser[name](timestamp);
      return parser.match();
    });

    // Finally return the parsed timestamp.
    return parser.parse();
  };
}, {});
</code></pre>
<p>É isso aí. Agora estou satisfeito com esta implementação!</p>

<h2>Finalizando</h2>

<p>No nosso exemplo, extrair cada parser e unificar a API desses adapters, automatizando o processo de descoberta de qual o adapter mais indicado para o timestamp passado como argumento tornou o nosso código muito mais simples de entender. Você não precisa, por exemplo, ler toda a função para saber como um determinado parser funciona.</p>

<p>Uma outra coisa que você precisa saber é que toda implementação possui espaço para melhorar. Mais importante que saber como fazer este tipo de melhoria é saber quando parar, pois isso pode ser uma coisa sem fim.</p>
]]>
      </description>
      <content:encoded>
        <![CDATA[<p>No <a href="http://simplesideias.com.br/escrevendo-javascript-modular">último artigo</a> do Simples Ideias mostrei como uma implementação &quot;tradicional&quot; poderia ser implementada de um modo um pouco mais modular. O feedback positivo me motivou a escrever esta continuação, em um exemplo de refatoração de uma função que converte timestamps em objetos do tipo <code>Date</code>.</p>

<p>Este método pode receber diferentes tipos de objetos como argumento.</p>

<ul>
<li>Uma instância de <code>Date</code>.</li>
<li>Um <a href="http://en.wikipedia.org/wiki/Unix_time">UNIX Epoch Time</a>.</li>
<li>Uma string no formato <a href="http://www.w3.org/TR/NOTE-datetime">RFC 8601</a>.</li>
<li>Uma string no formato <a href="http://www.ietf.org/rfc/rfc2822.txt">RFC 2822</a>, formato aceito pela função <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse">Date.parse</a>.</li>
</ul>

<p>A primeira implementação que eu tinha era apenas uma função que fazia tudo isso.</p>
<pre class="language-javascript"><code>Utils.parseDate = function(timestamp) {
  var matches, date;
  var diff = 0;

  // we have a date, so just return it.
  if (timestamp.constructor === Date) {
    return timestamp;
  };

  matches = timestamp.toString().match(/(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2}):(\d{2}))?(Z|[+-]\d+)?/);

  if (matches) {
    for (var i = 1; i &lt;= 6; i++) {
      matches[i] = parseInt(matches[i], 10) || 0;
    }

    // month starts on 0
    matches[2] -= 1;

    date = new Date(Date.UTC(matches[1], matches[2], matches[3], matches[4], matches[5], matches[6]));

    // Check if timezone is available.
    matches = matches[7] &amp;&amp; timezone.match(/^([+-])(\d{2})(\d{2})/);

    if (matches) {
      diff += parseInt(matches[2], 10) * 60 * 60 * 1000;
      diff += parseInt(matches[3], 10) * 60 * 1000;
      diff *= matches[1] === &quot;-&quot; ? 1 : -1;
      date.setTime(date.getTime() + diff);
    }
  } else if (typeof(timestamp) == &quot;number&quot;) {
    // UNIX timestamp
    date = new Date();
    date.setTime(timestamp);
  } else if (timestamp.match(/\d+ \d+:\d+:\d+ [+-]\d+ \d+/)) {
    // a valid javascript format with timezone info
    date = new Date();
    date.setTime(Date.parse(timestamp))
  } else {
    // an arbitrary javascript string
    date = new Date();
    date.setTime(Date.parse(timestamp));
  }

  return date;
};
</code></pre>
<p>Embora a função não seja extremamente complicada, está fazendo mais do que deveria. A ideia aqui será extrair cada uma das condições em sua própria função construtora. Decidi criar um namespace chamado <code>DateParser</code>, que irá conter cada um dos adapters. O parsing do timestamp será feito na função <code>parse()</code>. Cada adapter pode estar em seu próprio arquivo, mas para facilitar este exemplo coloquei tudo junto.</p>
<pre class="language-javascript"><code>Module(&quot;DateParser.Date&quot;, function(Adapter){
  Adapter.fn.initialize = function(timestamp) {
    this.timestamp = timestamp;
  };

  // The DateParse.Date adapter will receive a Date instance,
  // so we just have to return it.
  Adapter.fn.parse = function() {
    return this.timestamp;
  };
});

Module(&quot;DateParser.Timestamp&quot;, function(Adapter){
  Adapter.fn.initialize = function(timestamp) {
    this.timestamp = timestamp;
  };

  // We received a UNIX time, so we can just set it
  // through Date#setTime function.
  Adapter.fn.parse = function() {
    var date = new Date();
    date.setTime(this.timestamp);
  };
});

Module(&quot;DateParser.ISO8601&quot;, function(Adapter){
  Adapter.FORMAT_REGEX = /(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2}):(\d{2}))?(Z|\+0000)?/;

  Adapter.fn.initialize = function(timestamp) {
    this.timestamp = timestamp;
  };

  Adapter.fn.parse = function() {
    var date;
    var matches = this.timestamp.match(Adapter.FORMAT_REGEX);
    var diff = 0;

    for (var i = 1; i &lt;= 6; i++) {
      matches[i] = parseInt(matches[i], 10) || 0;
    }

    var year     = matches[1]
      , month    = matches[2] - 1 // remember that months starts on zero
      , day      = matches[3]
      , hours    = matches[4]
      , minutes  = matches[5]
      , seconds  = matches[6]
      , timezone = matches[7]
    ;

    // Always set the date as UTC. We&#39;ll consider the
    // timezone later on when is available.
    date = new Date(Date.UTC(year, month, day, hours, minutes, seconds));

    // Check if timezone is available.
    matches = timezone &amp;&amp; timezone.match(/^([+-])(\d{2})(\d{2})/);

    if (matches) {
      diff += parseInt(matches[2], 10) * 60 * 60 * 1000;
      diff += parseInt(matches[3], 10) * 60 * 1000;
      diff *= matches[1] === &quot;-&quot; ? 1 : -1;
      date.setTime(date.getTime() + diff);
    }

    return date;
  };
});

Module(&quot;DateParser.RFC2822&quot;, function(Adapter){
  Adapter.fn.initialize = function(timestamp) {
    this.timestamp = timestamp;
  };

  Adapter.fn.parse = function() {
    var date = new Date();
    date.setTime(Date.parse(this.timestamp));
  };
});
</code></pre>
<p>A implementação da função <code>DateParser.parse()</code> vai mudar, pois precisaremos delegar o timestamp para cada um dos adapters. Vamos aproveitar para dar uma refatorada no modo como fazemos as condições.</p>
<pre class="language-javascript"><code>Module(&quot;DateParser&quot;, function(DateParser){
  DateParser.parse = function(timestamp) {
    if (timestamp.constructor === Date) {
      return DateParser.Date(timestamp).parse();
    }

    if (typeof(timestamp) === &quot;number&quot;) {
      return DateParser.Timestamp(timestamp).parse();
    }

    if (typeof(timestamp) === &quot;string&quot; &amp;&amp; DateParser.ISO8601.FORMAT_REGEX.match(timestamp)) {
      return DateParser.ISO8601(timestamp).parse();
    }

    return DateParser.RFC2822(timestamp).parse();
  };
}, {});
</code></pre>
<p>Muito mais simples! Mas ainda temos espaço para melhorar essa implementação. Primeiro vamos extrair as condicionais para cada adapter. Note abaixo que estou exibindo apenas a função <code>match()</code>.</p>
<pre class="language-javascript"><code>Module(&quot;DateParser.Date&quot;, function(Adapter){
  Adapter.fn.match = function() {
    return this.timestamp.constructor === Date;
  };
});

Module(&quot;DateParser.Timestamp&quot;, function(Adapter){
  Adapter.fn.match = function() {
    return typeof(this.timestamp) === &quot;number&quot;;
  };
});

Module(&quot;DateParser.ISO8601&quot;, function(Adapter){
  var FORMAT_REGEX = /(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2}):(\d{2}))?(Z|[+-]\d+)?/;

  Adapter.fn.match = function() {
    return this.timestamp.toString().match(FORMAT_REGEX);
  };
});

Module(&quot;DateParser.RFC2822&quot;, function(Adapter){
  // Always return true, since this will be the default adapter.
  Adapter.fn.match = function() {
    return true;
  };
});
</code></pre>
<p>Agora, podemos alterar a implementação do método <code>DateParser.parse</code> para usar a função <code>match()</code> definido em cada um dos adapters. Note que esta função foi definida na instância. Isso significa que vamos ter que instanciar o adapter durante o processo de descoberta que faremos em um loop.</p>

<p>Vamos precisar de um array que define a ordem dos adapters.</p>
<pre class="language-javascript"><code>Module(&quot;DateParser&quot;, function(DateParser){
  DateParser.parse = function(timestamp) {
    var adapters = [&quot;Date&quot;, &quot;Timestamp&quot;, &quot;ISO8601&quot;, &quot;RFC2822&quot;];
  };
}, {});
</code></pre>
<p>Nós iremos usar a função <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some">Array.prototype.some</a> para saber qual o adapter deve ser usado. Essa função para de ser executada quando um dos callbacks retornar <code>true</code>, o que é exatamente o precisamos fazer.</p>
<pre class="language-javascript"><code>Module(&quot;DateParser&quot;, function(DateParser){
  DateParser.parse = function(timestamp) {
    var adapters = [&quot;Date&quot;, &quot;Timestamp&quot;, &quot;ISO8601&quot;, &quot;RFC2822&quot;];
    var parser;

    adapters.some(function(name){
      // Retrieve the adapter and instantiate it with the
      // provided timestamp.
      parser = DateParser[name](timestamp);
      return parser.match();
    });

    // Finally return the parsed timestamp.
    return parser.parse();
  };
}, {});
</code></pre>
<p>É isso aí. Agora estou satisfeito com esta implementação!</p>

<h2>Finalizando</h2>

<p>No nosso exemplo, extrair cada parser e unificar a API desses adapters, automatizando o processo de descoberta de qual o adapter mais indicado para o timestamp passado como argumento tornou o nosso código muito mais simples de entender. Você não precisa, por exemplo, ler toda a função para saber como um determinado parser funciona.</p>

<p>Uma outra coisa que você precisa saber é que toda implementação possui espaço para melhorar. Mais importante que saber como fazer este tipo de melhoria é saber quando parar, pois isso pode ser uma coisa sem fim.</p>
]]>
      </content:encoded>
      <link>http://simplesideias.com.br/um-pouco-mais-sobre-javascript-modular</link>
      <guid>http://simplesideias.com.br/um-pouco-mais-sobre-javascript-modular</guid>
      <pubDate>Mon, 10 Jun 2013 15:27:00 -0300</pubDate>
    </item>
    <item>
      <title>Escrevendo JavaScript modular</title>
      <description>
        <![CDATA[<p>Você começa escrevendo algumas linhas de código, a coisa começa a tomar forma e quando você vai ver, toda a funcionalidade que você implementou está contida em uma única função, monolítica, que você terá dificuldades de entender o que fez em pouco tempo. Quem usa jQuery já passou por isso.</p>

<p>Estou fazendo o fórum do <a href="http://howtocode.com.br/?r=simplesideias">HOWTO</a> e comecei a trabalhar no textarea de resposta. Minha ideia foi seguir a mesma linha do <a href="http://disqus.com">Disqus</a>. Veja o objetivo final abaixo:</p>

<p><img src="http://media.simplesideias.com.br/postbox.gif" alt="Postbox do fórum do HOWTO"></p>

<p>Sempre que preciso implementar esse tipo de coisa, começo pelo jeito mais simples, que é usar o &quot;modo jQuery&quot; de fazer as coisas. Primeiro vamos definir o markup (ou uma versão simplificada dele; na versão real estou usando atributos <code>data</code> para fazer algumas coisas com AJAX).</p>
<pre class="language-markup"><code>&lt;div class=&quot;postbox&quot;&gt;
  &lt;textarea placeholder=&quot;Escreva sua resposta...&quot;&gt;&lt;/textarea&gt;
  &lt;button class=&quot;reply-button&quot;&gt;Enviar esta resposta&lt;/button&gt;
&lt;/div&gt;
</code></pre>
<p>Todas as animações são feitas com CSS3. Note que o CSS abaixo não contém as versões com prefixo, apenas para simplificar (eu uso <a href="http://bourbon.io">Bourbon</a> para isso).</p>
<pre class="language-css"><code>.postbox {
  background: #f3f6f7;
  border: 1px solid #ccc;
  overflow: hidden;
  position: relative;
}

.postbox .reply-button {
  background: #606b73;
  border: none;
  bottom: -1px;
  color: #fff;
  display: none;
  float: right;
  overflow: hidden;
  padding: 10px 15px;
  position: relative;
  right: -1px;
}

.postbox textarea {
  box-sizing: border-box;
  border: none;
  height: 50px;
  outline: none;
  padding: 8px 10px;
  transition: height .2s ease-in;
  width: 100%;
}

.postbox textarea.is-taller {
  height: 300px;
}

.postbox.did-focus textarea {
  height: 150px;
}

.postbox.did-focus .reply-button {
  display: block;
}

.postbox.is-contracted textarea {
  height: 50px;
}
</code></pre>
<p>O <code>textarea</code> possui três alturas distintas. Quando ele não teve foco, sua altura é de <code>50px</code>. Se ele teve foco, sua altura muda para <code>150px</code>. Por fim, quando atingir 5 quebras de linha, ele mudará para <code>300px</code>. Todas essas mudanças são feitas com classes CSS (ou a ausência delas).</p>

<p>Para lidar com o foco do <code>textarea</code>, comecei com a implementação abaixo. Toda vez que um textarea recebe o foco, adicionamos a classe <code>did-focus</code> e removemos a classe <code>is-contracted</code>.</p>
<pre class="language-javascript"><code>$(&quot;.postbox textarea&quot;)
  .on(&quot;focus&quot;, function(){
    $(this).closest(&quot;.postbox&quot;)
      .addClass(&quot;did-focus&quot;)
      .removeClass(&quot;is-contracted&quot;)
    ;
  })
;
</code></pre>
<p>O próximo passo é ouvir o evento <code>keyup</code>, para fazer a contagem de linhas do <code>textarea</code>. Se tiver pelo menos cinco linhas, adicionamos a classe <code>is-taller</code>; caso contrário, removemos esta mesma classe.</p>
<pre class="language-javascript"><code>$(&quot;.postbox textarea&quot;)
  .on(&quot;focus&quot;, function(){
    $(this).closest(&quot;.postbox&quot;)
      .addClass(&quot;did-focus&quot;)
      .removeClass(&quot;is-contracted&quot;)
    ;
  })

  .on(&quot;keyup&quot;, function(){
    var lines = this.value.split(/\r?\n/);
    var textarea = $(this);

    if (lines.length &gt;= 5) {
      textarea.addClass(&quot;is-taller&quot;);
    } else {
      textarea.removeClass(&quot;is-taller&quot;);
    }
  })
;
</code></pre>
<p>Por fim, precisamos ouvir o evento <code>blur</code> para saber se o <code>textarea</code> possui algum conteúdo ou não e adicionar a classe <code>is-contracted</code> ao container <code>.postbox</code> de acordo com essa verificação.</p>
<pre class="language-javascript"><code>$(&quot;.postbox textarea&quot;)
  .on(&quot;focus&quot;, function(){
    $(this).closest(&quot;.postbox&quot;)
      .addClass(&quot;did-focus&quot;)
      .removeClass(&quot;is-contracted&quot;)
    ;
  })

  .on(&quot;keyup&quot;, function(){
    var lines = this.value.split(/\r?\n/);
    var textarea = $(this);

    if (lines.length &gt;= 5) {
      textarea.addClass(&quot;is-taller&quot;);
    } else {
      textarea.removeClass(&quot;is-taller&quot;);
    }
  })

  .on(&quot;blur&quot;, function(){
    if (!this.value) {
      $(this).closest(&quot;.postbox&quot;).addClass(&quot;is-contracted&quot;);
    }
  })
;
</code></pre>
<p>Esta implementação funciona, mas ela não é das melhores. Normalmente eu prefiro escrever códigos mais modulares, que são mais fáceis de <a href="http://pivotal.github.io/jasmine">testar</a>, entender e dar manutenção.</p>

<p>Para começar, vamos definir um módulo deste componente, que irá receber o container <code>.postbox</code> durante sua inicialização. Além disso, iremos extrair os elementos usados pelo componente, fazendo caching e facilitando a referência aos elementos.</p>
<pre class="language-javascript"><code>Module(&quot;HOWTO.Postbox&quot;, function(Postbox){
  Postbox.fn.initialize = function(container) {
    this.container = container;
    this.textarea = container.find(&quot;textarea&quot;);
    this.button = container.find(&quot;.button&quot;);
  };
});
</code></pre>
<p>Eu estou usando uma biblioteca chamada <a href="http://github.com/fnando/module.js">Module.js</a>. Note que o objeto <code>fn</code> é apenas um atalho para <code>prototype</code>.</p>

<p>Vamos adicionar os eventos do <code>textarea</code>. Os bindings são feitos através da função <code>HOWTO.Postbox.fn.addEventListeners</code>.</p>
<pre class="language-javascript"><code>Module(&quot;HOWTO.Postbox&quot;, function(Postbox){
  Postbox.fn.initialize = function(container) {
    this.container = container;
    this.textarea = container.find(&quot;textarea&quot;);
    this.button = container.find(&quot;.button&quot;);

    this.addEventListeners();
  };

  Postbox.fn.addEventListeners = function() {
    this.textarea
      .on(&quot;focus&quot;, this.onTextareaFocus.bind(this))
      .on(&quot;keyup&quot;, this.onTextareaKeyUp.bind(this))
      .on(&quot;blur&quot;, this.onTextareaBlur.bind(this))
    ;
  };
});
</code></pre>
<p>Perceba que estou usando a função <code>Function.prototype.bind</code> para forçar o contexto <code>this</code> para a instância de <code>HOWTO.Postbox</code>. Isso é uma coisa que sempre faço, e que é um dos motivos de confusão do JavaScript.</p>

<p>O modelo de eventos do JavaScript faz com que o contexto <code>this</code> seja sempre o elemento que lançou o evento. No exemplo acima, seria sempre o <code>textarea</code>, mas isso impossibilitaria o acesso à instância de <code>HOWTO.Postbox</code>.</p>

<p>Agora podemos implementar as funções que lidarão com os eventos. Elas permanecem essencialmente como na implementação original. A única diferença é que precisamos acessar o elemento através de <code>event.target</code>, já que o contexto <code>this</code> não é mais o próprio <code>textarea</code>.</p>
<pre class="language-javascript"><code>Module(&quot;HOWTO.Postbox&quot;, function(Postbox){
  Postbox.fn.initialize = function(container) {
    this.container = container;
    this.textarea = container.find(&quot;textarea&quot;);
    this.button = container.find(&quot;.button&quot;);

    this.addEventListeners();
  };

  Postbox.fn.addEventListeners = function() {
    this.textarea
      .on(&quot;focus&quot;, this.onTextareaFocus.bind(this))
      .on(&quot;keyup&quot;, this.onTextareaKeyUp.bind(this))
      .on(&quot;blur&quot;, this.onTextareaBlur.bind(this))
    ;
  };

  Postbox.fn.onTextareaFocus = function(event) {
    this.container
      .addClass(&quot;did-focus&quot;)
      .removeClass(&quot;is-contracted&quot;)
    ;
  };

  Postbox.fn.onTextareaKeyUp = function(event) {
    var lines = event.target.value.split(/\r?\n/);

    if (lines.length &gt;= 5) {
      this.textarea.addClass(&quot;is-taller&quot;);
    } else {
      this.textarea.removeClass(&quot;is-taller&quot;);
    }
  };

  Postbox.fn.onTextareaBlur = function(event) {
    if (!event.target.value) {
      this.container.addClass(&quot;is-contract&quot;);
    }
  };
});
</code></pre>
<p>Para usar o nosso componente, você pode ter algo assim:</p>
<pre class="language-javascript"><code>$(&quot;.postbox&quot;).each(function(){
  HOWTO.Postbox($(this));
});
</code></pre>
<h2>Finalizando</h2>

<p>O código final é ligeiramente maior que a implementação original, mas tem uma vantagem: ele é mais simples de entender e manter. Isso porque as responsabilidades de cada função são bem definidas, em vez de termos um espaguete de código dentro de uma única função.</p>

<p>Lembre-se que em projetos maiores, seu JavaScript não é composto por poucas linhas e, no fim, a legibilidade e facilidade de manutenção são muito mais importantes que todo o resto.</p>
]]>
      </description>
      <content:encoded>
        <![CDATA[<p>Você começa escrevendo algumas linhas de código, a coisa começa a tomar forma e quando você vai ver, toda a funcionalidade que você implementou está contida em uma única função, monolítica, que você terá dificuldades de entender o que fez em pouco tempo. Quem usa jQuery já passou por isso.</p>

<p>Estou fazendo o fórum do <a href="http://howtocode.com.br/?r=simplesideias">HOWTO</a> e comecei a trabalhar no textarea de resposta. Minha ideia foi seguir a mesma linha do <a href="http://disqus.com">Disqus</a>. Veja o objetivo final abaixo:</p>

<p><img src="http://media.simplesideias.com.br/postbox.gif" alt="Postbox do fórum do HOWTO"></p>

<p>Sempre que preciso implementar esse tipo de coisa, começo pelo jeito mais simples, que é usar o &quot;modo jQuery&quot; de fazer as coisas. Primeiro vamos definir o markup (ou uma versão simplificada dele; na versão real estou usando atributos <code>data</code> para fazer algumas coisas com AJAX).</p>
<pre class="language-markup"><code>&lt;div class=&quot;postbox&quot;&gt;
  &lt;textarea placeholder=&quot;Escreva sua resposta...&quot;&gt;&lt;/textarea&gt;
  &lt;button class=&quot;reply-button&quot;&gt;Enviar esta resposta&lt;/button&gt;
&lt;/div&gt;
</code></pre>
<p>Todas as animações são feitas com CSS3. Note que o CSS abaixo não contém as versões com prefixo, apenas para simplificar (eu uso <a href="http://bourbon.io">Bourbon</a> para isso).</p>
<pre class="language-css"><code>.postbox {
  background: #f3f6f7;
  border: 1px solid #ccc;
  overflow: hidden;
  position: relative;
}

.postbox .reply-button {
  background: #606b73;
  border: none;
  bottom: -1px;
  color: #fff;
  display: none;
  float: right;
  overflow: hidden;
  padding: 10px 15px;
  position: relative;
  right: -1px;
}

.postbox textarea {
  box-sizing: border-box;
  border: none;
  height: 50px;
  outline: none;
  padding: 8px 10px;
  transition: height .2s ease-in;
  width: 100%;
}

.postbox textarea.is-taller {
  height: 300px;
}

.postbox.did-focus textarea {
  height: 150px;
}

.postbox.did-focus .reply-button {
  display: block;
}

.postbox.is-contracted textarea {
  height: 50px;
}
</code></pre>
<p>O <code>textarea</code> possui três alturas distintas. Quando ele não teve foco, sua altura é de <code>50px</code>. Se ele teve foco, sua altura muda para <code>150px</code>. Por fim, quando atingir 5 quebras de linha, ele mudará para <code>300px</code>. Todas essas mudanças são feitas com classes CSS (ou a ausência delas).</p>

<p>Para lidar com o foco do <code>textarea</code>, comecei com a implementação abaixo. Toda vez que um textarea recebe o foco, adicionamos a classe <code>did-focus</code> e removemos a classe <code>is-contracted</code>.</p>
<pre class="language-javascript"><code>$(&quot;.postbox textarea&quot;)
  .on(&quot;focus&quot;, function(){
    $(this).closest(&quot;.postbox&quot;)
      .addClass(&quot;did-focus&quot;)
      .removeClass(&quot;is-contracted&quot;)
    ;
  })
;
</code></pre>
<p>O próximo passo é ouvir o evento <code>keyup</code>, para fazer a contagem de linhas do <code>textarea</code>. Se tiver pelo menos cinco linhas, adicionamos a classe <code>is-taller</code>; caso contrário, removemos esta mesma classe.</p>
<pre class="language-javascript"><code>$(&quot;.postbox textarea&quot;)
  .on(&quot;focus&quot;, function(){
    $(this).closest(&quot;.postbox&quot;)
      .addClass(&quot;did-focus&quot;)
      .removeClass(&quot;is-contracted&quot;)
    ;
  })

  .on(&quot;keyup&quot;, function(){
    var lines = this.value.split(/\r?\n/);
    var textarea = $(this);

    if (lines.length &gt;= 5) {
      textarea.addClass(&quot;is-taller&quot;);
    } else {
      textarea.removeClass(&quot;is-taller&quot;);
    }
  })
;
</code></pre>
<p>Por fim, precisamos ouvir o evento <code>blur</code> para saber se o <code>textarea</code> possui algum conteúdo ou não e adicionar a classe <code>is-contracted</code> ao container <code>.postbox</code> de acordo com essa verificação.</p>
<pre class="language-javascript"><code>$(&quot;.postbox textarea&quot;)
  .on(&quot;focus&quot;, function(){
    $(this).closest(&quot;.postbox&quot;)
      .addClass(&quot;did-focus&quot;)
      .removeClass(&quot;is-contracted&quot;)
    ;
  })

  .on(&quot;keyup&quot;, function(){
    var lines = this.value.split(/\r?\n/);
    var textarea = $(this);

    if (lines.length &gt;= 5) {
      textarea.addClass(&quot;is-taller&quot;);
    } else {
      textarea.removeClass(&quot;is-taller&quot;);
    }
  })

  .on(&quot;blur&quot;, function(){
    if (!this.value) {
      $(this).closest(&quot;.postbox&quot;).addClass(&quot;is-contracted&quot;);
    }
  })
;
</code></pre>
<p>Esta implementação funciona, mas ela não é das melhores. Normalmente eu prefiro escrever códigos mais modulares, que são mais fáceis de <a href="http://pivotal.github.io/jasmine">testar</a>, entender e dar manutenção.</p>

<p>Para começar, vamos definir um módulo deste componente, que irá receber o container <code>.postbox</code> durante sua inicialização. Além disso, iremos extrair os elementos usados pelo componente, fazendo caching e facilitando a referência aos elementos.</p>
<pre class="language-javascript"><code>Module(&quot;HOWTO.Postbox&quot;, function(Postbox){
  Postbox.fn.initialize = function(container) {
    this.container = container;
    this.textarea = container.find(&quot;textarea&quot;);
    this.button = container.find(&quot;.button&quot;);
  };
});
</code></pre>
<p>Eu estou usando uma biblioteca chamada <a href="http://github.com/fnando/module.js">Module.js</a>. Note que o objeto <code>fn</code> é apenas um atalho para <code>prototype</code>.</p>

<p>Vamos adicionar os eventos do <code>textarea</code>. Os bindings são feitos através da função <code>HOWTO.Postbox.fn.addEventListeners</code>.</p>
<pre class="language-javascript"><code>Module(&quot;HOWTO.Postbox&quot;, function(Postbox){
  Postbox.fn.initialize = function(container) {
    this.container = container;
    this.textarea = container.find(&quot;textarea&quot;);
    this.button = container.find(&quot;.button&quot;);

    this.addEventListeners();
  };

  Postbox.fn.addEventListeners = function() {
    this.textarea
      .on(&quot;focus&quot;, this.onTextareaFocus.bind(this))
      .on(&quot;keyup&quot;, this.onTextareaKeyUp.bind(this))
      .on(&quot;blur&quot;, this.onTextareaBlur.bind(this))
    ;
  };
});
</code></pre>
<p>Perceba que estou usando a função <code>Function.prototype.bind</code> para forçar o contexto <code>this</code> para a instância de <code>HOWTO.Postbox</code>. Isso é uma coisa que sempre faço, e que é um dos motivos de confusão do JavaScript.</p>

<p>O modelo de eventos do JavaScript faz com que o contexto <code>this</code> seja sempre o elemento que lançou o evento. No exemplo acima, seria sempre o <code>textarea</code>, mas isso impossibilitaria o acesso à instância de <code>HOWTO.Postbox</code>.</p>

<p>Agora podemos implementar as funções que lidarão com os eventos. Elas permanecem essencialmente como na implementação original. A única diferença é que precisamos acessar o elemento através de <code>event.target</code>, já que o contexto <code>this</code> não é mais o próprio <code>textarea</code>.</p>
<pre class="language-javascript"><code>Module(&quot;HOWTO.Postbox&quot;, function(Postbox){
  Postbox.fn.initialize = function(container) {
    this.container = container;
    this.textarea = container.find(&quot;textarea&quot;);
    this.button = container.find(&quot;.button&quot;);

    this.addEventListeners();
  };

  Postbox.fn.addEventListeners = function() {
    this.textarea
      .on(&quot;focus&quot;, this.onTextareaFocus.bind(this))
      .on(&quot;keyup&quot;, this.onTextareaKeyUp.bind(this))
      .on(&quot;blur&quot;, this.onTextareaBlur.bind(this))
    ;
  };

  Postbox.fn.onTextareaFocus = function(event) {
    this.container
      .addClass(&quot;did-focus&quot;)
      .removeClass(&quot;is-contracted&quot;)
    ;
  };

  Postbox.fn.onTextareaKeyUp = function(event) {
    var lines = event.target.value.split(/\r?\n/);

    if (lines.length &gt;= 5) {
      this.textarea.addClass(&quot;is-taller&quot;);
    } else {
      this.textarea.removeClass(&quot;is-taller&quot;);
    }
  };

  Postbox.fn.onTextareaBlur = function(event) {
    if (!event.target.value) {
      this.container.addClass(&quot;is-contract&quot;);
    }
  };
});
</code></pre>
<p>Para usar o nosso componente, você pode ter algo assim:</p>
<pre class="language-javascript"><code>$(&quot;.postbox&quot;).each(function(){
  HOWTO.Postbox($(this));
});
</code></pre>
<h2>Finalizando</h2>

<p>O código final é ligeiramente maior que a implementação original, mas tem uma vantagem: ele é mais simples de entender e manter. Isso porque as responsabilidades de cada função são bem definidas, em vez de termos um espaguete de código dentro de uma única função.</p>

<p>Lembre-se que em projetos maiores, seu JavaScript não é composto por poucas linhas e, no fim, a legibilidade e facilidade de manutenção são muito mais importantes que todo o resto.</p>
]]>
      </content:encoded>
      <link>http://simplesideias.com.br/escrevendo-javascript-modular</link>
      <guid>http://simplesideias.com.br/escrevendo-javascript-modular</guid>
      <pubDate>Wed, 05 Jun 2013 09:10:00 -0300</pubDate>
    </item>
    <item>
      <title>Abstração de mais ou de menos?</title>
      <description>
        <![CDATA[<p>Em um projeto que comecei a trabalhar recentemente tínhamos uma action que cuja responsabilidade era renderizar uma lista de produtos. Algo como este trecho de código:</p>
<pre class="language-ruby"><code>class ProductsController &lt; ApplicationController
  def index
    @products = Product.with_state(:published).limit(34).load
    respond_with @products
  end
end
</code></pre>
<p>Embora seja apenas uma única linha de consulta, fiz um refactoring alterando essa única linha para isso:</p>
<pre class="language-ruby"><code>@products = Vitrine.load(34)
</code></pre>
<p>Essa abstração introduziu uma nova classe chamada <code>Vitrine</code>, que quebrei em diversos métodos menores.</p>
<pre class="language-ruby"><code>class Vitrine
  def self.load(size, finder = Product)
    new(size, finder).load
  end

  def initialize(size, finder)
    @finder = finder
    @size = size
  end

  def published
    @finder.with_state(:published)
  end

  def limit
    @finder.limit(@size)
  end

  def scope
    published.merge(limit)
  end

  def load
    scope.load
  end
end
</code></pre>
<p>OMG! Trocar uma linha com 56 caracteres por um novo arquivo com 26 linhas e 347 caracteres? Faz sentido?</p>

<p>Ao meu ver, faz todo o sentido. Por ter quebrado essa consulta em uma nova classe, tive a flexibilidade de poder escrever testes completamente desacoplados do Rails.</p>
<pre class="language-ruby"><code>require &quot;test_helper_lite&quot;
require &quot;./app/models/vitrine&quot;

class VitrineTest &lt; ActiveSupport::TestCase
  test &quot;delegates to the initializer&quot; do
    finder = stub
    instance = stub

    instance.expects(:load)

    Vitrine
      .expects(:new)
      .with(10, finder)
      .returns(instance)

    Vitrine.load(10, finder)
  end

  test &quot;scope searches by state&quot; do
    finder = stub
    vitrine = Vitrine.new(10, finder)

    finder
      .expects(:with_state)
      .with(:published)

    vitrine.published
  end

  test &quot;limits result&quot; do
    finder = stub
    vitrine = Vitrine.new(10, finder)

    finder
      .expects(:limit)
      .with(10)

    vitrine.limit
  end

  test &quot;merges scope&quot; do
    published = stub
    limit = stub
    finder = stub
    vitrine = Vitrine.new(10, finder)

    vitrine.stubs(limit: limit, published: published)
    published.expects(:merge).with(limit)

    vitrine.scope
  end

  test &quot;loads products&quot; do
    finder = stub
    scope = stub
    vitrine = Vitrine.new(10, finder)

    vitrine.stubs scope: scope
    scope.expects(:load)

    vitrine.load
  end
end
</code></pre>
<p>Perceba que estou apenas validando a interface desta classe, o que exige que eu escreva testes de integração, ou estarei testando apenas stubs.</p>

<p>O ponto é o seguinte: até onde esse tipo de abstração traz benefícios? Fui questionado sobre a vantagem de ter trocado uma única linha por vinte e cinco delas.</p>

<p>Minha alteração foi movida pela segurança que escrever este tipo de testes me traz. É infinitamente mais simples encapsular este comportamento e ter testes isolados, do que deixar em um controller e ter testes por lá.</p>

<p>Justificar a implementação de uma determinada funcionalidade não deve ser motivada <em>apenas</em> pelo teste, mas eu quase sempre não consigo fazer a desassociação. Se é difícil de testar, deve existir uma maneira melhor.</p>

<p>Eu continuo acreditando que ter uma classe desacoplada com testes isolados que validam sua interface, juntamente com testes de integração é a melhor abordagem, mas confesso que bateu uma dúvida.</p>

<p>O que você acha? Esse tipo de abstração faz sentido ou é apenas <a href="http://en.wikipedia.org/wiki/Overengineering">overengineering</a>? O que você faria de diferente?</p>
]]>
      </description>
      <content:encoded>
        <![CDATA[<p>Em um projeto que comecei a trabalhar recentemente tínhamos uma action que cuja responsabilidade era renderizar uma lista de produtos. Algo como este trecho de código:</p>
<pre class="language-ruby"><code>class ProductsController &lt; ApplicationController
  def index
    @products = Product.with_state(:published).limit(34).load
    respond_with @products
  end
end
</code></pre>
<p>Embora seja apenas uma única linha de consulta, fiz um refactoring alterando essa única linha para isso:</p>
<pre class="language-ruby"><code>@products = Vitrine.load(34)
</code></pre>
<p>Essa abstração introduziu uma nova classe chamada <code>Vitrine</code>, que quebrei em diversos métodos menores.</p>
<pre class="language-ruby"><code>class Vitrine
  def self.load(size, finder = Product)
    new(size, finder).load
  end

  def initialize(size, finder)
    @finder = finder
    @size = size
  end

  def published
    @finder.with_state(:published)
  end

  def limit
    @finder.limit(@size)
  end

  def scope
    published.merge(limit)
  end

  def load
    scope.load
  end
end
</code></pre>
<p>OMG! Trocar uma linha com 56 caracteres por um novo arquivo com 26 linhas e 347 caracteres? Faz sentido?</p>

<p>Ao meu ver, faz todo o sentido. Por ter quebrado essa consulta em uma nova classe, tive a flexibilidade de poder escrever testes completamente desacoplados do Rails.</p>
<pre class="language-ruby"><code>require &quot;test_helper_lite&quot;
require &quot;./app/models/vitrine&quot;

class VitrineTest &lt; ActiveSupport::TestCase
  test &quot;delegates to the initializer&quot; do
    finder = stub
    instance = stub

    instance.expects(:load)

    Vitrine
      .expects(:new)
      .with(10, finder)
      .returns(instance)

    Vitrine.load(10, finder)
  end

  test &quot;scope searches by state&quot; do
    finder = stub
    vitrine = Vitrine.new(10, finder)

    finder
      .expects(:with_state)
      .with(:published)

    vitrine.published
  end

  test &quot;limits result&quot; do
    finder = stub
    vitrine = Vitrine.new(10, finder)

    finder
      .expects(:limit)
      .with(10)

    vitrine.limit
  end

  test &quot;merges scope&quot; do
    published = stub
    limit = stub
    finder = stub
    vitrine = Vitrine.new(10, finder)

    vitrine.stubs(limit: limit, published: published)
    published.expects(:merge).with(limit)

    vitrine.scope
  end

  test &quot;loads products&quot; do
    finder = stub
    scope = stub
    vitrine = Vitrine.new(10, finder)

    vitrine.stubs scope: scope
    scope.expects(:load)

    vitrine.load
  end
end
</code></pre>
<p>Perceba que estou apenas validando a interface desta classe, o que exige que eu escreva testes de integração, ou estarei testando apenas stubs.</p>

<p>O ponto é o seguinte: até onde esse tipo de abstração traz benefícios? Fui questionado sobre a vantagem de ter trocado uma única linha por vinte e cinco delas.</p>

<p>Minha alteração foi movida pela segurança que escrever este tipo de testes me traz. É infinitamente mais simples encapsular este comportamento e ter testes isolados, do que deixar em um controller e ter testes por lá.</p>

<p>Justificar a implementação de uma determinada funcionalidade não deve ser motivada <em>apenas</em> pelo teste, mas eu quase sempre não consigo fazer a desassociação. Se é difícil de testar, deve existir uma maneira melhor.</p>

<p>Eu continuo acreditando que ter uma classe desacoplada com testes isolados que validam sua interface, juntamente com testes de integração é a melhor abordagem, mas confesso que bateu uma dúvida.</p>

<p>O que você acha? Esse tipo de abstração faz sentido ou é apenas <a href="http://en.wikipedia.org/wiki/Overengineering">overengineering</a>? O que você faria de diferente?</p>
]]>
      </content:encoded>
      <link>http://simplesideias.com.br/abstracao-de-mais-ou-de-menos</link>
      <guid>http://simplesideias.com.br/abstracao-de-mais-ou-de-menos</guid>
      <pubDate>Tue, 02 Apr 2013 18:49:00 -0300</pubDate>
    </item>
    <item>
      <title>Configurando o NGINX com SPDY</title>
      <description>
        <![CDATA[<p>O Google criou um protocolo de rede chamado <a href="http://www.chromium.org/spdy/spdy-whitepaper">SPDY</a> (leia-se <em>speedy</em>), com o objetivo de reduzir o tempo inicial de carregamento de páginas web.</p>

<p>O SPDY não veio para substituir o protocolo HTTP. Na verdade, ele modifica o modo como as respostas e requisições HTTP são realizadas. Em vez de realizar diversas requisições para carregar os elementos de uma página, o SPDY estabelece uma única conexão e trabalha com <em>multiplexing</em>, ou seja, pacotes de diversas requisições são combinados e enviados por esta única conexão. Com isso, é possível ter até <a href="http://www.chromium.org/spdy/spdy-whitepaper">64% de redução</a> no tempo de carregamento das páginas.</p>

<p>Mas e quanto aos navegadores que suportam o SPDY? O suporte ainda não é completo, mas a lista já é bastante promissora.</p>

<ul>
<li>Firefox 15+</li>
<li>Chrome 11+</li>
<li>Opera</li>
</ul>

<h2>Instalando o NGINX com suporte ao SPDY</h2>

<p>Se você se interessou, saiba que o NGINX possui <a href="http://nginx.org/patches/spdy/README.txt">suporte experimental</a> ao SPDY. Esta funcionalidade foi patrocinada pela <a href="http://automattic.com/">Automattic</a>, empresa por trás do <a href="http://wordpress.com">Wordpress</a>.</p>

<p>Para instalar o NGINX com suporte ao SPDY, você vai precisar compilá-lo à partir do código-fonte.</p>
<pre class="language-text"><code>$ wget http://nginx.org/download/nginx-1.3.13.tar.gz
$ tar xvfz nginx-1.3.13.tar.gz
$ cd nginx-1.3.13
$ wget http://nginx.org/patches/spdy/patch.spdy.txt
$ patch -p1 &lt; patch.spdy.txt
$ ./configure --with-http_ssl_module --with-http_spdy_module
$ make
$ make install
</code></pre>
<p>Se você está usando o Ubuntu 12.04 Precise Pangolin, pode usar o <a href="http://apt.hellobits.com">repositório Debian</a> da <a href="http://hellobits.com">Hellobits</a>, que possui o pacote <code>nginx-plus</code>, com algumas outras extensões como Redis, Websockets e outras.</p>

<p>Primeiro, adicione a chave pública GPG.</p>
<pre class="language-text"><code>$ wget -O - http://apt.hellobits.com/hellobits.key | sudo apt-key add -
</code></pre>
<p>Depois, adicione o repositório.</p>
<pre class="language-text"><code>echo &#39;deb http://apt.hellobits.com/ precise main&#39; | sudo tee /etc/apt/sources.list.d/hellobits.list
</code></pre>
<p>Agora basta atualizar a lista de pacotes e instalar o pacote <code>nginx-plus</code>.</p>
<pre class="language-text"><code>$ sudo apt-get update
$ sudo apt-get install nginx-plus
</code></pre>
<h2>Configurando o NGINX</h2>

<p>Você vai precisar de um certificado SSL para poder usar o SPDY. Se você precisa de certificados SSL, recomendo o site <a href="https://www.cheapssls.com">CheapSSLs</a>. Um certificado de 5 anos da PositiveSSL custa <a href="https://www.cheapssls.com/comodo-ssl-certificates/positivessl.html">apenas $25</a>.</p>

<p>Para configurar o NGINX, basta adicionar poucas linhas ao seu bloco <code>server</code>.
 Veja, por exemplo, as configurações que estou usando no Simples Ideias.</p>
<pre class="language-text"><code>server {
  listen 443 ssl spdy;
  server_name simplesideias.com.br;
  root /var/www/simplesideias/current/public;

  ssl_certificate /etc/nginx/ssl/simplesideias.com.br/ssl.crt;
  ssl_certificate_key /etc/nginx/ssl/simplesideias.com.br/ssl.key;
  ssl_session_cache shared:SSL:10m;
  ssl_session_timeout 10m;
  ssl_prefer_server_ciphers on;
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers RC4:HIGH:!aNULL:!MD5;

  # other config
}
</code></pre>
<p>Verifique se as configurações estão corretas e reinicie o servidor.</p>
<pre class="language-text"><code>$ sudo nginx -t
$ sudo nginx -s reload
</code></pre>
<p>Se você usa o Google Chrome, existe uma <a href="https://chrome.google.com/webstore/detail/spdy-indicator/mpbpobfflnpcgagjijhmgnchggcjblin">extensão</a> que permite verificar se o site que você está visitando possui suporte ao SPDY. O Firefox possui uma <a href="https://addons.mozilla.org/en-us/firefox/addon/spdy-indicator/">extensão semelhante</a>.</p>

<p><img src="http://simplesideias.com.br/media/chrome-spdy.png" alt="Chrome - Extensão que mostra se SPDY está ativo"></p>
]]>
      </description>
      <content:encoded>
        <![CDATA[<p>O Google criou um protocolo de rede chamado <a href="http://www.chromium.org/spdy/spdy-whitepaper">SPDY</a> (leia-se <em>speedy</em>), com o objetivo de reduzir o tempo inicial de carregamento de páginas web.</p>

<p>O SPDY não veio para substituir o protocolo HTTP. Na verdade, ele modifica o modo como as respostas e requisições HTTP são realizadas. Em vez de realizar diversas requisições para carregar os elementos de uma página, o SPDY estabelece uma única conexão e trabalha com <em>multiplexing</em>, ou seja, pacotes de diversas requisições são combinados e enviados por esta única conexão. Com isso, é possível ter até <a href="http://www.chromium.org/spdy/spdy-whitepaper">64% de redução</a> no tempo de carregamento das páginas.</p>

<p>Mas e quanto aos navegadores que suportam o SPDY? O suporte ainda não é completo, mas a lista já é bastante promissora.</p>

<ul>
<li>Firefox 15+</li>
<li>Chrome 11+</li>
<li>Opera</li>
</ul>

<h2>Instalando o NGINX com suporte ao SPDY</h2>

<p>Se você se interessou, saiba que o NGINX possui <a href="http://nginx.org/patches/spdy/README.txt">suporte experimental</a> ao SPDY. Esta funcionalidade foi patrocinada pela <a href="http://automattic.com/">Automattic</a>, empresa por trás do <a href="http://wordpress.com">Wordpress</a>.</p>

<p>Para instalar o NGINX com suporte ao SPDY, você vai precisar compilá-lo à partir do código-fonte.</p>
<pre class="language-text"><code>$ wget http://nginx.org/download/nginx-1.3.13.tar.gz
$ tar xvfz nginx-1.3.13.tar.gz
$ cd nginx-1.3.13
$ wget http://nginx.org/patches/spdy/patch.spdy.txt
$ patch -p1 &lt; patch.spdy.txt
$ ./configure --with-http_ssl_module --with-http_spdy_module
$ make
$ make install
</code></pre>
<p>Se você está usando o Ubuntu 12.04 Precise Pangolin, pode usar o <a href="http://apt.hellobits.com">repositório Debian</a> da <a href="http://hellobits.com">Hellobits</a>, que possui o pacote <code>nginx-plus</code>, com algumas outras extensões como Redis, Websockets e outras.</p>

<p>Primeiro, adicione a chave pública GPG.</p>
<pre class="language-text"><code>$ wget -O - http://apt.hellobits.com/hellobits.key | sudo apt-key add -
</code></pre>
<p>Depois, adicione o repositório.</p>
<pre class="language-text"><code>echo &#39;deb http://apt.hellobits.com/ precise main&#39; | sudo tee /etc/apt/sources.list.d/hellobits.list
</code></pre>
<p>Agora basta atualizar a lista de pacotes e instalar o pacote <code>nginx-plus</code>.</p>
<pre class="language-text"><code>$ sudo apt-get update
$ sudo apt-get install nginx-plus
</code></pre>
<h2>Configurando o NGINX</h2>

<p>Você vai precisar de um certificado SSL para poder usar o SPDY. Se você precisa de certificados SSL, recomendo o site <a href="https://www.cheapssls.com">CheapSSLs</a>. Um certificado de 5 anos da PositiveSSL custa <a href="https://www.cheapssls.com/comodo-ssl-certificates/positivessl.html">apenas $25</a>.</p>

<p>Para configurar o NGINX, basta adicionar poucas linhas ao seu bloco <code>server</code>.
 Veja, por exemplo, as configurações que estou usando no Simples Ideias.</p>
<pre class="language-text"><code>server {
  listen 443 ssl spdy;
  server_name simplesideias.com.br;
  root /var/www/simplesideias/current/public;

  ssl_certificate /etc/nginx/ssl/simplesideias.com.br/ssl.crt;
  ssl_certificate_key /etc/nginx/ssl/simplesideias.com.br/ssl.key;
  ssl_session_cache shared:SSL:10m;
  ssl_session_timeout 10m;
  ssl_prefer_server_ciphers on;
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers RC4:HIGH:!aNULL:!MD5;

  # other config
}
</code></pre>
<p>Verifique se as configurações estão corretas e reinicie o servidor.</p>
<pre class="language-text"><code>$ sudo nginx -t
$ sudo nginx -s reload
</code></pre>
<p>Se você usa o Google Chrome, existe uma <a href="https://chrome.google.com/webstore/detail/spdy-indicator/mpbpobfflnpcgagjijhmgnchggcjblin">extensão</a> que permite verificar se o site que você está visitando possui suporte ao SPDY. O Firefox possui uma <a href="https://addons.mozilla.org/en-us/firefox/addon/spdy-indicator/">extensão semelhante</a>.</p>

<p><img src="http://simplesideias.com.br/media/chrome-spdy.png" alt="Chrome - Extensão que mostra se SPDY está ativo"></p>
]]>
      </content:encoded>
      <link>http://simplesideias.com.br/configurando-o-nginx-com-spdy</link>
      <guid>http://simplesideias.com.br/configurando-o-nginx-com-spdy</guid>
      <pubDate>Sun, 03 Mar 2013 09:46:00 -0300</pubDate>
    </item>
    <item>
      <title>O que mudou no Ruby 2.0</title>
      <description>
        <![CDATA[<p>Chegou a hora de darmos uma olhada nas principais <a href="https://github.com/ruby/ruby/blob/ruby_2_0_0/NEWS">mudanças introduzidas</a> pelo <a href="http://www.ruby-lang.org/en/news/2013/02/24/ruby-2-0-0-p0-is-released/">Ruby 2.0</a>. Se você usa Ruby 1.9, não terá muito o que fazer e a migração será bastante tranquila.</p>

<p>Se você ainda está preso no Ruby 1.8, a história é muito diferente. À partir de <a href="http://www.ruby-lang.org/en/news/2011/10/06/plans-for-1-8-7/">Junho de 2013</a> ele deixará de ter atualizações. <strong>E isso inclui atualizações de segurança.</strong> Por isso, meu conselho é que você comece a fazer a migração o mais rápido possível.</p>

<p>Neste artigo irei mostrar as principais mudanças introduzidas pela nova versão, <a href="http://www.ruby-lang.org/en/news/2013/02/24/ruby-2-0-0-p0-is-released/">lançada no dia 24/02/2013</a>.</p>

<blockquote>
<p><em>Trivia:</em> Você sabia que o lançamento do Ruby 2.0 foi exatamente no dia em que o Ruby completou seu vigésimo aniversário?</p>
</blockquote>

<h2>Argumentos nomeados</h2>

<p>Nós já estamos acostumados a usar hashes quando precisamos passar muitos argumentos para um método. Assim, não temos que nos preocupar com sua ordem e obrigatoriedade.</p>

<p>Agora você pode usar argumentos nomeados, que na assinatura do método se parecem muito com a definição de hashes.</p>

<p>Veja o método abaixo. Ele aceita um único hash com diversas chaves. Se você quiser extrair seus valores em variáveis, é preciso fazer isso manualmente.</p>
<pre class="language-ruby"><code>def link(options = {})
  href = options[:href]
  text = options[:text]

  puts &quot;href: #{href}&quot;
  puts &quot;text: #{text}&quot;
end
</code></pre>
<p>No Ruby 2.0 isso não é mais necessário. Basta definir seus argumentos com o valor de inicialização e a variável será definida automaticamente.</p>
<pre class="language-ruby"><code>def link(href: nil, text: nil)
  puts &quot;href: #{href}&quot;
  puts &quot;text: #{text}&quot;
end
</code></pre>
<p>Se você quiser, pode executar o método com os argumentos em ordem arbitrária.</p>
<pre class="language-ruby"><code>link href: &quot;http://simplesideias.com.br&quot;, text: &quot;SimplesIdeias&quot;
link text: &quot;Hellobits&quot;, href: &quot;http://hellobits.com&quot;
</code></pre>
<p>Mas o que acontece se passarmos argumentos que não foram definidos?</p>
<pre class="language-ruby"><code>link rel: &quot;external&quot;, text: &quot;Codeplane&quot;, href: &quot;http://codeplane.com&quot;
#=&gt; ArgumentError: unknown keyword: rel
</code></pre>
<p>Neste caso, uma exceção <code>ArgumentError</code> será lançada, informando qual argumento não foi definido. Se você quiser, pode pegar uma referência para todos os argumentos que forem passados mas não definidos na assinatura do método. Basta usar o <em>double splat</em>.</p>
<pre class="language-ruby"><code>def link(href: nil, text: nil, **keywords)
  puts &quot;href: #{href}&quot;
  puts &quot;text: #{text}&quot;
end
</code></pre>
<p>Todo e qualquer argumento nomeado que não for definido na assinatura do método será armazenado em um hash, que aqui foi chamado de <code>keywords</code>.</p>

<p>Como fica, então, a assinatura do método se eu tiver parâmetros ordenados misturados com parâmetros nomeados?</p>
<pre class="language-ruby"><code>def catch_all(*args, **keywords)
  p args
  p keywords
end

catch_all &quot;WOW!&quot;, &quot;Ruby 2.0 rules!&quot;, message: &quot;It rules indeed!&quot;
#=&gt; [&quot;WOW!&quot;, &quot;Ruby 2.0 rules!&quot;]
#=&gt; {:message=&gt;&quot;It rules indeed!&quot;}
</code></pre>
<p>Note que não é possível mudar a posição do <em>double splat</em>. Se você quiser mesclar argumentos ordenados e nomeados, passe primeiro os ordenados e depois os nomeados.</p>

<p>Uma outra restrição dos argumentos nomeados é que você não pode ignorar os argumentos não definidos sem passar uma variável. Com argumentos ordenados você pode simplesmente usar o <code>*</code>.</p>
<pre class="language-ruby"><code>def catch_args(*)
end
</code></pre>
<p>No caso de argumentos nomeados, ainda não é possível definir apenas <code>**</code>, mas <a href="http://bugs.ruby-lang.org/issues/7922">isso já foi corrigido</a> e deve entrar no próximo release.</p>
<pre class="language-ruby"><code>def catch_keywords(**)
end

catch_keywords a: 1
#=&gt; ArgumentError: unknown keyword: a
</code></pre>
<p>O método <code>Method#parameters</code> identifica argumentos nomeados com o símbolo <code>:key</code> e <code>:keyrest</code>.</p>
<pre class="language-ruby"><code>def inspect_parameters(a, b = nil, *args, c: nil, **keywords, &amp;block)
end

p method(:inspect_parameters).parameters
#=&gt; [
#     [:req, :a],
#     [:opt, :b],
#     [:rest, :args],
#     [:key, :c],
#     [:keyrest, :keywords],
#     [:block, :block]
#   ]
</code></pre>
<h2>Arrays de símbolos</h2>

<p>O Ruby já possuia muitas construções literais para arrays, strings e expressões regulares, como <code>%w[]</code>, <code>%()</code> e <code>%r[]</code>. O Ruby 2.0 adicionou mais uma construção, que agora permite criar arrays de símbolos.</p>
<pre class="language-ruby"><code>platforms = %i[mac windows linux]
[:mac, :windows, :linux]
#=&gt;
</code></pre>
<p>O literal <code>%i</code> não permite interpolar valores. É aí que entra o <code>%I</code>.</p>
<pre class="language-ruby"><code>%i[#{Time.now}]
#=&gt; [:&quot;\#{Time.now}&quot;]

%I[#{Time.now}]
#=&gt; [:&quot;2013-02-26 19:13:13 -0300&quot;]
</code></pre>
<h2>Encoding</h2>

<p>No Ruby 1.9, o encoding padrão é <code>US-ASCII</code>. Isto significa que se você quiser usar caracteres acentuados, por exemplo, precisa definir o <em>magic comment</em> ou uma exceção será lançada.</p>
<pre class="language-ruby"><code>puts __ENCODING__
#=&gt; US-ASCII

text = &quot;áéíóú&quot;
puts text
#=&gt; invalid multibyte char (US-ASCII)
</code></pre>
<p>Agora, o encoding padrão é <code>UTF-8</code>. Você não precisa mais adicionar o <em>magic comment</em>, há menos que queira manter a compatibilidade com o Ruby 1.9, o que é uma boa ideia. Veja este mesmo código ao ser executado no Ruby 2.0:</p>
<pre class="language-ruby"><code>puts __ENCODING__
#=&gt; UTF-8

text = &quot;áéíóú&quot;
puts text
#=&gt; áéíóú
</code></pre>
<h2>Module#prepend</h2>

<p>Você já deve ter sentido a necessidade de estender o comportamento de um método. Imagine que você tem uma classe chamada <code>MyClass</code>, que possui um único método <code>MyClass#foo</code>. Você precisa estender este método, executando algo antes e depois da implementação original.</p>
<pre class="language-ruby"><code>class MyClass
  def foo
    puts &quot;foo&quot;
  end
end
</code></pre>
<p>Você tem duas alternativas para resolver este problema. A primeira usa os métodos <code>Module.define_method</code> e <code>Module.instance_method</code> e é a mais recomendada, já que não causa efeitos colaterais.</p>
<pre class="language-ruby"><code>class MyClass
  foo_method = instance_method(:foo)

  define_method :foo do
    puts &quot;before foo&quot;
    result = foo_method.bind(self).call
    puts &quot;after foo&quot;
    result
  end
end

MyClass.new.foo
#=&gt; before foo
#=&gt; original
#=&gt; after foo
</code></pre>
<p>A segunda alternativa, muito comum diga-se de passagem, seria renomear o método e executá-lo com este novo nome. O problema acontece se alguém teve a mesma ideia que você e também renomeou o método para <code>MyClass#foo_original</code>.</p>
<pre class="language-ruby"><code>class MyClass
  alias_method :foo_original, :foo

  def foo
    puts &quot;before foo&quot;
    result = foo_original
    puts &quot;after foo&quot;
    result
  end
end

MyClass.new.foo
#=&gt; before foo
#=&gt; original
#=&gt; after foo
</code></pre>
<p>Se você está no Rails, é possível usar o método <a href="http://api.rubyonrails.org/classes/Module.html#method-i-alias_method_chain">Module#alias_method_chain</a>, que segue a mesma ideia do <code>Module#alias_method</code>.</p>
<pre class="language-ruby"><code>require &quot;active_support/all&quot;

class MyClass
  def foo_with_puts
    puts &quot;before foo&quot;
    result = foo_without_puts
    puts &quot;after foo&quot;
    result
  end

  alias_method_chain :foo, :puts
end

MyClass.new.foo
#=&gt; before foo
#=&gt; original
#=&gt; after foo
</code></pre>
<p>Com o método <code>Module#prepend</code> isso se torna muito mais simples. Ele permite alterar a hierarquia de classes e módulos de modo que este módulo seja adicionado antes da própria classe. Assim, podemos trocar todas as soluções anteriores por esta, que usa o <code>super</code>.</p>
<pre class="language-ruby"><code>module FooExtension
  def foo
    puts &quot;before foo&quot;
    result = super
    puts &quot;after foo&quot;
    result
  end
end

class MyClass
  prepend FooExtension
end

MyClass.new.foo
#=&gt; before foo
#=&gt; original
#=&gt; after foo
</code></pre>
<p>Mas como isso funciona? Se você executar o método <code>Module.ancestors</code>, verá que o módulo <code>FooExtension</code> foi adicionado na hierarquia antes mesmo da própria classe <code>MyClass</code>.</p>
<pre class="language-ruby"><code>MyClass.ancestors
#=&gt; [FooExtension, MyClass, Object, Kernel, BasicObject]
</code></pre>
<p>Por isso é possível chamar o <code>super</code>, que por sua vez irá executar o método <code>MyClass#foo</code>.</p>

<h2>Protocolo to_h</h2>

<p>Finalmente temos um protocolo oficial para converter objetos em uma representação em Hash. Trata-se do método <code>to_h</code>, que agora é implementado em várias classes do Core como <code>NilClass</code>, <code>Struct</code> e <code>OpenStruct</code>.</p>

<p>Veja, por exemplo, como fica isso com a classe <a href="http://simplesideias.com.br/openstruct-no-ruby-dois-ponto-zero">OpenStruct</a>:</p>
<pre class="language-ruby"><code>require &quot;ostruct&quot;

user = OpenStruct.new(:name =&gt; &quot;John Doe&quot;, :email =&gt; &quot;john@example.org&quot;)

# Ruby 1.9
user.to_h
#=&gt; nil

# Ruby 2.0
#=&gt; {:name =&gt; &quot;John Doe&quot;, :email =&gt; &quot;john@example.org&quot;}
</code></pre>
<p>Com a classe <code>Struct</code> o comportamento é semelhante.</p>
<pre class="language-ruby"><code>User = Struct.new(:name, :email)
user = User.new(&quot;John Doe&quot;, &quot;john@example.org&quot;)

user.to_h
#=&gt; {:name=&gt;&quot;John Doe&quot;, :email=&gt;&quot;john@example.org&quot;}
</code></pre>
<p>No caso de <code>nil</code>, um Hash vazio é retornado.</p>
<pre class="language-ruby"><code>nil.to_h
#=&gt; {}
</code></pre>
<p>No Ruby 1.9 os métodos <code>NilClass#to_h</code> e <code>Struct#to_h</code> não existem.</p>

<h2>Expressões Regulares</h2>

<p>O Ruby 2.0 mudou seu <em>engine</em> de expressão regular mais uma vez. O Oniguruma saiu para dar lugar ao <a href="https://github.com/k-takata/Onigmo">Onigmo</a>, um fork do Oniguruma com novas funcionalidades.</p>

<p>Uma das novidades introduzidas pelo Onigmo é a possibilidade de se ter condicionais na expressão regular. Também foram adicionadas algumas funcionalidades do Perl 5.10+.</p>

<p>Para saber quais sintaxes são aceitas no Ruby, acesse a <a href="https://github.com/k-takata/Onigmo/blob/master/doc/RE">documentação do Onigmo</a>.</p>

<h2>Refinements</h2>

<p>Uma das grandes preocupações de quem começa a usar Ruby é em relação às classes abertas. A justificativa quase sempre envolve o perigo que existe em modificar classes existentes. Na prática, isso quase nunca acontece, embora vez ou outra você vai dar de frente com um código que faz algo muito bizarro (e que não deveria), mais por culpa do desenvolvedor meia-boca que do Ruby.</p>

<p>Tentando amenizar este problema, o Ruby 2.0 introduziu o Refinements, que é uma maneira de fazermos Monkey Patching de modo mais controlado.</p>

<p>Para mostrar como o Refinements funciona, vamos estender a classe <code>Integer</code> com o método <code>Integer#minutes</code>, que retorna a quantidade de segundos. Você poderia adicionar este método diretamente à classe <code>Integer</code>.</p>
<pre class="language-ruby"><code>class Integer
  def minutes
    self * 60
  end
end

class MyLib
  puts 3.minutes
  #=&gt; 180
end

puts 5.minutes
#=&gt; 300
</code></pre>
<p>É exatamente isso que o <a href="http://rubygems.org/gems/activesupport">ActiveSupport</a> faz, estendendo classes do Core como <code>Time</code>, <code>Date</code>, <code>Hash</code>, <code>Array</code>, dentre outras. O questão é que essas extensões são aplicadas em todo o Ruby.</p>

<p>Para resolver este problema, o Ruby 2.0 adicionou os métodos <code>Module.refine</code> e <code>Module.using</code>. A ideia é adicionar este tipo de extensão de um modo mais controlado. A proposta inicial permitia fazer isso.</p>
<pre class="language-ruby"><code>module TimeExtension
  refine Integer do
    def minutes
      self * minutes
    end
  end
end

class MyLib
  using TimeExtension

  puts 3.minutes
  #=&gt; 180
end

puts 5.minutes
#=&gt;  undefined method `minutes&#39; for 5:Fixnum (NoMethodError)
</code></pre>
<p>Infelizmente a implementação presente no Ruby 2.0 é experimental e reduzida. Este exemplo acima <em>não funciona</em> no Ruby 2.0.0-p0, mas funciona no Ruby 2.0.0-preview1. Em vez disso, você precisa fazer a chamada do método <code>using()</code> no contexto principal. As extensões aplicadas por este serão aplicadas apenas ao arquivo que fez a chamada.</p>
<pre class="language-ruby"><code># file: time_extension.rb
module TimeExtension
  refine Integer do
    def minutes
      self * 60
    end
  end
end

# file: with_refinement.rb
require_relative &quot;time_extension&quot;
using TimeExtension

puts 5.minutes
#=&gt;  300

# file: without_refinement.rb
require_relative &quot;time_extension&quot;

puts 5.minutes
#=&gt; undefined method `minutes&#39; for 10:Fixnum (NoMethodError)
</code></pre>
<p>Existem muitas <a href="https://bugs.ruby-lang.org/issues/4085#note-175">incertezas</a> quanto ao modo como o Refinements deve funcionar. O Charles Nutter escreveu um <a href="http://blog.headius.com/2012/11/refining-ruby.html">ótimo artigo</a> falando sobre a complexidade e problemas que o Refinements introduz.</p>

<h2>Warnings</h2>

<p>o Ruby gerará um warning toda vez que você executar um programa com o flag <code>-w</code> se você declarar uma variável e não usá-la.</p>
<pre class="language-ruby"><code>def parse_name(full_name)
  first, last = full_name.split(&quot; &quot;)
  first
end

parse_name(&quot;John Doe&quot;)
</code></pre>
<p>Ao executarmos esse código:</p>
<pre class="language-text"><code>$ ruby -c -w unused_var.rb
unused_var.rb:2: warning: assigned but unused variable - last
Syntax OK
</code></pre>
<p>No Ruby 2.0, variáveis começadas com <code>_</code> não irão mais gerar estes warnings, mesmo quando não utilizadas.</p>
<pre class="language-ruby"><code>def parse_name(full_name)
  first, _last = full_name.split(&quot; &quot;)
  first
end

parse_name(&quot;John Doe&quot;)
</code></pre>
<p>E ao verificar a sintaxe:</p>
<pre class="language-text"><code>$ ruby -c -w unused_var.rb
Syntax OK
</code></pre>
<h2>Constantes</h2>

<p>Imagine que você tem uma constante <code>A::B</code> e quer pegar uma referência através do seu nome. Se você utilizar o método <code>Object.const_get</code>, verá que uma exceção será lançada.</p>
<pre class="language-ruby"><code>module A
  module B
  end
end

Object.const_get(&quot;A::B&quot;)
#=&gt; NameError: wrong constant name A::B
</code></pre>
<p>Para pegar a constante <code>A::B</code> você tinha iterar cada parte do nome da constante.</p>
<pre class="language-ruby"><code>&quot;A::B&quot;
  .split(&quot;::&quot;)
  .reduce(Object) {|scope, name| scope.const_get(name) }
#=&gt; A::B
</code></pre>
<p>Agora, isso ficou muito mais simples e funciona exatamente do jeito que você espera:</p>
<pre class="language-ruby"><code>Object.const_get(&quot;A::B&quot;)
#=&gt; A::B
</code></pre>
<h2>Enumerator#lazy</h2>

<p>O Ruby 2.0 introduziu um modo de criarmos enumerators que podem ser executados em conjuntos grandes ou mesmo infinitos. Veja o intervalo abaixo, por exemplo.</p>
<pre class="language-ruby"><code>range = (1..Float::INFINITY)
</code></pre>
<p>Imagine que você quer pegar os 10 primeiros números primos maiores que 50. Com o método <code>Enumerator#lazy</code>, o estilo de programação não muda nada.</p>
<pre class="language-ruby"><code>require &quot;prime&quot;

range = (0..Float::INFINITY)

primes = range.lazy
  .reject {|number| number &lt; 50 }
  .select(&amp;:prime?)
  .first(10)

primes
#=&gt; [53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
</code></pre>
<p>Se você tentar executar isso sem o método <code>Enumerator#lazy</code>, prepare-se para usar o <code>Ctrl+C</code>. Isso porque o Ruby tentará criar um objeto contendo o intervalo de 0 a infinito, o que obviamente não irá funcionar.</p>

<p>Já com o método <code>Enumerator#lazy</code>, apenas os elementos solicitados é que serão gerados, o que no nosso caso é bastante rápido de fazer, porque estamos acessando apenas 97 números.</p>

<p>Você não precisa ser tão radical quanto ao tamanho da coleção. Mesmo em uma lista muito menor, é possível ver a diferença. Vamos fazer um benchmark com este mesmo exemplo, mas desta vez usando uma coleção com apenas 1000 números.</p>
<pre class="language-ruby"><code>require &quot;benchmark&quot;
require &quot;prime&quot;

range = (0..1000)
cycles = 1_000

def primes(range)
  range
    .reject {|number| number &lt; 50 }
    .select(&amp;:prime?)
    .first(10)
end

Benchmark.bmbm do |x|
  x.report(&quot;with lazy&quot;) do
    cycles.times{ primes(range.lazy) }
  end

  x.report(&quot;without lazy&quot;) do
    cycles.times{ primes(range) }
  end
end
</code></pre>
<p>O diferença é muito grande!</p>
<pre class="language-text"><code>Rehearsal ------------------------------------------------
with lazy      0.250000   0.000000   0.250000 (  0.243124)
without lazy   4.800000   0.000000   4.800000 (  4.808169)
--------------------------------------- total: 5.050000sec

                   user     system      total        real
with lazy      0.290000   0.000000   0.290000 (  0.290303)
without lazy   4.250000   0.000000   4.250000 (  4.244091)
</code></pre>
<p>Já em coleções menores, usar o <code>Enumerator#lazy</code> pode não ser uma boa ideia. Mudando a quantidade de números gerados para <code>0..100</code>, temos um resultado um pouco diferente.</p>
<pre class="language-text"><code>Rehearsal ------------------------------------------------
with lazy      0.260000   0.000000   0.260000 (  0.260372)
without lazy   0.220000   0.010000   0.230000 (  0.226624)
--------------------------------------- total: 0.490000sec

                   user     system      total        real
with lazy      0.260000   0.000000   0.260000 (  0.262915)
without lazy   0.200000   0.000000   0.200000 (  0.200987)
</code></pre>
<h2>TracePoint</h2>

<p>O Ruby possui o método <code>Kernel#set_trace_func</code>, que permite rastrear diversos eventos durante a execução do código. Ele aceita um bloco, que pode receber até seis argumentos.</p>
<pre class="language-ruby"><code>set_trace_func proc {|event, file, line, method, binding, class_name|
  puts &quot;%8s %s:%-2d %10s %8s&quot; % [event, file, line, method, class_name]
}

class Foo
  def initialize(options = {})
    @options = options
  end
end
</code></pre>
<p>Ao executar este arquivo, teremos uma saída como esta:</p>
<pre class="language-text"><code>$ ruby trace.rb
  c-return trace.rb:1   set_trace_func     Kernel
      line trace.rb:5
    c-call trace.rb:5        inherited      Class
  c-return trace.rb:5        inherited      Class
     class trace.rb:5
      line trace.rb:6
    c-call trace.rb:6     method_added     Module
  c-return trace.rb:6     method_added     Module
       end trace.rb:9
</code></pre>
<p>Você pode ouvir até oito eventos diferentes:</p>

<ul>
<li><code>line</code>: uma nova linha foi executada</li>
<li><code>class</code>: uma nova definição de classe/módulo</li>
<li><code>end</code>: fim da definição de classe/módulo</li>
<li><code>call</code>: um método foi executado por um método Ruby</li>
<li><code>c-call</code>: um método foi retornado por um método C</li>
<li><code>return</code>: um valor foi retornado por um método Ruby</li>
<li><code>c-return</code>: um valor foi retornado por um método C</li>
<li><code>raise</code>: uma exceção foi lançada</li>
</ul>

<p>O Ruby 2.0 introduziu uma nova classe chamada <code>TracePoint</code>, que permite utilizar a mesma funcionalidade do método <code>Kernel#set_trace_func</code> usando uma API orientada a objetos.</p>

<p>Usando a classe <code>TracePoint</code>, o exemplo acima seria definido assim:</p>
<pre class="language-ruby"><code>trace = TracePoint.new do |t|
  puts &quot;%10s %s:%-2d %15s %10s&quot; % [t.event, t.path, t.lineno, t.method_id, t.defined_class]
end
</code></pre>
<p>A saída é um pouco diferente, pois o nome do evento possui <code>_</code> em vez de <code>-</code>.</p>
<pre class="language-text"><code>$ ruby trace.rb
  c_return trace.rb:9           enable TracePoint
      line trace.rb:11
    c_call trace.rb:11       inherited      Class
  c_return trace.rb:11       inherited      Class
     class trace.rb:11
      line trace.rb:12
    c_call trace.rb:12    method_added     Module
  c_return trace.rb:12    method_added     Module
       end trace.rb:15
</code></pre>
<p>Se você quiser, pode ouvir um evento específico. Para isso, basta passar seu nome para o initializer.</p>
<pre class="language-ruby"><code>trace = TracePoint.new(:class, &amp;block)
</code></pre>
<h2>Diretório corrente de um arquivo</h2>

<p>Agora é possível pegar uma referência do diretório atual de um script que está sendo executado com o método <code>Kernel#__dir__</code>.</p>
<pre class="language-ruby"><code>puts __FILE__
#=&gt; ruby20_dir.rb

puts __dir__
#=&gt; /Projects/samples
</code></pre>
<p>O método <code>Kernel#__dir__</code> é equivalente a:</p>
<pre class="language-ruby"><code>File.dirname(File.realpath(__FILE__))
</code></pre>
<p>Note que ele é todo em minúsculas, ao contrário de <code>__FILE__</code>. Isso acontece porque <code>__FILE__</code> é apenas uma expressão, enquanto <code>Kernel#__dir__</code> é um método. Não que isso seja uma justificativa, já que podemos criar um alias para este método, adicionando uma versão toda em maiúsculas.</p>
<pre class="language-ruby"><code>module Kernel
  alias_method :__DIR__, :__dir__
end

puts __dir__
#=&gt; /Projects/samples

puts __DIR__
#=&gt; /Projects/samples
</code></pre>
<h2>DTrace</h2>

<p>O Ruby 2.0 trouxe integração com o <a href="http://en.wikipedia.org/wiki/DTrace">DTrace</a>, uma ferramenta que permite fazer a análise de performance e errors do sistema operacional e programas executados. O probes reconhecidos pelo Ruby estão disponíveis no <a href="https://bugs.ruby-lang.org/projects/ruby/wiki/DTraceProbes">wiki do projeto</a>.</p>

<h2>Outras mudanças</h2>

<ul>
<li>A classe <code>Iconv</code> foi removida. A recomendação é que use o método <code>String#encode</code>. O uso do <code>Iconv</code> já era desaconselhado na versão 1.9.</li>
<li>Os métodos <code>String#chars</code>, <code>String#lines</code>, <code>String#codepoints</code> e <code>String#bytes</code> agora retornam um <code>Array</code>, em vez de <code>Enumerator</code>. Use os métodos <code>String#each_(char|line|byte|codepoints)</code> se você quiser um <code>Enumerator</code>.</li>
<li>A biblioteca <code>net/http</code> agora suporta Server Name Indication (SNI), uma extensão do protocolo SSL que indica o hostname no início do processo de handshake. Assim, é possível usar múltiplos certificados SSL com um único endereço IP.</li>
<li>O método <code>Kernel#require</code> teve algumas otimizações que diminuem o tempo de boot de um app Rails.</li>
<li>A classe <code>CGI</code> agora implementa o HTML5.</li>
</ul>

<h2>Finalizando</h2>

<p>Como você pode perceber, o Ruby 2.0 tem muitas novidades. Eu não listei aqui tudo o que tem novo. Para saber exatamente o que entrou nesta versão, <a href="https://github.com/ruby/ruby/blob/ruby_2_0_0/NEWS">acesse a documentação</a>.</p>

<p>Tenho que dizer que estou muito empolgado com esta versão! Se o Rails 4 der uma forcinha e exigir o Ruby 2.0, seria excelente! E isso não é nada impossível, já que em todos os projetos que testei o Ruby 2.0, nenhum precisou de mudanças para rodar o Rails 3.2.</p>
]]>
      </description>
      <content:encoded>
        <![CDATA[<p>Chegou a hora de darmos uma olhada nas principais <a href="https://github.com/ruby/ruby/blob/ruby_2_0_0/NEWS">mudanças introduzidas</a> pelo <a href="http://www.ruby-lang.org/en/news/2013/02/24/ruby-2-0-0-p0-is-released/">Ruby 2.0</a>. Se você usa Ruby 1.9, não terá muito o que fazer e a migração será bastante tranquila.</p>

<p>Se você ainda está preso no Ruby 1.8, a história é muito diferente. À partir de <a href="http://www.ruby-lang.org/en/news/2011/10/06/plans-for-1-8-7/">Junho de 2013</a> ele deixará de ter atualizações. <strong>E isso inclui atualizações de segurança.</strong> Por isso, meu conselho é que você comece a fazer a migração o mais rápido possível.</p>

<p>Neste artigo irei mostrar as principais mudanças introduzidas pela nova versão, <a href="http://www.ruby-lang.org/en/news/2013/02/24/ruby-2-0-0-p0-is-released/">lançada no dia 24/02/2013</a>.</p>

<blockquote>
<p><em>Trivia:</em> Você sabia que o lançamento do Ruby 2.0 foi exatamente no dia em que o Ruby completou seu vigésimo aniversário?</p>
</blockquote>

<h2>Argumentos nomeados</h2>

<p>Nós já estamos acostumados a usar hashes quando precisamos passar muitos argumentos para um método. Assim, não temos que nos preocupar com sua ordem e obrigatoriedade.</p>

<p>Agora você pode usar argumentos nomeados, que na assinatura do método se parecem muito com a definição de hashes.</p>

<p>Veja o método abaixo. Ele aceita um único hash com diversas chaves. Se você quiser extrair seus valores em variáveis, é preciso fazer isso manualmente.</p>
<pre class="language-ruby"><code>def link(options = {})
  href = options[:href]
  text = options[:text]

  puts &quot;href: #{href}&quot;
  puts &quot;text: #{text}&quot;
end
</code></pre>
<p>No Ruby 2.0 isso não é mais necessário. Basta definir seus argumentos com o valor de inicialização e a variável será definida automaticamente.</p>
<pre class="language-ruby"><code>def link(href: nil, text: nil)
  puts &quot;href: #{href}&quot;
  puts &quot;text: #{text}&quot;
end
</code></pre>
<p>Se você quiser, pode executar o método com os argumentos em ordem arbitrária.</p>
<pre class="language-ruby"><code>link href: &quot;http://simplesideias.com.br&quot;, text: &quot;SimplesIdeias&quot;
link text: &quot;Hellobits&quot;, href: &quot;http://hellobits.com&quot;
</code></pre>
<p>Mas o que acontece se passarmos argumentos que não foram definidos?</p>
<pre class="language-ruby"><code>link rel: &quot;external&quot;, text: &quot;Codeplane&quot;, href: &quot;http://codeplane.com&quot;
#=&gt; ArgumentError: unknown keyword: rel
</code></pre>
<p>Neste caso, uma exceção <code>ArgumentError</code> será lançada, informando qual argumento não foi definido. Se você quiser, pode pegar uma referência para todos os argumentos que forem passados mas não definidos na assinatura do método. Basta usar o <em>double splat</em>.</p>
<pre class="language-ruby"><code>def link(href: nil, text: nil, **keywords)
  puts &quot;href: #{href}&quot;
  puts &quot;text: #{text}&quot;
end
</code></pre>
<p>Todo e qualquer argumento nomeado que não for definido na assinatura do método será armazenado em um hash, que aqui foi chamado de <code>keywords</code>.</p>

<p>Como fica, então, a assinatura do método se eu tiver parâmetros ordenados misturados com parâmetros nomeados?</p>
<pre class="language-ruby"><code>def catch_all(*args, **keywords)
  p args
  p keywords
end

catch_all &quot;WOW!&quot;, &quot;Ruby 2.0 rules!&quot;, message: &quot;It rules indeed!&quot;
#=&gt; [&quot;WOW!&quot;, &quot;Ruby 2.0 rules!&quot;]
#=&gt; {:message=&gt;&quot;It rules indeed!&quot;}
</code></pre>
<p>Note que não é possível mudar a posição do <em>double splat</em>. Se você quiser mesclar argumentos ordenados e nomeados, passe primeiro os ordenados e depois os nomeados.</p>

<p>Uma outra restrição dos argumentos nomeados é que você não pode ignorar os argumentos não definidos sem passar uma variável. Com argumentos ordenados você pode simplesmente usar o <code>*</code>.</p>
<pre class="language-ruby"><code>def catch_args(*)
end
</code></pre>
<p>No caso de argumentos nomeados, ainda não é possível definir apenas <code>**</code>, mas <a href="http://bugs.ruby-lang.org/issues/7922">isso já foi corrigido</a> e deve entrar no próximo release.</p>
<pre class="language-ruby"><code>def catch_keywords(**)
end

catch_keywords a: 1
#=&gt; ArgumentError: unknown keyword: a
</code></pre>
<p>O método <code>Method#parameters</code> identifica argumentos nomeados com o símbolo <code>:key</code> e <code>:keyrest</code>.</p>
<pre class="language-ruby"><code>def inspect_parameters(a, b = nil, *args, c: nil, **keywords, &amp;block)
end

p method(:inspect_parameters).parameters
#=&gt; [
#     [:req, :a],
#     [:opt, :b],
#     [:rest, :args],
#     [:key, :c],
#     [:keyrest, :keywords],
#     [:block, :block]
#   ]
</code></pre>
<h2>Arrays de símbolos</h2>

<p>O Ruby já possuia muitas construções literais para arrays, strings e expressões regulares, como <code>%w[]</code>, <code>%()</code> e <code>%r[]</code>. O Ruby 2.0 adicionou mais uma construção, que agora permite criar arrays de símbolos.</p>
<pre class="language-ruby"><code>platforms = %i[mac windows linux]
[:mac, :windows, :linux]
#=&gt;
</code></pre>
<p>O literal <code>%i</code> não permite interpolar valores. É aí que entra o <code>%I</code>.</p>
<pre class="language-ruby"><code>%i[#{Time.now}]
#=&gt; [:&quot;\#{Time.now}&quot;]

%I[#{Time.now}]
#=&gt; [:&quot;2013-02-26 19:13:13 -0300&quot;]
</code></pre>
<h2>Encoding</h2>

<p>No Ruby 1.9, o encoding padrão é <code>US-ASCII</code>. Isto significa que se você quiser usar caracteres acentuados, por exemplo, precisa definir o <em>magic comment</em> ou uma exceção será lançada.</p>
<pre class="language-ruby"><code>puts __ENCODING__
#=&gt; US-ASCII

text = &quot;áéíóú&quot;
puts text
#=&gt; invalid multibyte char (US-ASCII)
</code></pre>
<p>Agora, o encoding padrão é <code>UTF-8</code>. Você não precisa mais adicionar o <em>magic comment</em>, há menos que queira manter a compatibilidade com o Ruby 1.9, o que é uma boa ideia. Veja este mesmo código ao ser executado no Ruby 2.0:</p>
<pre class="language-ruby"><code>puts __ENCODING__
#=&gt; UTF-8

text = &quot;áéíóú&quot;
puts text
#=&gt; áéíóú
</code></pre>
<h2>Module#prepend</h2>

<p>Você já deve ter sentido a necessidade de estender o comportamento de um método. Imagine que você tem uma classe chamada <code>MyClass</code>, que possui um único método <code>MyClass#foo</code>. Você precisa estender este método, executando algo antes e depois da implementação original.</p>
<pre class="language-ruby"><code>class MyClass
  def foo
    puts &quot;foo&quot;
  end
end
</code></pre>
<p>Você tem duas alternativas para resolver este problema. A primeira usa os métodos <code>Module.define_method</code> e <code>Module.instance_method</code> e é a mais recomendada, já que não causa efeitos colaterais.</p>
<pre class="language-ruby"><code>class MyClass
  foo_method = instance_method(:foo)

  define_method :foo do
    puts &quot;before foo&quot;
    result = foo_method.bind(self).call
    puts &quot;after foo&quot;
    result
  end
end

MyClass.new.foo
#=&gt; before foo
#=&gt; original
#=&gt; after foo
</code></pre>
<p>A segunda alternativa, muito comum diga-se de passagem, seria renomear o método e executá-lo com este novo nome. O problema acontece se alguém teve a mesma ideia que você e também renomeou o método para <code>MyClass#foo_original</code>.</p>
<pre class="language-ruby"><code>class MyClass
  alias_method :foo_original, :foo

  def foo
    puts &quot;before foo&quot;
    result = foo_original
    puts &quot;after foo&quot;
    result
  end
end

MyClass.new.foo
#=&gt; before foo
#=&gt; original
#=&gt; after foo
</code></pre>
<p>Se você está no Rails, é possível usar o método <a href="http://api.rubyonrails.org/classes/Module.html#method-i-alias_method_chain">Module#alias_method_chain</a>, que segue a mesma ideia do <code>Module#alias_method</code>.</p>
<pre class="language-ruby"><code>require &quot;active_support/all&quot;

class MyClass
  def foo_with_puts
    puts &quot;before foo&quot;
    result = foo_without_puts
    puts &quot;after foo&quot;
    result
  end

  alias_method_chain :foo, :puts
end

MyClass.new.foo
#=&gt; before foo
#=&gt; original
#=&gt; after foo
</code></pre>
<p>Com o método <code>Module#prepend</code> isso se torna muito mais simples. Ele permite alterar a hierarquia de classes e módulos de modo que este módulo seja adicionado antes da própria classe. Assim, podemos trocar todas as soluções anteriores por esta, que usa o <code>super</code>.</p>
<pre class="language-ruby"><code>module FooExtension
  def foo
    puts &quot;before foo&quot;
    result = super
    puts &quot;after foo&quot;
    result
  end
end

class MyClass
  prepend FooExtension
end

MyClass.new.foo
#=&gt; before foo
#=&gt; original
#=&gt; after foo
</code></pre>
<p>Mas como isso funciona? Se você executar o método <code>Module.ancestors</code>, verá que o módulo <code>FooExtension</code> foi adicionado na hierarquia antes mesmo da própria classe <code>MyClass</code>.</p>
<pre class="language-ruby"><code>MyClass.ancestors
#=&gt; [FooExtension, MyClass, Object, Kernel, BasicObject]
</code></pre>
<p>Por isso é possível chamar o <code>super</code>, que por sua vez irá executar o método <code>MyClass#foo</code>.</p>

<h2>Protocolo to_h</h2>

<p>Finalmente temos um protocolo oficial para converter objetos em uma representação em Hash. Trata-se do método <code>to_h</code>, que agora é implementado em várias classes do Core como <code>NilClass</code>, <code>Struct</code> e <code>OpenStruct</code>.</p>

<p>Veja, por exemplo, como fica isso com a classe <a href="http://simplesideias.com.br/openstruct-no-ruby-dois-ponto-zero">OpenStruct</a>:</p>
<pre class="language-ruby"><code>require &quot;ostruct&quot;

user = OpenStruct.new(:name =&gt; &quot;John Doe&quot;, :email =&gt; &quot;john@example.org&quot;)

# Ruby 1.9
user.to_h
#=&gt; nil

# Ruby 2.0
#=&gt; {:name =&gt; &quot;John Doe&quot;, :email =&gt; &quot;john@example.org&quot;}
</code></pre>
<p>Com a classe <code>Struct</code> o comportamento é semelhante.</p>
<pre class="language-ruby"><code>User = Struct.new(:name, :email)
user = User.new(&quot;John Doe&quot;, &quot;john@example.org&quot;)

user.to_h
#=&gt; {:name=&gt;&quot;John Doe&quot;, :email=&gt;&quot;john@example.org&quot;}
</code></pre>
<p>No caso de <code>nil</code>, um Hash vazio é retornado.</p>
<pre class="language-ruby"><code>nil.to_h
#=&gt; {}
</code></pre>
<p>No Ruby 1.9 os métodos <code>NilClass#to_h</code> e <code>Struct#to_h</code> não existem.</p>

<h2>Expressões Regulares</h2>

<p>O Ruby 2.0 mudou seu <em>engine</em> de expressão regular mais uma vez. O Oniguruma saiu para dar lugar ao <a href="https://github.com/k-takata/Onigmo">Onigmo</a>, um fork do Oniguruma com novas funcionalidades.</p>

<p>Uma das novidades introduzidas pelo Onigmo é a possibilidade de se ter condicionais na expressão regular. Também foram adicionadas algumas funcionalidades do Perl 5.10+.</p>

<p>Para saber quais sintaxes são aceitas no Ruby, acesse a <a href="https://github.com/k-takata/Onigmo/blob/master/doc/RE">documentação do Onigmo</a>.</p>

<h2>Refinements</h2>

<p>Uma das grandes preocupações de quem começa a usar Ruby é em relação às classes abertas. A justificativa quase sempre envolve o perigo que existe em modificar classes existentes. Na prática, isso quase nunca acontece, embora vez ou outra você vai dar de frente com um código que faz algo muito bizarro (e que não deveria), mais por culpa do desenvolvedor meia-boca que do Ruby.</p>

<p>Tentando amenizar este problema, o Ruby 2.0 introduziu o Refinements, que é uma maneira de fazermos Monkey Patching de modo mais controlado.</p>

<p>Para mostrar como o Refinements funciona, vamos estender a classe <code>Integer</code> com o método <code>Integer#minutes</code>, que retorna a quantidade de segundos. Você poderia adicionar este método diretamente à classe <code>Integer</code>.</p>
<pre class="language-ruby"><code>class Integer
  def minutes
    self * 60
  end
end

class MyLib
  puts 3.minutes
  #=&gt; 180
end

puts 5.minutes
#=&gt; 300
</code></pre>
<p>É exatamente isso que o <a href="http://rubygems.org/gems/activesupport">ActiveSupport</a> faz, estendendo classes do Core como <code>Time</code>, <code>Date</code>, <code>Hash</code>, <code>Array</code>, dentre outras. O questão é que essas extensões são aplicadas em todo o Ruby.</p>

<p>Para resolver este problema, o Ruby 2.0 adicionou os métodos <code>Module.refine</code> e <code>Module.using</code>. A ideia é adicionar este tipo de extensão de um modo mais controlado. A proposta inicial permitia fazer isso.</p>
<pre class="language-ruby"><code>module TimeExtension
  refine Integer do
    def minutes
      self * minutes
    end
  end
end

class MyLib
  using TimeExtension

  puts 3.minutes
  #=&gt; 180
end

puts 5.minutes
#=&gt;  undefined method `minutes&#39; for 5:Fixnum (NoMethodError)
</code></pre>
<p>Infelizmente a implementação presente no Ruby 2.0 é experimental e reduzida. Este exemplo acima <em>não funciona</em> no Ruby 2.0.0-p0, mas funciona no Ruby 2.0.0-preview1. Em vez disso, você precisa fazer a chamada do método <code>using()</code> no contexto principal. As extensões aplicadas por este serão aplicadas apenas ao arquivo que fez a chamada.</p>
<pre class="language-ruby"><code># file: time_extension.rb
module TimeExtension
  refine Integer do
    def minutes
      self * 60
    end
  end
end

# file: with_refinement.rb
require_relative &quot;time_extension&quot;
using TimeExtension

puts 5.minutes
#=&gt;  300

# file: without_refinement.rb
require_relative &quot;time_extension&quot;

puts 5.minutes
#=&gt; undefined method `minutes&#39; for 10:Fixnum (NoMethodError)
</code></pre>
<p>Existem muitas <a href="https://bugs.ruby-lang.org/issues/4085#note-175">incertezas</a> quanto ao modo como o Refinements deve funcionar. O Charles Nutter escreveu um <a href="http://blog.headius.com/2012/11/refining-ruby.html">ótimo artigo</a> falando sobre a complexidade e problemas que o Refinements introduz.</p>

<h2>Warnings</h2>

<p>o Ruby gerará um warning toda vez que você executar um programa com o flag <code>-w</code> se você declarar uma variável e não usá-la.</p>
<pre class="language-ruby"><code>def parse_name(full_name)
  first, last = full_name.split(&quot; &quot;)
  first
end

parse_name(&quot;John Doe&quot;)
</code></pre>
<p>Ao executarmos esse código:</p>
<pre class="language-text"><code>$ ruby -c -w unused_var.rb
unused_var.rb:2: warning: assigned but unused variable - last
Syntax OK
</code></pre>
<p>No Ruby 2.0, variáveis começadas com <code>_</code> não irão mais gerar estes warnings, mesmo quando não utilizadas.</p>
<pre class="language-ruby"><code>def parse_name(full_name)
  first, _last = full_name.split(&quot; &quot;)
  first
end

parse_name(&quot;John Doe&quot;)
</code></pre>
<p>E ao verificar a sintaxe:</p>
<pre class="language-text"><code>$ ruby -c -w unused_var.rb
Syntax OK
</code></pre>
<h2>Constantes</h2>

<p>Imagine que você tem uma constante <code>A::B</code> e quer pegar uma referência através do seu nome. Se você utilizar o método <code>Object.const_get</code>, verá que uma exceção será lançada.</p>
<pre class="language-ruby"><code>module A
  module B
  end
end

Object.const_get(&quot;A::B&quot;)
#=&gt; NameError: wrong constant name A::B
</code></pre>
<p>Para pegar a constante <code>A::B</code> você tinha iterar cada parte do nome da constante.</p>
<pre class="language-ruby"><code>&quot;A::B&quot;
  .split(&quot;::&quot;)
  .reduce(Object) {|scope, name| scope.const_get(name) }
#=&gt; A::B
</code></pre>
<p>Agora, isso ficou muito mais simples e funciona exatamente do jeito que você espera:</p>
<pre class="language-ruby"><code>Object.const_get(&quot;A::B&quot;)
#=&gt; A::B
</code></pre>
<h2>Enumerator#lazy</h2>

<p>O Ruby 2.0 introduziu um modo de criarmos enumerators que podem ser executados em conjuntos grandes ou mesmo infinitos. Veja o intervalo abaixo, por exemplo.</p>
<pre class="language-ruby"><code>range = (1..Float::INFINITY)
</code></pre>
<p>Imagine que você quer pegar os 10 primeiros números primos maiores que 50. Com o método <code>Enumerator#lazy</code>, o estilo de programação não muda nada.</p>
<pre class="language-ruby"><code>require &quot;prime&quot;

range = (0..Float::INFINITY)

primes = range.lazy
  .reject {|number| number &lt; 50 }
  .select(&amp;:prime?)
  .first(10)

primes
#=&gt; [53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
</code></pre>
<p>Se você tentar executar isso sem o método <code>Enumerator#lazy</code>, prepare-se para usar o <code>Ctrl+C</code>. Isso porque o Ruby tentará criar um objeto contendo o intervalo de 0 a infinito, o que obviamente não irá funcionar.</p>

<p>Já com o método <code>Enumerator#lazy</code>, apenas os elementos solicitados é que serão gerados, o que no nosso caso é bastante rápido de fazer, porque estamos acessando apenas 97 números.</p>

<p>Você não precisa ser tão radical quanto ao tamanho da coleção. Mesmo em uma lista muito menor, é possível ver a diferença. Vamos fazer um benchmark com este mesmo exemplo, mas desta vez usando uma coleção com apenas 1000 números.</p>
<pre class="language-ruby"><code>require &quot;benchmark&quot;
require &quot;prime&quot;

range = (0..1000)
cycles = 1_000

def primes(range)
  range
    .reject {|number| number &lt; 50 }
    .select(&amp;:prime?)
    .first(10)
end

Benchmark.bmbm do |x|
  x.report(&quot;with lazy&quot;) do
    cycles.times{ primes(range.lazy) }
  end

  x.report(&quot;without lazy&quot;) do
    cycles.times{ primes(range) }
  end
end
</code></pre>
<p>O diferença é muito grande!</p>
<pre class="language-text"><code>Rehearsal ------------------------------------------------
with lazy      0.250000   0.000000   0.250000 (  0.243124)
without lazy   4.800000   0.000000   4.800000 (  4.808169)
--------------------------------------- total: 5.050000sec

                   user     system      total        real
with lazy      0.290000   0.000000   0.290000 (  0.290303)
without lazy   4.250000   0.000000   4.250000 (  4.244091)
</code></pre>
<p>Já em coleções menores, usar o <code>Enumerator#lazy</code> pode não ser uma boa ideia. Mudando a quantidade de números gerados para <code>0..100</code>, temos um resultado um pouco diferente.</p>
<pre class="language-text"><code>Rehearsal ------------------------------------------------
with lazy      0.260000   0.000000   0.260000 (  0.260372)
without lazy   0.220000   0.010000   0.230000 (  0.226624)
--------------------------------------- total: 0.490000sec

                   user     system      total        real
with lazy      0.260000   0.000000   0.260000 (  0.262915)
without lazy   0.200000   0.000000   0.200000 (  0.200987)
</code></pre>
<h2>TracePoint</h2>

<p>O Ruby possui o método <code>Kernel#set_trace_func</code>, que permite rastrear diversos eventos durante a execução do código. Ele aceita um bloco, que pode receber até seis argumentos.</p>
<pre class="language-ruby"><code>set_trace_func proc {|event, file, line, method, binding, class_name|
  puts &quot;%8s %s:%-2d %10s %8s&quot; % [event, file, line, method, class_name]
}

class Foo
  def initialize(options = {})
    @options = options
  end
end
</code></pre>
<p>Ao executar este arquivo, teremos uma saída como esta:</p>
<pre class="language-text"><code>$ ruby trace.rb
  c-return trace.rb:1   set_trace_func     Kernel
      line trace.rb:5
    c-call trace.rb:5        inherited      Class
  c-return trace.rb:5        inherited      Class
     class trace.rb:5
      line trace.rb:6
    c-call trace.rb:6     method_added     Module
  c-return trace.rb:6     method_added     Module
       end trace.rb:9
</code></pre>
<p>Você pode ouvir até oito eventos diferentes:</p>

<ul>
<li><code>line</code>: uma nova linha foi executada</li>
<li><code>class</code>: uma nova definição de classe/módulo</li>
<li><code>end</code>: fim da definição de classe/módulo</li>
<li><code>call</code>: um método foi executado por um método Ruby</li>
<li><code>c-call</code>: um método foi retornado por um método C</li>
<li><code>return</code>: um valor foi retornado por um método Ruby</li>
<li><code>c-return</code>: um valor foi retornado por um método C</li>
<li><code>raise</code>: uma exceção foi lançada</li>
</ul>

<p>O Ruby 2.0 introduziu uma nova classe chamada <code>TracePoint</code>, que permite utilizar a mesma funcionalidade do método <code>Kernel#set_trace_func</code> usando uma API orientada a objetos.</p>

<p>Usando a classe <code>TracePoint</code>, o exemplo acima seria definido assim:</p>
<pre class="language-ruby"><code>trace = TracePoint.new do |t|
  puts &quot;%10s %s:%-2d %15s %10s&quot; % [t.event, t.path, t.lineno, t.method_id, t.defined_class]
end
</code></pre>
<p>A saída é um pouco diferente, pois o nome do evento possui <code>_</code> em vez de <code>-</code>.</p>
<pre class="language-text"><code>$ ruby trace.rb
  c_return trace.rb:9           enable TracePoint
      line trace.rb:11
    c_call trace.rb:11       inherited      Class
  c_return trace.rb:11       inherited      Class
     class trace.rb:11
      line trace.rb:12
    c_call trace.rb:12    method_added     Module
  c_return trace.rb:12    method_added     Module
       end trace.rb:15
</code></pre>
<p>Se você quiser, pode ouvir um evento específico. Para isso, basta passar seu nome para o initializer.</p>
<pre class="language-ruby"><code>trace = TracePoint.new(:class, &amp;block)
</code></pre>
<h2>Diretório corrente de um arquivo</h2>

<p>Agora é possível pegar uma referência do diretório atual de um script que está sendo executado com o método <code>Kernel#__dir__</code>.</p>
<pre class="language-ruby"><code>puts __FILE__
#=&gt; ruby20_dir.rb

puts __dir__
#=&gt; /Projects/samples
</code></pre>
<p>O método <code>Kernel#__dir__</code> é equivalente a:</p>
<pre class="language-ruby"><code>File.dirname(File.realpath(__FILE__))
</code></pre>
<p>Note que ele é todo em minúsculas, ao contrário de <code>__FILE__</code>. Isso acontece porque <code>__FILE__</code> é apenas uma expressão, enquanto <code>Kernel#__dir__</code> é um método. Não que isso seja uma justificativa, já que podemos criar um alias para este método, adicionando uma versão toda em maiúsculas.</p>
<pre class="language-ruby"><code>module Kernel
  alias_method :__DIR__, :__dir__
end

puts __dir__
#=&gt; /Projects/samples

puts __DIR__
#=&gt; /Projects/samples
</code></pre>
<h2>DTrace</h2>

<p>O Ruby 2.0 trouxe integração com o <a href="http://en.wikipedia.org/wiki/DTrace">DTrace</a>, uma ferramenta que permite fazer a análise de performance e errors do sistema operacional e programas executados. O probes reconhecidos pelo Ruby estão disponíveis no <a href="https://bugs.ruby-lang.org/projects/ruby/wiki/DTraceProbes">wiki do projeto</a>.</p>

<h2>Outras mudanças</h2>

<ul>
<li>A classe <code>Iconv</code> foi removida. A recomendação é que use o método <code>String#encode</code>. O uso do <code>Iconv</code> já era desaconselhado na versão 1.9.</li>
<li>Os métodos <code>String#chars</code>, <code>String#lines</code>, <code>String#codepoints</code> e <code>String#bytes</code> agora retornam um <code>Array</code>, em vez de <code>Enumerator</code>. Use os métodos <code>String#each_(char|line|byte|codepoints)</code> se você quiser um <code>Enumerator</code>.</li>
<li>A biblioteca <code>net/http</code> agora suporta Server Name Indication (SNI), uma extensão do protocolo SSL que indica o hostname no início do processo de handshake. Assim, é possível usar múltiplos certificados SSL com um único endereço IP.</li>
<li>O método <code>Kernel#require</code> teve algumas otimizações que diminuem o tempo de boot de um app Rails.</li>
<li>A classe <code>CGI</code> agora implementa o HTML5.</li>
</ul>

<h2>Finalizando</h2>

<p>Como você pode perceber, o Ruby 2.0 tem muitas novidades. Eu não listei aqui tudo o que tem novo. Para saber exatamente o que entrou nesta versão, <a href="https://github.com/ruby/ruby/blob/ruby_2_0_0/NEWS">acesse a documentação</a>.</p>

<p>Tenho que dizer que estou muito empolgado com esta versão! Se o Rails 4 der uma forcinha e exigir o Ruby 2.0, seria excelente! E isso não é nada impossível, já que em todos os projetos que testei o Ruby 2.0, nenhum precisou de mudanças para rodar o Rails 3.2.</p>
]]>
      </content:encoded>
      <link>http://simplesideias.com.br/o-que-mudou-no-ruby-dois-ponto-zero</link>
      <guid>http://simplesideias.com.br/o-que-mudou-no-ruby-dois-ponto-zero</guid>
      <pubDate>Thu, 28 Feb 2013 17:51:00 -0300</pubDate>
    </item>
    <item>
      <title>Instalando o Ruby 2.0 no Ubuntu</title>
      <description>
        <![CDATA[<p>É oficial! O Ruby 2.0 foi <a href="http://www.ruby-lang.org/en/news/2013/02/24/ruby-2-0-0-p0-is-released/">lançando ontem</a> e você já pode usá-lo sem medo. A boa notícia é que já criei os pacotes do Ruby 2.0 para Ubuntu 12.04 Precise Pangolin. Para instalá-lo, você precisa adicionar o <a href="http://apt.hellobits.com">repositório da Hellobits</a> ao seu Ubuntu.</p>

<p>O Ruby 2.0 trás uma série de novidades como argumentos nomeados em métodos, array literal para criação de símbolos, UTF-8 como encoding padrão, e muito mais. Se você já estava rodando seus projetos no Ruby 1.9 não precisará mexer quase nada. Algumas gems podem não estar funcionando, mas a tendência é que tenhamos uma série de atualizações nas próximas semanas. Vale notar que nenhum dos projetos que testei teve falhas desse tipo.</p>

<p>Veja à seguir como instalar o Ruby 2.0 em seu Ubuntu.</p>

<h2>Removendo o ruby-stable/ruby-ichi</h2>

<p>Se você já tinha instalado o Ruby 1.9 seguindo este <a href="http://simplesideias.com.br/instalando-o-ruby-no-ubuntu-precise">outro tutorial</a>, você precisará remover o Ruby.</p>
<pre class="language-text"><code>$ sudo apt-get remove ruby-stable
</code></pre>
<p>ou</p>
<pre class="language-text"><code>$ sudo apt-get remove ruby-ichi
</code></pre>
<h2>Instalando o ruby-ni</h2>

<p>Primeiro você precisará adicionar a chave pública GPG. Para isso, execute o comando abaixo em seu terminal. <em>Se você já tinha instalado o pacote ruby-stable/ruby-ichi, pule esta etapa</em>.</p>
<pre class="language-text"><code>$ wget -O - http://apt.hellobits.com/hellobits.key | sudo apt-key add -
</code></pre>
<p>Agora, adicione o o repositório. Basta criar o arquivo <code>/etc/apt/sources.list.d/hellobits.list</code>. Você pode fazer executando o comando abaixo.</p>
<pre class="language-text"><code>$ echo &#39;deb http://apt.hellobits.com/ precise main&#39; | sudo tee /etc/apt/sources.list.d/hellobits.list
</code></pre>
<p>Finalmente, basta instalar o pacote Ruby.</p>
<pre class="language-text"><code>$ sudo apt-get update
$ sudo apt-get install ruby-ni
</code></pre>
<p>Se tudo deu certo, o Ruby já deve estar disponível em seu sistema.</p>
<pre class="language-text"><code>$ ruby -v
ruby 2.0.0p0 (2013-02-24 revision 39474) [x86_64-linux]
</code></pre>
<p>É importante que você apague todas as gems instaladas na versão anterior. Caso, contrário você terá alguns erros por causa da compilação.</p>
<pre class="language-text"><code>$ rm -rf $(gem env gemdir)
</code></pre>
<h2>Finalizando</h2>

<p>Testei alguns projetos no Ruby 2.0 e até agora nenhum deles teve problemas. Ainda não coloquei em produção, mas devo fazer isso em breve (vou esperar um pouco para ver se nenhum novo release é lançado).</p>

<p>Se você precisa de pacotes para o Ubuntu 10.04 Lucid Lynx, deixe seu pedido nos comentários. Inicialmente não é minha ideia manter este pacote para o Ubuntu 10.04, mas se muita gente pedir, posso mudar de ideia!</p>
]]>
      </description>
      <content:encoded>
        <![CDATA[<p>É oficial! O Ruby 2.0 foi <a href="http://www.ruby-lang.org/en/news/2013/02/24/ruby-2-0-0-p0-is-released/">lançando ontem</a> e você já pode usá-lo sem medo. A boa notícia é que já criei os pacotes do Ruby 2.0 para Ubuntu 12.04 Precise Pangolin. Para instalá-lo, você precisa adicionar o <a href="http://apt.hellobits.com">repositório da Hellobits</a> ao seu Ubuntu.</p>

<p>O Ruby 2.0 trás uma série de novidades como argumentos nomeados em métodos, array literal para criação de símbolos, UTF-8 como encoding padrão, e muito mais. Se você já estava rodando seus projetos no Ruby 1.9 não precisará mexer quase nada. Algumas gems podem não estar funcionando, mas a tendência é que tenhamos uma série de atualizações nas próximas semanas. Vale notar que nenhum dos projetos que testei teve falhas desse tipo.</p>

<p>Veja à seguir como instalar o Ruby 2.0 em seu Ubuntu.</p>

<h2>Removendo o ruby-stable/ruby-ichi</h2>

<p>Se você já tinha instalado o Ruby 1.9 seguindo este <a href="http://simplesideias.com.br/instalando-o-ruby-no-ubuntu-precise">outro tutorial</a>, você precisará remover o Ruby.</p>
<pre class="language-text"><code>$ sudo apt-get remove ruby-stable
</code></pre>
<p>ou</p>
<pre class="language-text"><code>$ sudo apt-get remove ruby-ichi
</code></pre>
<h2>Instalando o ruby-ni</h2>

<p>Primeiro você precisará adicionar a chave pública GPG. Para isso, execute o comando abaixo em seu terminal. <em>Se você já tinha instalado o pacote ruby-stable/ruby-ichi, pule esta etapa</em>.</p>
<pre class="language-text"><code>$ wget -O - http://apt.hellobits.com/hellobits.key | sudo apt-key add -
</code></pre>
<p>Agora, adicione o o repositório. Basta criar o arquivo <code>/etc/apt/sources.list.d/hellobits.list</code>. Você pode fazer executando o comando abaixo.</p>
<pre class="language-text"><code>$ echo &#39;deb http://apt.hellobits.com/ precise main&#39; | sudo tee /etc/apt/sources.list.d/hellobits.list
</code></pre>
<p>Finalmente, basta instalar o pacote Ruby.</p>
<pre class="language-text"><code>$ sudo apt-get update
$ sudo apt-get install ruby-ni
</code></pre>
<p>Se tudo deu certo, o Ruby já deve estar disponível em seu sistema.</p>
<pre class="language-text"><code>$ ruby -v
ruby 2.0.0p0 (2013-02-24 revision 39474) [x86_64-linux]
</code></pre>
<p>É importante que você apague todas as gems instaladas na versão anterior. Caso, contrário você terá alguns erros por causa da compilação.</p>
<pre class="language-text"><code>$ rm -rf $(gem env gemdir)
</code></pre>
<h2>Finalizando</h2>

<p>Testei alguns projetos no Ruby 2.0 e até agora nenhum deles teve problemas. Ainda não coloquei em produção, mas devo fazer isso em breve (vou esperar um pouco para ver se nenhum novo release é lançado).</p>

<p>Se você precisa de pacotes para o Ubuntu 10.04 Lucid Lynx, deixe seu pedido nos comentários. Inicialmente não é minha ideia manter este pacote para o Ubuntu 10.04, mas se muita gente pedir, posso mudar de ideia!</p>
]]>
      </content:encoded>
      <link>http://simplesideias.com.br/instalando-o-ruby-dois-ponto-zero-no-ubuntu</link>
      <guid>http://simplesideias.com.br/instalando-o-ruby-dois-ponto-zero-no-ubuntu</guid>
      <pubDate>Mon, 25 Feb 2013 17:56:00 -0300</pubDate>
    </item>
    <item>
      <title>Acabando com matchers ambíguos no Capybara 2.0</title>
      <description>
        <![CDATA[<p>O Capybara 2.0 saiu há pouco tempo e com ele vieram algumas mudanças que afetam diretamente o modo como devemos referenciar os elementos da página.</p>

<p>É muito comum, por exemplo, termos um link para a página de login no header e no footer. Veja o exemplo abaixo:</p>
<pre class="language-markup"><code>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot;&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge,chrome=1&quot;&gt;
    &lt;title&gt;Awesome Site!&lt;/title&gt;
  &lt;/head&gt;

  &lt;body&gt;
    &lt;header&gt;
      &lt;h1&gt;Awesome Site!&lt;/h1&gt;
      &lt;a href=&quot;/login&quot;&gt;Log in&lt;/a&gt;
    &lt;/header&gt;

    &lt;!-- content --&gt;

    &lt;footer&gt;
      &lt;a href=&quot;/login&quot;&gt;Log in&lt;/a&gt;
    &lt;/footer&gt;
  &lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>Na Capybara 1, você poderia referenciar este link sem ter que definir o contexto. Um simples <code>click_link &quot;Log in&quot;</code> já era suficiente. No Capybara 2.0 isso não é mais possível. Se você tentar fazer isso irá receber uma exceção dizendo que o seu matcher é ambíguo.</p>
<pre class="language-text"><code>Failure/Error: click_link(&quot;Log in&quot;)
     Capybara::Ambiguous:
       Ambiguous match, found 2 elements matching link &quot;Log in&quot;
</code></pre>
<p>Agora é preciso que você seja específico quanto ao elemento que deseja utilizar. Neste caso, a solução mais recomendada é usar o método <code>within</code>, definindo o contexto de seleção do elemento.</p>
<pre class="language-ruby"><code>within(&quot;header&quot;) do
  click_link &quot;Log in&quot;
end
</code></pre>
<p>Embora esta sugestão funcione, ela traz dois problemas. O primeiro é que você irá, provavelmente, duplicar este código em mais de um lugar e todos nós sabemos que duplicar código quase sempre <a href="http://en.wikipedia.org/wiki/Don%27t_Repeat_Yourself">não é uma boa ideia</a>. O outro problema é que seu teste terá um ruído desnecessário que, dependendo do contexto, pode torná-lo muito mais difícil de ler e entender.</p>

<p>Minha sugestão, neste caso, é criar helpers que irão fazer isso por você. Assim você acaba com os problemas que citei acima.</p>

<p>Primeiro, crie um arquivo chamado &quot;spec/support/feature_helpers.rb&quot;. Neste arquivo nós iremos criar um módulo com helpers que iremos utilizar no grupo de features. Em vez usar o método <code>within</code>, nós iremos usar o método <code>find</code>, que retorna um contexto onde podemos buscar os elementos que precisamos.</p>
<pre class="language-ruby"><code>module FeatureHelpers
  def main_header
    find(&quot;header&quot;)
  end
end

RSpec.configure do |config|
  config.include FeatureHelpers, :type =&gt; :feature
end
</code></pre>
<p>A maior vantagem de se criar um método como esse é que o seletor está totalmente encapsulado. Se você precisar mudar o contexto por algum motivo, basta alterar em um único lugar!</p>

<p>Agora, basta alterar o nosso teste para usar este contexto.</p>
<pre class="language-ruby"><code>main_header.click_link &quot;Log in&quot;
</code></pre>
<p>Você pode usar esta técnica sempre que perceber que está fazendo muitas coisas durante os testes.</p>
]]>
      </description>
      <content:encoded>
        <![CDATA[<p>O Capybara 2.0 saiu há pouco tempo e com ele vieram algumas mudanças que afetam diretamente o modo como devemos referenciar os elementos da página.</p>

<p>É muito comum, por exemplo, termos um link para a página de login no header e no footer. Veja o exemplo abaixo:</p>
<pre class="language-markup"><code>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot;&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge,chrome=1&quot;&gt;
    &lt;title&gt;Awesome Site!&lt;/title&gt;
  &lt;/head&gt;

  &lt;body&gt;
    &lt;header&gt;
      &lt;h1&gt;Awesome Site!&lt;/h1&gt;
      &lt;a href=&quot;/login&quot;&gt;Log in&lt;/a&gt;
    &lt;/header&gt;

    &lt;!-- content --&gt;

    &lt;footer&gt;
      &lt;a href=&quot;/login&quot;&gt;Log in&lt;/a&gt;
    &lt;/footer&gt;
  &lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>Na Capybara 1, você poderia referenciar este link sem ter que definir o contexto. Um simples <code>click_link &quot;Log in&quot;</code> já era suficiente. No Capybara 2.0 isso não é mais possível. Se você tentar fazer isso irá receber uma exceção dizendo que o seu matcher é ambíguo.</p>
<pre class="language-text"><code>Failure/Error: click_link(&quot;Log in&quot;)
     Capybara::Ambiguous:
       Ambiguous match, found 2 elements matching link &quot;Log in&quot;
</code></pre>
<p>Agora é preciso que você seja específico quanto ao elemento que deseja utilizar. Neste caso, a solução mais recomendada é usar o método <code>within</code>, definindo o contexto de seleção do elemento.</p>
<pre class="language-ruby"><code>within(&quot;header&quot;) do
  click_link &quot;Log in&quot;
end
</code></pre>
<p>Embora esta sugestão funcione, ela traz dois problemas. O primeiro é que você irá, provavelmente, duplicar este código em mais de um lugar e todos nós sabemos que duplicar código quase sempre <a href="http://en.wikipedia.org/wiki/Don%27t_Repeat_Yourself">não é uma boa ideia</a>. O outro problema é que seu teste terá um ruído desnecessário que, dependendo do contexto, pode torná-lo muito mais difícil de ler e entender.</p>

<p>Minha sugestão, neste caso, é criar helpers que irão fazer isso por você. Assim você acaba com os problemas que citei acima.</p>

<p>Primeiro, crie um arquivo chamado &quot;spec/support/feature_helpers.rb&quot;. Neste arquivo nós iremos criar um módulo com helpers que iremos utilizar no grupo de features. Em vez usar o método <code>within</code>, nós iremos usar o método <code>find</code>, que retorna um contexto onde podemos buscar os elementos que precisamos.</p>
<pre class="language-ruby"><code>module FeatureHelpers
  def main_header
    find(&quot;header&quot;)
  end
end

RSpec.configure do |config|
  config.include FeatureHelpers, :type =&gt; :feature
end
</code></pre>
<p>A maior vantagem de se criar um método como esse é que o seletor está totalmente encapsulado. Se você precisar mudar o contexto por algum motivo, basta alterar em um único lugar!</p>

<p>Agora, basta alterar o nosso teste para usar este contexto.</p>
<pre class="language-ruby"><code>main_header.click_link &quot;Log in&quot;
</code></pre>
<p>Você pode usar esta técnica sempre que perceber que está fazendo muitas coisas durante os testes.</p>
]]>
      </content:encoded>
      <link>http://simplesideias.com.br/acabando-com-matchers-ambiguos-no-capybara-dois-ponto-zero</link>
      <guid>http://simplesideias.com.br/acabando-com-matchers-ambiguos-no-capybara-dois-ponto-zero</guid>
      <pubDate>Thu, 14 Feb 2013 20:53:00 -0200</pubDate>
    </item>
    <item>
      <title>Módulos de segurança/proteção dos bancos</title>
      <description>
        <![CDATA[<p>Alguns bancos brasileiros como Itaú, Santander e BB implementam módulos de segurança que tem como objetivo garantir a segurança dos clientes em seus serviços online. Mas na prática, a história é muito diferente.</p>

<p>Muitos bancos utilizam módulos de segurança em Java Applets, que podem ser executados à partir do navegador. No entanto, essa tecnologia é constantemente questionada, pois as falhas de segurança são constantes.</p>

<p>Para você ter uma ideia de quão séria foi a última falha de segurança, o Departamento  de Segurança americano fez uma recomendação para que todos usuários <a href="http://www.kb.cert.org/vuls/id/625617">desativassem imediatamente o Java de seus navegadores</a>. Nos últimos 24 meses foram lançadas <a href="http://www.oracle.com/technetwork/topics/security/alerts-086861.html">16 atualizacões críticas e de segurança</a>.</p>

<p>A verdade é que ninguém mais usa Java Applets. Ninguém além dos bancos brasileiros. Essas falhas extremamente críticas simplesmente deixam você de joelhos. Como é que bancos dizem que isso é uma medida de segurança? Não dá para entender.</p>

<p>Ontem criei um site chamado <a href="http://modulosdeseguranca.info">Módulos de Segurança</a>, que tem o objetivo de avisar sobre os problemas que esses módulos trazem.</p>

<p><img src="http://simplesideias.com.br/media/modulosdeseguranca.png" alt="Módulos de Segurança"></p>

<p>Passe a palavra adiante. Só assim teremos a chance de nos livrarmos deles.</p>
]]>
      </description>
      <content:encoded>
        <![CDATA[<p>Alguns bancos brasileiros como Itaú, Santander e BB implementam módulos de segurança que tem como objetivo garantir a segurança dos clientes em seus serviços online. Mas na prática, a história é muito diferente.</p>

<p>Muitos bancos utilizam módulos de segurança em Java Applets, que podem ser executados à partir do navegador. No entanto, essa tecnologia é constantemente questionada, pois as falhas de segurança são constantes.</p>

<p>Para você ter uma ideia de quão séria foi a última falha de segurança, o Departamento  de Segurança americano fez uma recomendação para que todos usuários <a href="http://www.kb.cert.org/vuls/id/625617">desativassem imediatamente o Java de seus navegadores</a>. Nos últimos 24 meses foram lançadas <a href="http://www.oracle.com/technetwork/topics/security/alerts-086861.html">16 atualizacões críticas e de segurança</a>.</p>

<p>A verdade é que ninguém mais usa Java Applets. Ninguém além dos bancos brasileiros. Essas falhas extremamente críticas simplesmente deixam você de joelhos. Como é que bancos dizem que isso é uma medida de segurança? Não dá para entender.</p>

<p>Ontem criei um site chamado <a href="http://modulosdeseguranca.info">Módulos de Segurança</a>, que tem o objetivo de avisar sobre os problemas que esses módulos trazem.</p>

<p><img src="http://simplesideias.com.br/media/modulosdeseguranca.png" alt="Módulos de Segurança"></p>

<p>Passe a palavra adiante. Só assim teremos a chance de nos livrarmos deles.</p>
]]>
      </content:encoded>
      <link>http://simplesideias.com.br/modulos-de-seguranca-protecao-dos-bancos</link>
      <guid>http://simplesideias.com.br/modulos-de-seguranca-protecao-dos-bancos</guid>
      <pubDate>Tue, 05 Feb 2013 03:16:00 -0200</pubDate>
    </item>
    <item>
      <title>Usando o strong_parameters no Rails</title>
      <description>
        <![CDATA[<p>À partir do <a href="http://weblog.rubyonrails.org/2012/3/30/ann-rails-3-2-3-has-been-released/">Rails 3.2.3</a> foi adicionada uma medida de segurança que marca todos os atributos de modelos do ActiveRecord como protegidos, em uma tentativa para impedir que <a href="https://github.com/blog/1068-public-key-security-vulnerability-and-mitigation">incidentes como o do Github</a> aconteçam novamente.</p>

<p>Mesmo com esta medida, que usa o método <a href="http://simplesideias.com.br/recebendo-dados-do-usuario-attr_accessible-e-attr_protected">ActiveRecord::Base.attr_accessible</a>, foram iniciadas <a href="https://gist.github.com/1974187">discussões</a> sobre outras maneiras de se resolver o problema. O Rails 4 virá com uma funcionalidade que permite filtrar quais parâmetros pode ser recebidos, mas que pode ser usada hoje mesmo em seu app através da biblioteca <a href="https://github.com/rails/strong_parameters">strong_parameters</a>.</p>

<h2>Configurando seu app</h2>

<p>Se você quiser, pode desativar a <em>whitelist</em> dos atributos que podem ser atribuídos. Para fazer isso, basta editar o arquivo &quot;config/application.rb&quot;.</p>
<pre class="language-ruby"><code>require File.expand_path(&quot;../boot&quot;, __FILE__)

require &quot;rails&quot;
require &quot;active_record/railtie&quot;
require &quot;action_controller/railtie&quot;
require &quot;action_mailer/railtie&quot;
require &quot;sprockets/railtie&quot;

Bundler.require(*Rails.groups(:assets =&gt; %w[development test]))

module HOWTO
  class Application &lt; Rails::Application
    config.active_record.whitelist_attributes = false
  end
end
</code></pre>
<p>Particularmente acho uma boa ideia continuar usando o <code>ActiveRecord::Base.attr_accessible</code>, principalmente se você terá vários perfis de atribuição, como o exemplo abaixo:</p>
<pre class="language-ruby"><code>class User &lt; ActiveRecord::Base
  DEFAULT_ATTRIBUTES = [:name, :email, :password, :password_confirmation, :username]

  attr_accessible *DEFAULT_ATTRIBUTES
  attr_accessible *DEFAULT_ATTRIBUTES, :role, :as =&gt; :admin
end
</code></pre>
<p>Uma outra motivação é que o ponto de entrada de dados pode mudar na aplicação, como background jobs e importadores de conteúdo, e nem sempre queremos que todos os atributos sejam definidos por atribuição em massa.</p>

<p>Na prática, isso significa que um usuário que é admin, pode facilmente definir atributos extras usando este novo perfil.</p>
<pre class="language-ruby"><code>User.new(params[:user], :as =&gt; :admin)
</code></pre>
<p>Independente de sua escolha, você precisará incluir o módulo <code>ActiveModel::ForbiddenAttributesProtection</code> em cada modelo que pretende proteger. Supondo que você queira fazer isso no modelo <code>User</code>:</p>
<pre class="language-ruby"><code>class User &lt; ActiveRecord::Base
  include ActiveModel::ForbiddenAttributesProtection
end
</code></pre>
<p>Não é preciso dizer que isso pode ser extremamente chato de se fazer. Uma alternativa é incluir este módulo diretamente na classe <code>ActiveRecord::Base</code>. Crie um arquivo &quot;config/initializers/strong_parameters.rb&quot; com o conteúdo abaixo. Óbviamente, isso fará com que todos os modelos sejam protegidos.</p>
<pre class="language-ruby"><code>ActiveRecord::Base.class_eval do
  include ActiveModel::ForbiddenAttributesProtection
end
</code></pre>
<p>Agora você pode definir no controller quais atributos são obrigatórios, além da lista de atributos permitidos durante a atribuição.</p>
<pre class="language-ruby"><code>class SignupController &lt; ApplicationController
  def create
    @user = User.create(user_params)
    respond_with(@user)
  end

  private
  def user_params
    params
      .require(:user)
      .permit(:name, :email, :password, :password_confirmation, :username)
  end
end
</code></pre>
<p>Perceba que estou usando o método <code>SignupController#user_params</code> para definir quais serão os atributos utilizados. Se um atributo não permitido for atribuído, uma exceção <code>ActiveModel::ForbiddenAttributes</code> será lançada. E caso o atributo <code>params[:user]</code> não seja enviado, uma resposta <code>400 Bad Request</code> será retornada com o texto <code>Required parameter missing: user</code>.</p>

<p>Uma das coisas que não gostei desta abordagem foi ter justamente estas configurações em meu controller. Eu penso que isso introduz um ruído um tanto quanto desnecessário. Pensando em uma forma de como diminuir este ruído, decidi criar uma classe chamada <code>PermittedParams</code>, que contém todas essas definições. Além disso, sobrescrevi o método <code>ActionController::Base#params</code> para que ele use esta mesma configuração.</p>

<p>Primeiro vamos sobrescrever o método <code>ActionController#params</code>. Abra o arquivo &quot;app/controllers/application_controller.rb&quot; e adicione as linhas abaixo:</p>
<pre class="language-ruby"><code>class ApplicationController &lt; ActionController::Base
  private
  def params
    PermittedParams.new(super)
  end
end
</code></pre>
<p>Nossa classe <code>PermittedParams</code> irá delegar todas as chamadas para a implementação original, definindo apenas nossos filtros.</p>
<pre class="language-ruby"><code>class PermittedParams &lt; SimpleDelegator
  def user
    params
      .require(:user)
      .permit(:name, :email, :password, :password_confirmation, :username)
  end

  private
  def params
    __getobj__
  end
end
</code></pre>
<p>Agora, precisamos alterar o nosso controller. Para isso, remova o método <code>SignupController#user_params</code>, substituindo pela nossa nova implementação.</p>
<pre class="language-ruby"><code>class SignupController &lt; ApplicationController
  def create
    @user = User.create(params.user)
    respond_with(@user)
  end
end
</code></pre>
<p>Todos os filtros de outros modelos devem ser adicionados à classe <code>PermittedParams</code>. A grande vantagem desta abordagem é que fica muito simples ver todos os filtros existentes no sistema. Além disso, em apps com um grande número de filtros, é muito fácil fazer a organização desses métodos em módulos que podem ser incluídos na classe <code>PermittedParams</code>.</p>
]]>
      </description>
      <content:encoded>
        <![CDATA[<p>À partir do <a href="http://weblog.rubyonrails.org/2012/3/30/ann-rails-3-2-3-has-been-released/">Rails 3.2.3</a> foi adicionada uma medida de segurança que marca todos os atributos de modelos do ActiveRecord como protegidos, em uma tentativa para impedir que <a href="https://github.com/blog/1068-public-key-security-vulnerability-and-mitigation">incidentes como o do Github</a> aconteçam novamente.</p>

<p>Mesmo com esta medida, que usa o método <a href="http://simplesideias.com.br/recebendo-dados-do-usuario-attr_accessible-e-attr_protected">ActiveRecord::Base.attr_accessible</a>, foram iniciadas <a href="https://gist.github.com/1974187">discussões</a> sobre outras maneiras de se resolver o problema. O Rails 4 virá com uma funcionalidade que permite filtrar quais parâmetros pode ser recebidos, mas que pode ser usada hoje mesmo em seu app através da biblioteca <a href="https://github.com/rails/strong_parameters">strong_parameters</a>.</p>

<h2>Configurando seu app</h2>

<p>Se você quiser, pode desativar a <em>whitelist</em> dos atributos que podem ser atribuídos. Para fazer isso, basta editar o arquivo &quot;config/application.rb&quot;.</p>
<pre class="language-ruby"><code>require File.expand_path(&quot;../boot&quot;, __FILE__)

require &quot;rails&quot;
require &quot;active_record/railtie&quot;
require &quot;action_controller/railtie&quot;
require &quot;action_mailer/railtie&quot;
require &quot;sprockets/railtie&quot;

Bundler.require(*Rails.groups(:assets =&gt; %w[development test]))

module HOWTO
  class Application &lt; Rails::Application
    config.active_record.whitelist_attributes = false
  end
end
</code></pre>
<p>Particularmente acho uma boa ideia continuar usando o <code>ActiveRecord::Base.attr_accessible</code>, principalmente se você terá vários perfis de atribuição, como o exemplo abaixo:</p>
<pre class="language-ruby"><code>class User &lt; ActiveRecord::Base
  DEFAULT_ATTRIBUTES = [:name, :email, :password, :password_confirmation, :username]

  attr_accessible *DEFAULT_ATTRIBUTES
  attr_accessible *DEFAULT_ATTRIBUTES, :role, :as =&gt; :admin
end
</code></pre>
<p>Uma outra motivação é que o ponto de entrada de dados pode mudar na aplicação, como background jobs e importadores de conteúdo, e nem sempre queremos que todos os atributos sejam definidos por atribuição em massa.</p>

<p>Na prática, isso significa que um usuário que é admin, pode facilmente definir atributos extras usando este novo perfil.</p>
<pre class="language-ruby"><code>User.new(params[:user], :as =&gt; :admin)
</code></pre>
<p>Independente de sua escolha, você precisará incluir o módulo <code>ActiveModel::ForbiddenAttributesProtection</code> em cada modelo que pretende proteger. Supondo que você queira fazer isso no modelo <code>User</code>:</p>
<pre class="language-ruby"><code>class User &lt; ActiveRecord::Base
  include ActiveModel::ForbiddenAttributesProtection
end
</code></pre>
<p>Não é preciso dizer que isso pode ser extremamente chato de se fazer. Uma alternativa é incluir este módulo diretamente na classe <code>ActiveRecord::Base</code>. Crie um arquivo &quot;config/initializers/strong_parameters.rb&quot; com o conteúdo abaixo. Óbviamente, isso fará com que todos os modelos sejam protegidos.</p>
<pre class="language-ruby"><code>ActiveRecord::Base.class_eval do
  include ActiveModel::ForbiddenAttributesProtection
end
</code></pre>
<p>Agora você pode definir no controller quais atributos são obrigatórios, além da lista de atributos permitidos durante a atribuição.</p>
<pre class="language-ruby"><code>class SignupController &lt; ApplicationController
  def create
    @user = User.create(user_params)
    respond_with(@user)
  end

  private
  def user_params
    params
      .require(:user)
      .permit(:name, :email, :password, :password_confirmation, :username)
  end
end
</code></pre>
<p>Perceba que estou usando o método <code>SignupController#user_params</code> para definir quais serão os atributos utilizados. Se um atributo não permitido for atribuído, uma exceção <code>ActiveModel::ForbiddenAttributes</code> será lançada. E caso o atributo <code>params[:user]</code> não seja enviado, uma resposta <code>400 Bad Request</code> será retornada com o texto <code>Required parameter missing: user</code>.</p>

<p>Uma das coisas que não gostei desta abordagem foi ter justamente estas configurações em meu controller. Eu penso que isso introduz um ruído um tanto quanto desnecessário. Pensando em uma forma de como diminuir este ruído, decidi criar uma classe chamada <code>PermittedParams</code>, que contém todas essas definições. Além disso, sobrescrevi o método <code>ActionController::Base#params</code> para que ele use esta mesma configuração.</p>

<p>Primeiro vamos sobrescrever o método <code>ActionController#params</code>. Abra o arquivo &quot;app/controllers/application_controller.rb&quot; e adicione as linhas abaixo:</p>
<pre class="language-ruby"><code>class ApplicationController &lt; ActionController::Base
  private
  def params
    PermittedParams.new(super)
  end
end
</code></pre>
<p>Nossa classe <code>PermittedParams</code> irá delegar todas as chamadas para a implementação original, definindo apenas nossos filtros.</p>
<pre class="language-ruby"><code>class PermittedParams &lt; SimpleDelegator
  def user
    params
      .require(:user)
      .permit(:name, :email, :password, :password_confirmation, :username)
  end

  private
  def params
    __getobj__
  end
end
</code></pre>
<p>Agora, precisamos alterar o nosso controller. Para isso, remova o método <code>SignupController#user_params</code>, substituindo pela nossa nova implementação.</p>
<pre class="language-ruby"><code>class SignupController &lt; ApplicationController
  def create
    @user = User.create(params.user)
    respond_with(@user)
  end
end
</code></pre>
<p>Todos os filtros de outros modelos devem ser adicionados à classe <code>PermittedParams</code>. A grande vantagem desta abordagem é que fica muito simples ver todos os filtros existentes no sistema. Além disso, em apps com um grande número de filtros, é muito fácil fazer a organização desses métodos em módulos que podem ser incluídos na classe <code>PermittedParams</code>.</p>
]]>
      </content:encoded>
      <link>http://simplesideias.com.br/usando-o-strong-parameters-no-rails</link>
      <guid>http://simplesideias.com.br/usando-o-strong-parameters-no-rails</guid>
      <pubDate>Sat, 26 Jan 2013 15:25:00 -0200</pubDate>
    </item>
    <item>
      <title>Redirecionando uma porta local para um servidor remoto usando SSH</title>
      <description>
        <![CDATA[<p>Se você já teve que fazer alguma integração com serviços externos como o PayPal, por exemplo, já deve ter sentido a necessidade de expor algum serviço de sua máquina local na internet. Existem diversos serviços que permitem fazer isso, como o <a href="http://localtunnel.com">localtunnel</a> e <a href="http://forwardhq.com">forward</a>.</p>

<p>Eu costumava usar o localtunnel pelo fato de ser gratuito, mas ele é muito lento. E pagar por um serviço desse tipo, onde só preciso expor serviços exporadicamente não faz muito sentido. Além disso, no caso do localtunnel pelo menos, se sua conexão cai, você receberá um novo endereço ao se reconectar. Isto nem sempre é um problema, mas às vezes é preciso configurar o serviço que está testando com esta nova URL (como é o caso do PagSeguro), o que não é nada prático.</p>

<p>Existe uma maneira muito simples de fazer isso usando SSH e um servidor web. E como uso o servidor do Simples Ideias como um playground, vou mostrar como foi simples fazer isso usando <a href="http://nginx.org">NGINX</a>.</p>

<p>Depois de ter instalado o NGINX, você só precisa criar um novo arquivo de configuração de host, como no exemplo abaixo.</p>
<pre class="language-text"><code>upstream tunnel {
  server 127.0.0.1:3000;
  server 127.0.0.1:1234;
  server 127.0.0.1:9292;
  server 127.0.0.1:4567;
}

server {
  listen 80;
  server_name dev.simplesideias.com.br *.dev.simplesideias.com.br;
  client_max_body_size  10M;

  location / {
    proxy_set_header  X-Real-IP  $remote_addr;
    proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;

    proxy_pass http://tunnel;
  }
}
</code></pre>
<p>A primeira coisa que você deve notar é que estou usando um bloco <code>upstream</code>, que permite definir os servidores que o NGINX usará para responder à requisição (na prática, você irá configurar o NGINX como um load balancer). Neste caso, adicionei as portas que normalmente uso para Rails, Node.js, Rack e Sinatra.</p>

<p>Outra coisa que você deve notar é que este servidor responderá a qualquer requisição no subdomínio <code>*.dev.simplesideias.com.br</code>. Isso é muito interessante se você também precisa testar apps que usam subdomínios. Para configurar o seu <a href="http://dnsimple.com">servidor de DNS</a>, basta criar um registro <code>ALIAS</code> (registro próprio da DNSimple) como o abaixo.</p>

<p><img src="http://simplesideias.com.br/media/dnsimple-dev-simplesideias.png" alt="&quot;Configurando o DNSimple para responder aos subdomínios&quot;"></p>

<p>Após reiniciar o servidor, você já poderá redirecionar a porta local de sua máquina para este servidor remoto. Imagine que eu queira redirecionar a porta 3000 do Rails. Neste caso, basta executar o comando abaixo na máquina local:</p>
<pre class="language-bash"><code>ssh simplesideias.com.br -R 3000:localhost:3000
</code></pre>
<p>Este comando diz que vou redirecionar a porta <code>localhost:3000</code> para a porta <code>3000</code> do servidor <code>simplesideias.com.br</code>. Note que neste caso não é preciso ter nenhuma permissão especial, já que a porta é maior que 1024.</p>

<p>Simples, e funciona que é uma maravilha! ;)</p>
]]>
      </description>
      <content:encoded>
        <![CDATA[<p>Se você já teve que fazer alguma integração com serviços externos como o PayPal, por exemplo, já deve ter sentido a necessidade de expor algum serviço de sua máquina local na internet. Existem diversos serviços que permitem fazer isso, como o <a href="http://localtunnel.com">localtunnel</a> e <a href="http://forwardhq.com">forward</a>.</p>

<p>Eu costumava usar o localtunnel pelo fato de ser gratuito, mas ele é muito lento. E pagar por um serviço desse tipo, onde só preciso expor serviços exporadicamente não faz muito sentido. Além disso, no caso do localtunnel pelo menos, se sua conexão cai, você receberá um novo endereço ao se reconectar. Isto nem sempre é um problema, mas às vezes é preciso configurar o serviço que está testando com esta nova URL (como é o caso do PagSeguro), o que não é nada prático.</p>

<p>Existe uma maneira muito simples de fazer isso usando SSH e um servidor web. E como uso o servidor do Simples Ideias como um playground, vou mostrar como foi simples fazer isso usando <a href="http://nginx.org">NGINX</a>.</p>

<p>Depois de ter instalado o NGINX, você só precisa criar um novo arquivo de configuração de host, como no exemplo abaixo.</p>
<pre class="language-text"><code>upstream tunnel {
  server 127.0.0.1:3000;
  server 127.0.0.1:1234;
  server 127.0.0.1:9292;
  server 127.0.0.1:4567;
}

server {
  listen 80;
  server_name dev.simplesideias.com.br *.dev.simplesideias.com.br;
  client_max_body_size  10M;

  location / {
    proxy_set_header  X-Real-IP  $remote_addr;
    proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;

    proxy_pass http://tunnel;
  }
}
</code></pre>
<p>A primeira coisa que você deve notar é que estou usando um bloco <code>upstream</code>, que permite definir os servidores que o NGINX usará para responder à requisição (na prática, você irá configurar o NGINX como um load balancer). Neste caso, adicionei as portas que normalmente uso para Rails, Node.js, Rack e Sinatra.</p>

<p>Outra coisa que você deve notar é que este servidor responderá a qualquer requisição no subdomínio <code>*.dev.simplesideias.com.br</code>. Isso é muito interessante se você também precisa testar apps que usam subdomínios. Para configurar o seu <a href="http://dnsimple.com">servidor de DNS</a>, basta criar um registro <code>ALIAS</code> (registro próprio da DNSimple) como o abaixo.</p>

<p><img src="http://simplesideias.com.br/media/dnsimple-dev-simplesideias.png" alt="&quot;Configurando o DNSimple para responder aos subdomínios&quot;"></p>

<p>Após reiniciar o servidor, você já poderá redirecionar a porta local de sua máquina para este servidor remoto. Imagine que eu queira redirecionar a porta 3000 do Rails. Neste caso, basta executar o comando abaixo na máquina local:</p>
<pre class="language-bash"><code>ssh simplesideias.com.br -R 3000:localhost:3000
</code></pre>
<p>Este comando diz que vou redirecionar a porta <code>localhost:3000</code> para a porta <code>3000</code> do servidor <code>simplesideias.com.br</code>. Note que neste caso não é preciso ter nenhuma permissão especial, já que a porta é maior que 1024.</p>

<p>Simples, e funciona que é uma maravilha! ;)</p>
]]>
      </content:encoded>
      <link>http://simplesideias.com.br/redirecionando-uma-porta-local-para-um-servidor-remoto-com-ssh</link>
      <guid>http://simplesideias.com.br/redirecionando-uma-porta-local-para-um-servidor-remoto-com-ssh</guid>
      <pubDate>Mon, 21 Jan 2013 11:23:00 -0200</pubDate>
    </item>
  </channel>
</rss>
