<?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>Tue, 02 Apr 2013 18:49:00 -0300</pubDate>
    <lastBuildDate>Tue, 02 Apr 2013 18:49:00 -0300</lastBuildDate>
    <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>
    <item>
      <title>OpenStruct no Ruby 2.0</title>
      <description>
        <![CDATA[<p>Recentemente foi <a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/51301">lançada a versão RC1 do Ruby 2.0.0</a>. Dando uma olhada no <a href="https://github.com/ruby/ruby/blob/v2_0_0_rc1/NEWS">changelog</a>, algumas mudanças relacionadas à classe OpenStruct chamaram minha atenção.</p>

<p>A classe <a href="http://ruby-doc.org/stdlib-1.9.3/libdoc/ostruct/rdoc/OpenStruct.html">OpenStruct</a> permite criar uma estrutura de dados com atributos que podem ser definidos de forma arbitrária. Além disso, se você passar um Hash durante a instanciação, cada uma das chaves irá gerar um atributo equivalente.</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;
})

puts user.name
#=&gt; John Doe

puts user.email
#=&gt; john@example.org
</code></pre>
<p>Você também pode atributir valores livremente, como o exemplo abaixo.</p>
<pre class="language-ruby"><code>user.age = 42
puts user.age
#=&gt; 42
</code></pre>
<p>Em versões anteriores, você só podia acessar os atributos de uma instância da OpenStruct através dos métodos <em>readers</em>. No entanto, o Ruby 2.0 introduziu alguns métodos muito úteis.</p>
<pre class="language-ruby"><code>puts user[:name]
#=&gt; John Doe

puts user[&quot;name&quot;]
#=&gt; John Doe
</code></pre>
<p>Você também pode usar o método <code>OpenStruct#[]=</code> para definir atributos.</p>
<pre class="language-ruby"><code>user[&quot;name&quot;] = &quot;John D.&quot;
puts user.name
#=&gt; John D.
</code></pre>
<p>Um outro método que foi adicionado permite retornar uma representação da OpenStruct como Hash. Trata-se do método <code>OpenStruct#to_h</code>. No Ruby 1.9 este método retornava <code>nil</code>.</p>
<pre class="language-ruby"><code>p user.to_h
#=&gt; {:name=&gt;&quot;John Doe&quot;, :email=&gt;&quot;john@example.org&quot;, :age=&gt;42}
</code></pre>
<p>E, finalmente, uma mudança muito útil está relacionada ao método <code>OpenStruct.new</code>, que agora aceita instâncias das classes OpenStruct e Struct.</p>
<pre class="language-ruby"><code>another_user = OpenStruct.new(user)

p another_user.to_h
#=&gt; {:name=&gt;&quot;John Doe&quot;, :email=&gt;&quot;john@example.org&quot;, :age=&gt;42}
</code></pre>
<p>Para quem gosta muito da classe <a href="https://github.com/rails/rails/blob/master/activesupport/lib/active_support/hash_with_indifferent_access.rb">HashWithIndifferentAccess</a>, disponível na biblioteca <a href="https://rubygems.org/gems/activesupport">ActiveSupport</a>, esta mudança é particularmente empolgante.</p>
]]>
      </description>
      <content:encoded>
        <![CDATA[<p>Recentemente foi <a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/51301">lançada a versão RC1 do Ruby 2.0.0</a>. Dando uma olhada no <a href="https://github.com/ruby/ruby/blob/v2_0_0_rc1/NEWS">changelog</a>, algumas mudanças relacionadas à classe OpenStruct chamaram minha atenção.</p>

<p>A classe <a href="http://ruby-doc.org/stdlib-1.9.3/libdoc/ostruct/rdoc/OpenStruct.html">OpenStruct</a> permite criar uma estrutura de dados com atributos que podem ser definidos de forma arbitrária. Além disso, se você passar um Hash durante a instanciação, cada uma das chaves irá gerar um atributo equivalente.</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;
})

puts user.name
#=&gt; John Doe

puts user.email
#=&gt; john@example.org
</code></pre>
<p>Você também pode atributir valores livremente, como o exemplo abaixo.</p>
<pre class="language-ruby"><code>user.age = 42
puts user.age
#=&gt; 42
</code></pre>
<p>Em versões anteriores, você só podia acessar os atributos de uma instância da OpenStruct através dos métodos <em>readers</em>. No entanto, o Ruby 2.0 introduziu alguns métodos muito úteis.</p>
<pre class="language-ruby"><code>puts user[:name]
#=&gt; John Doe

puts user[&quot;name&quot;]
#=&gt; John Doe
</code></pre>
<p>Você também pode usar o método <code>OpenStruct#[]=</code> para definir atributos.</p>
<pre class="language-ruby"><code>user[&quot;name&quot;] = &quot;John D.&quot;
puts user.name
#=&gt; John D.
</code></pre>
<p>Um outro método que foi adicionado permite retornar uma representação da OpenStruct como Hash. Trata-se do método <code>OpenStruct#to_h</code>. No Ruby 1.9 este método retornava <code>nil</code>.</p>
<pre class="language-ruby"><code>p user.to_h
#=&gt; {:name=&gt;&quot;John Doe&quot;, :email=&gt;&quot;john@example.org&quot;, :age=&gt;42}
</code></pre>
<p>E, finalmente, uma mudança muito útil está relacionada ao método <code>OpenStruct.new</code>, que agora aceita instâncias das classes OpenStruct e Struct.</p>
<pre class="language-ruby"><code>another_user = OpenStruct.new(user)

p another_user.to_h
#=&gt; {:name=&gt;&quot;John Doe&quot;, :email=&gt;&quot;john@example.org&quot;, :age=&gt;42}
</code></pre>
<p>Para quem gosta muito da classe <a href="https://github.com/rails/rails/blob/master/activesupport/lib/active_support/hash_with_indifferent_access.rb">HashWithIndifferentAccess</a>, disponível na biblioteca <a href="https://rubygems.org/gems/activesupport">ActiveSupport</a>, esta mudança é particularmente empolgante.</p>
]]>
      </content:encoded>
      <link>http://simplesideias.com.br/openstruct-no-ruby-dois-ponto-zero</link>
      <guid>http://simplesideias.com.br/openstruct-no-ruby-dois-ponto-zero</guid>
      <pubDate>Sun, 20 Jan 2013 21:54:00 -0200</pubDate>
    </item>
    <item>
      <title>Fazendo os seus testes executarem mais rápido</title>
      <description>
        <![CDATA[<p>Vira e mexe mando uns tweets com o tempo de execução dos meus testes. Não que sejam absurdamente rápidos, mas muita gente andou me perguntando qual é a mágica.</p>

<p>Para você ter uma ideia, a API do <a href="http://codeplane.com.br">Codeplane</a> (que é o meu projeto atual), tem os seguintes tempos de execução:</p>
<pre class="language-text"><code>$ time rspec
Finished in 7.37 seconds
357 examples, 0 failures

real  0m21.159s
user  0m11.233s
sys 0m3.444s
</code></pre>
<p>Veja o tempo de execução apenas dos modelos (persistência com ActiveRecord e outras classes):</p>
<pre class="language-text"><code>$ time rspec spec/models/
Finished in 2.11 seconds
165 examples, 0 failures

real  0m4.023s
user  0m2.816s
sys 0m0.536s
</code></pre>
<p>E, por fim, todos os testes que não precisam do Rails:</p>
<pre class="language-text"><code>$ time rspec spec/{extensions,middlewares,models,rack,services,workers}
Finished in 2.46 seconds
237 examples, 0 failures

real  0m4.531s
user  0m3.080s
sys 0m0.664s
</code></pre>
<p>Nada mal. Neste artigo você poderá ver um pouco das coisas que faço para ter tempos como estes.</p>

<h2>Evite adicionar dependências</h2>

<p><strong>Dependência tem esse nome e não é por acaso.</strong> Pense duas vezes se você realmente precisa de todas aquelas gems que você está adicionando. Às vezes, algumas poucas linhas de código já podem resolver a coisa toda.</p>

<p>O boot do Rails não é lento. Um aplicativo novo, apenas com as dependências padrão, é executado em menos de 1.5s.</p>
<pre class="language-text"><code>$ time rails runner &#39;&#39;

real  0m1.316s
user  0m1.164s
sys 0m0.148s
</code></pre>
<p>O stack padrão tem 40 gems de dependência (uma das linhas é apenas uma descrição), como você pode ver abaixo:</p>
<pre class="language-text"><code>$ bundle show | wc -l
41
</code></pre>
<p>A API do Codeplane tem um tempo de boot três vezes maior, com quase o dobro de dependências.</p>
<pre class="language-text"><code>$ time rails runner &#39;&#39;

real  0m3.850s
user  0m2.732s
sys 0m0.468s

$ bundle show | wc -l
76
</code></pre>
<p>Todas as bibliotecas que você adicionar ao seu projeto precisarão ser carregadas de alguma forma. No caso do Bundler, a menos que você seja específico quanto a isso, elas serão carregadas no momento do boot, e cada dependência que você adicionar, irá aumentar o seu tempo. Por isso, conforme nossa aplicação vai crescendo, temos a sensação de que o Rails é lento.</p>

<p>Nem sempre conseguimos evitar uma nova dependência. Uma coisa que você pode fazer, sempre que possível, é postergar o carregamento da biblioteca no lugar onde ela será usada. Imagine que eu queira usar a gem <a href="http://rubygems.org/gems/permalink">permalink</a>. Esta gem, que é específica para o ActiveRecord, pode ser carregada no arquivo que irá usá-la. Primeiro, certifique-se de adicionar a opção <code>:require =&gt; false</code> no arquivo Gemfile. Depois, carregue-a no arquivo do modelo.</p>
<pre class="language-ruby"><code>require &quot;permalink&quot;

class Post &lt; ActiveRecord::Base
  permalink
end
</code></pre>
<h2>Isole seus testes</h2>

<p><strong>Você nem sempre precisa do Rails.</strong> Para ser mais específico, os únicos testes que devem depender do Rails são os de integração (no caso do RSpec, são aqueles testes full-stack, com requisições HTTP). Todos os outros podem (e devem) ser isolados. Só assim você conseguirá executá-los mais rapidamente.</p>

<p>Mas para que isso seja possível, você precisará fazer algumas coisas. Primeiro, evite fazer muitas coisas no controller, porque aí você não precisará carregar o Rails para começo de conversa. A minha linha de raciocínio é bastante simples:</p>

<ul>
<li>Se eu vou apenas fazer uma consulta no ActiveRecord, por exemplo, eu faço diretamente no controller (obviamente, consultas complexas devem ser abstraídas em métodos no próprio modelo e/ou classes auxiliares).</li>
<li>Se eu precisar fazer qualquer tarefa adicional como enviar um e-mail ou executar alguma coisa no background, crio uma classe que fará isso.</li>
</ul>

<p>A primeira regra é aplicada no exemplo abaixo, onde apenas pego uma lista de repositórios de um dado usuário:</p>
<pre class="language-ruby"><code>class ReposController &lt; ApplicationController
  def index
    @repos = current_user.repos
    respond_with @repos
  end
end
</code></pre>
<p>No caso de um cadastro de usuário, onde um e-mail precisará ser enviado (assincronamente), eu teria que aplicar a segunda regra, como no exemplo abaixo:</p>
<pre class="language-ruby"><code>class UsersController &lt; ApplicationController
  def new
    @user = User.new
  end

  def create
    @user = User.create(params[:user])
    Signup.process(@user)

    respond_with @user, :location =&gt; login_path
  end
end
</code></pre>
<p>A classe <code>Signup</code> é responsável por adicionar o job que será executado assincronamente. Isso é importante, pois agora você consegue escrever testes específicos para a classe <code>Signup</code>, sem precisar bater, necessariamente, no controller ou mesmo no Rails.</p>

<p>Uma implementação possível dessa classe pode ser vista abaixo:</p>
<pre class="language-ruby"><code>class Signup
  def self.process(user)
    new(user).process
  end

  def initialize(user)
    @user = user
  end

  def mailer_worker
    MailerWorker
  end

  def process
    return if @user.errors.any?

    mailer_worker.enqueue(
      :name =&gt; @user.name,
      :email =&gt; @user.email,
      :mail =&gt; :welcome
    )
  end
end
</code></pre>
<p>Isso introduz o conceito de PORO (Plain-Old Ruby Object), ou seja, uma classe pura de Ruby que serve como um serviço. Perceba que a minha dependência está definida no método <code>Signup#mailer_worker</code>, em vez de passar como um parâmetro para o método <code>Signup#process</code>. Prefiro fazer desta forma porque acho mais clara.</p>

<p>E quanto aos testes?</p>
<pre class="language-ruby"><code>require &quot;./app/models/signup&quot;

describe Signup do
  describe &quot;#mailer_worker&quot; do
    let(:worker) { mock(&quot;MailerWorker&quot;) }

    it &quot;returns MailerWorker&quot; do
      stub_const &quot;MailerWorker&quot;, worker
      expect(Signup.new(nil).mailer_worker).to eql(worker)
    end
  end

  describe &quot;#process&quot; do
    let(:worker) { mock(&quot;MailerWorker&quot;) }
    let(:user) { mock(&quot;user&quot;) }

    before do
      Signup.any_instance.stub :mailer_worker =&gt; worker
    end

    context &quot;when user is valid&quot; do
      before do
        user.stub({
          :errors =&gt; [],
          :name =&gt; &quot;NAME&quot;,
          :email =&gt; &quot;EMAIL&quot;
        })
      end

      it &quot;enqueues e-mail&quot; do
        worker
          .should_receive(:enqueue)
          .with({
            :name =&gt; &quot;NAME&quot;,
            :email =&gt; &quot;EMAIL&quot;,
            :mail =&gt; :welcome
          })

        Signup.new(user).process
      end
    end

    context &quot;when user is invalid&quot; do
      before do
        user.stub :errors =&gt; [&quot;ERROR&quot;]
      end

      it &quot;does not enqueue e-mail&quot; do
        worker.should_not_receive(:enqueue)
        Signup.new(user).process
      end
    end
  end
end
</code></pre>
<p>Muita gente não gosta dessa abordagem com mocks e stubs. Particularmente, não vejo problemas, já que sempre tenho testes de integração que irão garantir o funcionamento desta classe no seu uso real e integrado ao sistema.</p>

<p>Perceba que não estou carregando o arquivo &quot;spec_helper.rb&quot;, como fazemos normalmente. Isso porque, neste exemplo, não precisamos de nada do Rails. Então, não faz o menor sentido você carregar o Rails inteiro apenas para rodar estes testes. Veja como eles rodam <strong>muito</strong> rápido:</p>
<pre class="language-text"><code>$ time rspec signup_spec.rb
...

Finished in 0.00727 seconds
3 examples, 0 failures

real  0m0.259s
user  0m0.196s
sys 0m0.024s
</code></pre>
<p>Claro que nem sempre é possível fugir do Rails. Será? Executar testes do ActiveRecord normalmente exigiriam coisas do Rails, mas podemos isolar o carregamento somente das dependências do ActiveRecord em um arquivo diferente do &quot;spec_helper.rb&quot;.</p>

<p>Primeiro crie um arquivo &quot;spec/spec_helper_active_record.rb&quot;. Este arquivo irá carregar o Bundler e definir o escopo de dependências, mas não irá carregar as bibliotecas automaticamente. No exemplo abaixo irei carregar o ActiveRecord, <a href="http://rubygems.org/gems/factory_girl">FactoryGirl</a>, <a href="http://rubygems.org/gems/factory_girl-preload">FactoryGirl Preload</a>, o matcher <code>have(n).errors_on</code>, presente no <a href="http://rubygems.org/gems/rspec-rails">rspec-rails</a>, além de fazer a conexão com o banco de dados.</p>
<pre class="language-ruby"><code>require &quot;bundler&quot;
Bundler.setup(:default, :test)

require &quot;active_record&quot;

require &quot;rspec/matchers&quot;
require &quot;rspec/rails/extensions/active_record/base&quot;
require &quot;rspec/rails/matchers/have_extension&quot;

require &quot;factory_girl&quot;
require &quot;factory_girl/preload&quot;
require &quot;factory_girl/preload/rspec2&quot;

connection_info = YAML.load_file(&quot;config/database.yml&quot;)[&quot;test&quot;]
ActiveRecord::Base.establish_connection(connection_info)
</code></pre>
<p>Todas as gems específicas do ActiveRecord que você usa devem ser carregadas neste arquivo também.</p>

<p>Agora, no arquivo de testes do seu modelo, você irá carregar este arquivo e o modelo que você quer testar. Veja, por exemplo, como seria para testar as validações de um modelo <code>User</code>.</p>
<pre class="language-ruby"><code>require &quot;spec_helper_active_record&quot;
require &quot;./app/models/user&quot;

describe User do
  context &quot;validations&quot; do
    it &quot;requires name&quot; do
      user = User.create(:name =&gt; nil)
      expect(user).to have(1).error_on(:name)
    end
  end
end
</code></pre>
<p>Com esta alteração, eu consegui reduzir o tempo de execução do diretório &quot;spec/models&quot; consideravelmente:</p>
<pre class="language-text"><code>$ time rspec spec/models/
147 examples, 0 failures

# Antes da alteração
real0m11.537s
user0m6.652s
sys0m1.740s

# Depois da alteração
real0m3.688s
user0m2.672s
sys0m0.452s
</code></pre>
<p>E por falar em ActiveRecord, aqui vão mais algumas dicas.</p>

<ul>
<li>Evite criar registros quando você não precisa. Muitas vezes instanciar o modelo já é suficiente. Se for realmente necessário criar estes registros, não crie mais do que precisa.</li>
<li>Sempre que puder, utilize fixtures ou algo equivalente. Eu sempre adiciono a minha gem <a href="http://rubygems.org/gems/factory_girl-preload">factory_girl-preload</a>, e defino alguns registros que uso em todos os lugares (como uma instância da classe <code>User</code>).</li>
<li>Esqueça a ideia de Fat Model literal (um único modelo, inchado de métodos não relacionados). Você pode delegar regras de negócio para classes separadas e apenas criar métodos de conveniência, quando necessário (e quando fizer sentido).</li>
<li>Fuja dos callbacks do ActiveRecord, principalmente para realizar tarefas que não são relativas ao modelo (enviar e-mail, por exemplo, com o <code>after_create</code>).</li>
</ul>

<h2>Finalizando</h2>

<p>Testes rápidos não deve ser o seu objetivo final. Isso é apenas uma consequência de ter um código bem escrito, seguindo as <em>boas práticas de desenvolvimento de software</em> (piada que alguns amigos irão entender).</p>

<p><strong>Ouça sempre o que o seus testes estão dizendo</strong>. Se está muito difícil de testar, provavelmente sua classe/método está fazendo mais coisas do que deveria.</p>
]]>
      </description>
      <content:encoded>
        <![CDATA[<p>Vira e mexe mando uns tweets com o tempo de execução dos meus testes. Não que sejam absurdamente rápidos, mas muita gente andou me perguntando qual é a mágica.</p>

<p>Para você ter uma ideia, a API do <a href="http://codeplane.com.br">Codeplane</a> (que é o meu projeto atual), tem os seguintes tempos de execução:</p>
<pre class="language-text"><code>$ time rspec
Finished in 7.37 seconds
357 examples, 0 failures

real  0m21.159s
user  0m11.233s
sys 0m3.444s
</code></pre>
<p>Veja o tempo de execução apenas dos modelos (persistência com ActiveRecord e outras classes):</p>
<pre class="language-text"><code>$ time rspec spec/models/
Finished in 2.11 seconds
165 examples, 0 failures

real  0m4.023s
user  0m2.816s
sys 0m0.536s
</code></pre>
<p>E, por fim, todos os testes que não precisam do Rails:</p>
<pre class="language-text"><code>$ time rspec spec/{extensions,middlewares,models,rack,services,workers}
Finished in 2.46 seconds
237 examples, 0 failures

real  0m4.531s
user  0m3.080s
sys 0m0.664s
</code></pre>
<p>Nada mal. Neste artigo você poderá ver um pouco das coisas que faço para ter tempos como estes.</p>

<h2>Evite adicionar dependências</h2>

<p><strong>Dependência tem esse nome e não é por acaso.</strong> Pense duas vezes se você realmente precisa de todas aquelas gems que você está adicionando. Às vezes, algumas poucas linhas de código já podem resolver a coisa toda.</p>

<p>O boot do Rails não é lento. Um aplicativo novo, apenas com as dependências padrão, é executado em menos de 1.5s.</p>
<pre class="language-text"><code>$ time rails runner &#39;&#39;

real  0m1.316s
user  0m1.164s
sys 0m0.148s
</code></pre>
<p>O stack padrão tem 40 gems de dependência (uma das linhas é apenas uma descrição), como você pode ver abaixo:</p>
<pre class="language-text"><code>$ bundle show | wc -l
41
</code></pre>
<p>A API do Codeplane tem um tempo de boot três vezes maior, com quase o dobro de dependências.</p>
<pre class="language-text"><code>$ time rails runner &#39;&#39;

real  0m3.850s
user  0m2.732s
sys 0m0.468s

$ bundle show | wc -l
76
</code></pre>
<p>Todas as bibliotecas que você adicionar ao seu projeto precisarão ser carregadas de alguma forma. No caso do Bundler, a menos que você seja específico quanto a isso, elas serão carregadas no momento do boot, e cada dependência que você adicionar, irá aumentar o seu tempo. Por isso, conforme nossa aplicação vai crescendo, temos a sensação de que o Rails é lento.</p>

<p>Nem sempre conseguimos evitar uma nova dependência. Uma coisa que você pode fazer, sempre que possível, é postergar o carregamento da biblioteca no lugar onde ela será usada. Imagine que eu queira usar a gem <a href="http://rubygems.org/gems/permalink">permalink</a>. Esta gem, que é específica para o ActiveRecord, pode ser carregada no arquivo que irá usá-la. Primeiro, certifique-se de adicionar a opção <code>:require =&gt; false</code> no arquivo Gemfile. Depois, carregue-a no arquivo do modelo.</p>
<pre class="language-ruby"><code>require &quot;permalink&quot;

class Post &lt; ActiveRecord::Base
  permalink
end
</code></pre>
<h2>Isole seus testes</h2>

<p><strong>Você nem sempre precisa do Rails.</strong> Para ser mais específico, os únicos testes que devem depender do Rails são os de integração (no caso do RSpec, são aqueles testes full-stack, com requisições HTTP). Todos os outros podem (e devem) ser isolados. Só assim você conseguirá executá-los mais rapidamente.</p>

<p>Mas para que isso seja possível, você precisará fazer algumas coisas. Primeiro, evite fazer muitas coisas no controller, porque aí você não precisará carregar o Rails para começo de conversa. A minha linha de raciocínio é bastante simples:</p>

<ul>
<li>Se eu vou apenas fazer uma consulta no ActiveRecord, por exemplo, eu faço diretamente no controller (obviamente, consultas complexas devem ser abstraídas em métodos no próprio modelo e/ou classes auxiliares).</li>
<li>Se eu precisar fazer qualquer tarefa adicional como enviar um e-mail ou executar alguma coisa no background, crio uma classe que fará isso.</li>
</ul>

<p>A primeira regra é aplicada no exemplo abaixo, onde apenas pego uma lista de repositórios de um dado usuário:</p>
<pre class="language-ruby"><code>class ReposController &lt; ApplicationController
  def index
    @repos = current_user.repos
    respond_with @repos
  end
end
</code></pre>
<p>No caso de um cadastro de usuário, onde um e-mail precisará ser enviado (assincronamente), eu teria que aplicar a segunda regra, como no exemplo abaixo:</p>
<pre class="language-ruby"><code>class UsersController &lt; ApplicationController
  def new
    @user = User.new
  end

  def create
    @user = User.create(params[:user])
    Signup.process(@user)

    respond_with @user, :location =&gt; login_path
  end
end
</code></pre>
<p>A classe <code>Signup</code> é responsável por adicionar o job que será executado assincronamente. Isso é importante, pois agora você consegue escrever testes específicos para a classe <code>Signup</code>, sem precisar bater, necessariamente, no controller ou mesmo no Rails.</p>

<p>Uma implementação possível dessa classe pode ser vista abaixo:</p>
<pre class="language-ruby"><code>class Signup
  def self.process(user)
    new(user).process
  end

  def initialize(user)
    @user = user
  end

  def mailer_worker
    MailerWorker
  end

  def process
    return if @user.errors.any?

    mailer_worker.enqueue(
      :name =&gt; @user.name,
      :email =&gt; @user.email,
      :mail =&gt; :welcome
    )
  end
end
</code></pre>
<p>Isso introduz o conceito de PORO (Plain-Old Ruby Object), ou seja, uma classe pura de Ruby que serve como um serviço. Perceba que a minha dependência está definida no método <code>Signup#mailer_worker</code>, em vez de passar como um parâmetro para o método <code>Signup#process</code>. Prefiro fazer desta forma porque acho mais clara.</p>

<p>E quanto aos testes?</p>
<pre class="language-ruby"><code>require &quot;./app/models/signup&quot;

describe Signup do
  describe &quot;#mailer_worker&quot; do
    let(:worker) { mock(&quot;MailerWorker&quot;) }

    it &quot;returns MailerWorker&quot; do
      stub_const &quot;MailerWorker&quot;, worker
      expect(Signup.new(nil).mailer_worker).to eql(worker)
    end
  end

  describe &quot;#process&quot; do
    let(:worker) { mock(&quot;MailerWorker&quot;) }
    let(:user) { mock(&quot;user&quot;) }

    before do
      Signup.any_instance.stub :mailer_worker =&gt; worker
    end

    context &quot;when user is valid&quot; do
      before do
        user.stub({
          :errors =&gt; [],
          :name =&gt; &quot;NAME&quot;,
          :email =&gt; &quot;EMAIL&quot;
        })
      end

      it &quot;enqueues e-mail&quot; do
        worker
          .should_receive(:enqueue)
          .with({
            :name =&gt; &quot;NAME&quot;,
            :email =&gt; &quot;EMAIL&quot;,
            :mail =&gt; :welcome
          })

        Signup.new(user).process
      end
    end

    context &quot;when user is invalid&quot; do
      before do
        user.stub :errors =&gt; [&quot;ERROR&quot;]
      end

      it &quot;does not enqueue e-mail&quot; do
        worker.should_not_receive(:enqueue)
        Signup.new(user).process
      end
    end
  end
end
</code></pre>
<p>Muita gente não gosta dessa abordagem com mocks e stubs. Particularmente, não vejo problemas, já que sempre tenho testes de integração que irão garantir o funcionamento desta classe no seu uso real e integrado ao sistema.</p>

<p>Perceba que não estou carregando o arquivo &quot;spec_helper.rb&quot;, como fazemos normalmente. Isso porque, neste exemplo, não precisamos de nada do Rails. Então, não faz o menor sentido você carregar o Rails inteiro apenas para rodar estes testes. Veja como eles rodam <strong>muito</strong> rápido:</p>
<pre class="language-text"><code>$ time rspec signup_spec.rb
...

Finished in 0.00727 seconds
3 examples, 0 failures

real  0m0.259s
user  0m0.196s
sys 0m0.024s
</code></pre>
<p>Claro que nem sempre é possível fugir do Rails. Será? Executar testes do ActiveRecord normalmente exigiriam coisas do Rails, mas podemos isolar o carregamento somente das dependências do ActiveRecord em um arquivo diferente do &quot;spec_helper.rb&quot;.</p>

<p>Primeiro crie um arquivo &quot;spec/spec_helper_active_record.rb&quot;. Este arquivo irá carregar o Bundler e definir o escopo de dependências, mas não irá carregar as bibliotecas automaticamente. No exemplo abaixo irei carregar o ActiveRecord, <a href="http://rubygems.org/gems/factory_girl">FactoryGirl</a>, <a href="http://rubygems.org/gems/factory_girl-preload">FactoryGirl Preload</a>, o matcher <code>have(n).errors_on</code>, presente no <a href="http://rubygems.org/gems/rspec-rails">rspec-rails</a>, além de fazer a conexão com o banco de dados.</p>
<pre class="language-ruby"><code>require &quot;bundler&quot;
Bundler.setup(:default, :test)

require &quot;active_record&quot;

require &quot;rspec/matchers&quot;
require &quot;rspec/rails/extensions/active_record/base&quot;
require &quot;rspec/rails/matchers/have_extension&quot;

require &quot;factory_girl&quot;
require &quot;factory_girl/preload&quot;
require &quot;factory_girl/preload/rspec2&quot;

connection_info = YAML.load_file(&quot;config/database.yml&quot;)[&quot;test&quot;]
ActiveRecord::Base.establish_connection(connection_info)
</code></pre>
<p>Todas as gems específicas do ActiveRecord que você usa devem ser carregadas neste arquivo também.</p>

<p>Agora, no arquivo de testes do seu modelo, você irá carregar este arquivo e o modelo que você quer testar. Veja, por exemplo, como seria para testar as validações de um modelo <code>User</code>.</p>
<pre class="language-ruby"><code>require &quot;spec_helper_active_record&quot;
require &quot;./app/models/user&quot;

describe User do
  context &quot;validations&quot; do
    it &quot;requires name&quot; do
      user = User.create(:name =&gt; nil)
      expect(user).to have(1).error_on(:name)
    end
  end
end
</code></pre>
<p>Com esta alteração, eu consegui reduzir o tempo de execução do diretório &quot;spec/models&quot; consideravelmente:</p>
<pre class="language-text"><code>$ time rspec spec/models/
147 examples, 0 failures

# Antes da alteração
real0m11.537s
user0m6.652s
sys0m1.740s

# Depois da alteração
real0m3.688s
user0m2.672s
sys0m0.452s
</code></pre>
<p>E por falar em ActiveRecord, aqui vão mais algumas dicas.</p>

<ul>
<li>Evite criar registros quando você não precisa. Muitas vezes instanciar o modelo já é suficiente. Se for realmente necessário criar estes registros, não crie mais do que precisa.</li>
<li>Sempre que puder, utilize fixtures ou algo equivalente. Eu sempre adiciono a minha gem <a href="http://rubygems.org/gems/factory_girl-preload">factory_girl-preload</a>, e defino alguns registros que uso em todos os lugares (como uma instância da classe <code>User</code>).</li>
<li>Esqueça a ideia de Fat Model literal (um único modelo, inchado de métodos não relacionados). Você pode delegar regras de negócio para classes separadas e apenas criar métodos de conveniência, quando necessário (e quando fizer sentido).</li>
<li>Fuja dos callbacks do ActiveRecord, principalmente para realizar tarefas que não são relativas ao modelo (enviar e-mail, por exemplo, com o <code>after_create</code>).</li>
</ul>

<h2>Finalizando</h2>

<p>Testes rápidos não deve ser o seu objetivo final. Isso é apenas uma consequência de ter um código bem escrito, seguindo as <em>boas práticas de desenvolvimento de software</em> (piada que alguns amigos irão entender).</p>

<p><strong>Ouça sempre o que o seus testes estão dizendo</strong>. Se está muito difícil de testar, provavelmente sua classe/método está fazendo mais coisas do que deveria.</p>
]]>
      </content:encoded>
      <link>http://simplesideias.com.br/fazendo-os-seus-testes-executarem-mais-rapido</link>
      <guid>http://simplesideias.com.br/fazendo-os-seus-testes-executarem-mais-rapido</guid>
      <pubDate>Sun, 30 Dec 2012 20:57:00 -0200</pubDate>
    </item>
  </channel>
</rss>
