<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>ASCIIcasts - Full Episode Feed</title>
    <description>The latest episodes from ASCIIcasts</description>
    <link>http://asciicasts.com/</link>
    <pubDate>Mon, 08 Aug 2011 19:48:10 +0000</pubDate>
    <ttl>1440</ttl>
    <item>
      <title>Gravatar</title>
      <description>&lt;p&gt;Atualmente avatars s&amp;atilde;o muito importantes, especialmente em aplica&amp;ccedil;&amp;otilde;es sociais. Se voc&amp;ecirc; quer adicionar imagens de avatar para alguma aplica&amp;ccedil;&amp;atilde;o, voc&amp;ecirc; deve dar uma olhada no &lt;a href="http://en.gravatar.com"&gt;Gravatar&lt;/a&gt;, que fornece uma maneira interessante de fazer isso. Tudo que voc&amp;ecirc; precisa &amp;eacute; de um endere&amp;ccedil;o de email para cada usu&amp;aacute;rio, e assim n&amp;atilde;o h&amp;aacute; necessidade da sua aplica&amp;ccedil;&amp;atilde;o tratar arquivos anexos, crop de imagens, ou se preocupar se os usu&amp;aacute;rios est&amp;atilde;o fazendo upload de imagens inapropriadas, pois isso &amp;eacute; feito pelo Gravatar. Apenas forne&amp;ccedil;a um endere&amp;ccedil;o de email para o avatar do usu&amp;aacute;rio ser&amp;aacute; fornecido.&lt;/p&gt;

&lt;p&gt;Vamos adicionar o Gravatar em uma simples aplica&amp;ccedil;&amp;atilde;o Rails com um modelo &lt;code&gt;User&lt;/code&gt;. Ela tem atualmente tr&amp;ecirc;s usu&amp;aacute;rios, cada um com um diferente endere&amp;ccedil;o de email e a p&amp;aacute;gina  &lt;code&gt;index&lt;/code&gt; mostra uma coluna &lt;code&gt;avatar&lt;/code&gt; com &amp;quot;TODO&amp;quot;.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/531/original/E244I01.png" width="800" height="347" alt="The users page of our application."/&gt;
&lt;/div&gt;

&lt;p&gt;Existem muitos plugins dispon&amp;iacute;veis para adicionar o Gravatar ao Rails, mas &amp;eacute; t&amp;atilde;o f&amp;aacute;cil fazer isso do zero que n&amp;oacute;s n&amp;atilde;o queremos usar um plugin. Vamos come&amp;ccedil;ar modificando a view que renderiza a tabela mostrada acima. A view est&amp;aacute; assim:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/views/users/index.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;&amp;lt;% for user in @users %&amp;gt;
  &amp;lt;tr&amp;gt;
    &amp;lt;td&amp;gt;TODO&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%= user.email %&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%= link_to &amp;quot;Show&amp;quot;, user %&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%= link_to &amp;quot;Edit&amp;quot;, edit_user_path(user) %&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%= link_to &amp;quot;Destroy&amp;quot;, user, :confirm =&amp;gt; &amp;#x27;Are you &amp;crarr;
      sure?&amp;#x27;, :method =&amp;gt; :delete %&amp;gt;&amp;lt;/td&amp;gt;
  &amp;lt;/tr&amp;gt;
&amp;lt;% end %&amp;gt;&lt;/pre&gt;

&lt;p&gt;Vamos substituir o texto TODO, na primeira c&amp;eacute;lula da tabela, com uma &lt;code&gt;image_tag&lt;/code&gt;. A url da imagem ser&amp;aacute; gerada por um m&amp;eacute;todo helper, que vamos escrever, chamado &lt;code&gt;avatar_url&lt;/code&gt;. Ele recebe um usu&amp;aacute;rio como par&amp;acirc;metro.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/views/users/index.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;&amp;lt;% for user in @users %&amp;gt;
  &amp;lt;tr&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%= image_tag avatar_url(user) %&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%= user.email %&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%= link_to &amp;quot;Show&amp;quot;, user %&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%= link_to &amp;quot;Edit&amp;quot;, edit_user_path(user) %&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%= link_to &amp;quot;Destroy&amp;quot;, user, :confirm =&amp;gt; &amp;#x27;Are you &amp;crarr;
      sure?&amp;#x27;, :method =&amp;gt; :delete %&amp;gt;&amp;lt;/td&amp;gt;
  &amp;lt;/tr&amp;gt;
&amp;lt;% end %&amp;gt;&lt;/pre&gt;

&lt;p&gt;Agora vamos escrever o m&amp;eacute;todo &lt;code&gt;avatar_url&lt;/code&gt; no &lt;code&gt;ApplicationHelper&lt;/code&gt;. O &amp;uacute;nico truque &amp;eacute; a gera&amp;ccedil;&amp;atilde;o do id que o Gravatar espera. O id &amp;eacute; um hash MD5 em min&amp;uacute;sculas do endere&amp;ccedil;o de email do usu&amp;aacute;rio, o que &amp;eacute; bastante simples.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/helpers/application_helper.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;module ApplicationHelper
  def avatar_url(user)
    gravatar_id = Digest::MD5::hexdigest(user.email).downcase
    &amp;quot;http://gravatar.com/avatar/#{gravatar_id}.png&amp;quot;
  end
end&lt;/pre&gt;

&lt;p&gt;Quando recarregarmos a p&amp;aacute;gina agora, vamos ver as imagens dos avatars para as duas contas que tem imagens do Gravatar associadas a elas. Para a que n&amp;atilde;o tem, vamos ver uma imagem padr&amp;atilde;o do Gravatar.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/532/original/E244I02.png" width="800" height="539" alt="Images from Gravatar are now shown."/&gt;
&lt;/div&gt;

&lt;h3&gt;Customizando imagens do Gravatar&lt;/h3&gt;

&lt;p&gt;Existem alguns par&amp;acirc;metros que podem ser passados na url do Gravatar para customizar seu comportamento e mais detalhes podem ser encontrados no &lt;a href="http://en.gravatar.com/site/implement/images"&gt;site do Gravatar&lt;/a&gt;. Passando, por exemplo, o par&amp;acirc;metro &lt;code&gt;s&lt;/code&gt;, vamos mudar o tamanho do avatar, assim:&lt;/p&gt;

&lt;pre class="ruby"&gt;http://gravatar.com/avatar/9a295994737a47683a4da4ed47aef7dd.png?s=200&lt;/pre&gt;

&lt;p&gt;A op&amp;ccedil;&amp;atilde;o &lt;code&gt;d&lt;/code&gt; pode ser usada para fornecer uma imagem alternativa, se n&amp;atilde;o for encontrado um avatar para o usu&amp;aacute;rio.&lt;/p&gt;

&lt;pre class="ruby"&gt;http://gravatar.com/avatar/84ce1adb94b67014236a909fa4c1269d.png?d=http%3A%2F%2Fasciicasts.com%2Fimages%2Frails.png&lt;/pre&gt;

&lt;p&gt;Podemos passar a op&amp;ccedil;&amp;atilde;o &lt;code&gt;r&lt;/code&gt; para mudar a classifica&amp;ccedil;&amp;atilde;o e se o seu site usa HTTPS, ent&amp;atilde;o podemos obter imagens com seguran&amp;ccedil;a usando o endere&amp;ccedil;o &lt;code&gt;https://secure.gravatar.com/&lt;/code&gt;. Vamos usar algumas dessas op&amp;ccedil;&amp;otilde;es para redimensionar os avatars para 48 pixels, assim como o Twitter usa, e para fornecer uma imagem alternativa diferente.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/application/helpers/application_helper.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;module ApplicationHelper
  def avatar_url(user)
    default_url = &amp;quot;#{root_url}images/guest.png&amp;quot;
    gravatar_id = Digest::MD5::hexdigest(user.email).downcase
    &amp;quot;http://gravatar.com/avatar/#{gravatar_id}.png?s=48&amp;amp;d=#{CGI.escape(default_url)}&amp;quot;
  end
end&lt;/pre&gt;

&lt;p&gt;Quando recarregarmos a p&amp;aacute;gina agora, as imagens estar&amp;atilde;o menores e nossa imagem padr&amp;atilde;o customizada ser&amp;aacute; mostrada para a conta que n&amp;atilde;o tem uma imagem no Gravatar.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/533/original/E244I03.png" width="800" height="442" alt="Our custom default avatar is now shown."/&gt;
&lt;/div&gt;

&lt;h3&gt;Usando imagens de outros sites com OmniAuth&lt;/h3&gt;

&lt;p&gt;Essa solu&amp;ccedil;&amp;atilde;o de avatar funciona especialmente quando est&amp;aacute; junto com o OmniAuth. Se voc&amp;ecirc; n&amp;atilde;o est&amp;aacute; familiarizado com o OmniAuth, o epis&amp;oacute;dio 241 [&lt;a href="http://railscasts.com/episodes/241-simple-omniauth"&gt;assistir&lt;/a&gt;, &lt;a href="http://asciicasts.com/episodes/241-simple-omniauth"&gt;ler&lt;/a&gt;] aborda como us&amp;aacute;-lo em uma aplica&amp;ccedil;&amp;atilde;o Rails. O motivo do OmniAuth funcionar bem aqui &amp;eacute; que se um usu&amp;aacute;rio entrar no seu site atrav&amp;eacute;s do Facebook ou Twitter, ent&amp;atilde;o ele j&amp;aacute; ter&amp;aacute; um avatar desses servi&amp;ccedil;os e ela pode ser obtida da propriedade &lt;code&gt;image&lt;/code&gt; do hash &lt;code&gt;user_info&lt;/code&gt; que o OmniAuth retorna. Se um usu&amp;aacute;rio n&amp;atilde;o entrou atrav&amp;eacute;s de um desses servi&amp;ccedil;os, ent&amp;atilde;o podemos usar o Gravatar como uma alternativa, para que cada usu&amp;aacute;rio sempre tenha um avatar.&lt;/p&gt;

&lt;p&gt;N&amp;atilde;o vamos adicionar o OmniAuth nessa aplica&amp;ccedil;&amp;atilde;o, mas vamos adicionar um campo &lt;code&gt;avatar_url&lt;/code&gt; ao nosso modelo &lt;code&gt;User&lt;/code&gt; para simular essa parte dos dados do OmniAuth. Primeiro vamos modificar um dos usu&amp;aacute;rios para adicionar o avatar do Twitter.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/534/original/E244I04.png" width="801" height="351" alt="Adding an avatar_url to a user."/&gt;
&lt;/div&gt;

&lt;p&gt;Depois vamos modificar nosso &lt;code&gt;avatar_url&lt;/code&gt; no &lt;code&gt;ApplicationHelper&lt;/code&gt; para que ele use o avatar j&amp;aacute; armazenado, se ele existir.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/helpers/application_helper.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;module ApplicationHelper
  def avatar_url(user)
    if user.avatar_url.present?
      user.avatar_url
    else
      default_url = &amp;quot;#{root_url}images/guest.png&amp;quot;
      gravatar_id = Digest::MD5::hexdigest(user.email).downcase
      &amp;quot;http://gravatar.com/avatar/#{gravatar_id}.png?s=48&amp;amp;d=#{CGI.escape(default_url)}&amp;quot;
    end
  end
end&lt;/pre&gt;

&lt;p&gt;Quando recarregamos a p&amp;aacute;gina, o usu&amp;aacute;rio que tiver um avatar armazenado, ser&amp;aacute; mostrado. Para os outros, ainda pegaremos do Gravatar.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/535/original/E244I05.png" width="802" height="468" alt="The avatar from Twitter is now shown."/&gt;
&lt;/div&gt;

&lt;p&gt;&amp;Eacute; isso. Foi r&amp;aacute;pido mas espero que tenha abordado tudo para voc&amp;ecirc; usar avatar nas suas aplica&amp;ccedil;&amp;otilde;es Rails.&lt;/p&gt;
</description>
      <pubDate>Fri, 17 Dec 2010 00:08:07 +0000</pubDate>
      <guid>http://pt.asciicasts.com/episodes/244-gravatar</guid>
      <link>http://pt.asciicasts.com/episodes/244-gravatar</link>
    </item>
    <item>
      <title>Beanstalkd e Stalker</title>
      <description>&lt;p&gt;No &lt;a href="http://railsrumble.com/"&gt;Rails Rumble&lt;/a&gt; desse ano, Ryan Bates e sua equipe criaram o site &lt;a href="http://govsgo.com/"&gt;Go vs Go&lt;/a&gt;, onde voc&amp;ecirc; pode jogar Go (um jogo de tabuleiro) online. No site, voc&amp;ecirc; pode jogar contra outro jogador ou contra o computador. Quando voc&amp;ecirc; joga contra o computador, h&amp;aacute; um pequeno atraso ap&amp;oacute;s voc&amp;ecirc; mover sua pedra at&amp;eacute; o computador mover a dele. Isso acontece enquanto o computador  calcula o seu movimento e, por padr&amp;atilde;o, prende um processo do Rails. Para evitar esse problema, a IA do jogo foi movida para um processo em segundo plano. Existem algumas maneiras de agendar processos em aplica&amp;ccedil;&amp;otilde;es Rails, e a equipe do Go vs Go escolheu usar o &lt;a href="http://kr.github.com/beanstalkd/"&gt;beanstalkd&lt;/a&gt;. Nesse epis&amp;oacute;dio vamos dar uma olhada no beanstalkd e na gem Stalker.&lt;/p&gt;

&lt;h3&gt;Come&amp;ccedil;ando com Beanstalkd&lt;/h3&gt;

&lt;p&gt;Se voc&amp;ecirc; est&amp;aacute; no OSX, h&amp;aacute; uma maneira f&amp;aacute;cil de instalar o beanstalkd, que &amp;eacute; atrav&amp;eacute;s do &lt;a href="http://github.com/mxcl/homebrew"&gt;Homebrew&lt;/a&gt;. Nesse caso, voc&amp;ecirc; s&amp;oacute; precisa executar:&lt;/p&gt;

&lt;pre class="terminal"&gt;$ brew install beanstalkd&lt;/pre&gt;

&lt;p&gt;Depois de instalado, podemos iniciar o servidor do Beanstalkd executando o comando &lt;code&gt;beanstalkd&lt;/code&gt;. Para executar como um processo daemon, podemos adicionar a op&amp;ccedil;&amp;atilde;o &lt;code&gt;-d&lt;/code&gt;.&lt;/p&gt;

&lt;pre class="terminal"&gt;$ beanstalkd -d&lt;/pre&gt;

&lt;p&gt;Para usar o Beanstalkd com Ruby vamos precisar instalar a gem &lt;a href="http://rubygems.org/gems/beanstalk-client"&gt;beanstalk-clienk&lt;/a&gt;.&lt;/p&gt;

&lt;pre class="terminal"&gt;$ gem install beanstalk-client&lt;/pre&gt;

&lt;p&gt;H&amp;aacute; instru&amp;ccedil;&amp;otilde;es de como usar o Beanstalk com Ruby no &lt;a href="http://kr.github.com/beanstalkd/"&gt;site do Beanstalkd&lt;/a&gt;. Precisamos criar um novo &lt;code&gt;Beanstalk::Pool&lt;/code&gt; e usar seu m&amp;eacute;todo &lt;code&gt;put&lt;/code&gt; para adicionar uma tarefa na fila. E para trazer um item da fila, usamos o m&amp;eacute;todo &lt;code&gt;reserve&lt;/code&gt;. Ele ir&amp;aacute; aguardar at&amp;eacute; uma tarefa estar dispon&amp;iacute;vel na fila e ent&amp;atilde;o ir&amp;aacute; retorn&amp;aacute;-la. Podemos assim processar a tarefa e ent&amp;atilde;o usar delete para remov&amp;ecirc;-la da fila.&lt;/p&gt;

&lt;p&gt;Vamos demonstrar isso em duas sess&amp;otilde;es &lt;code&gt;irb&lt;/code&gt;. Em cada uma vamos criar um novo pool do Beanstalk em &lt;code&gt;localhost:11300&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;Top Window&lt;/p&gt;
&lt;pre class="terminal"&gt;$ irb
ruby-1.9.2-p0 &amp;gt; require &amp;#x27;beanstalk-client&amp;#x27;
 =&amp;gt; true 
ruby-1.9.2-p0 &amp;gt; beanstalk = Beanstalk::Pool.new([&amp;#x27;localhost:11300&amp;#x27;])
 =&amp;gt; #&amp;lt;Beanstalk::Pool:0x00000100a9f8e8 @addrs=[&amp;quot;localhost:11300&amp;quot;], @watch_list=[&amp;quot;default&amp;quot;], @default_tube=nil, @connections={&amp;quot;localhost:11300&amp;quot;=&amp;gt;#&amp;lt;Beanstalk::Connection:0x00000100a9f7f8 @mutex=#&amp;lt;Mutex:0x00000100a9f780&amp;gt;, @waiting=false, @addr=&amp;quot;localhost:11300&amp;quot;, @socket=#&amp;lt;TCPSocket:fd 3&amp;gt;, @last_used=&amp;quot;default&amp;quot;, @watch_list=[&amp;quot;default&amp;quot;]&amp;gt;}&amp;gt; 
ruby-1.9.2-p0 &amp;gt;&lt;/pre&gt;

&lt;p class="codeFilePath"&gt;Bottom Window&lt;/p&gt;
&lt;pre class="terminal"&gt;$ irb
ruby-1.9.2-p0 &amp;gt; require &amp;#x27;beanstalk-client&amp;#x27;
 =&amp;gt; true 
ruby-1.9.2-p0 &amp;gt; beanstalk = Beanstalk::Pool.new([&amp;#x27;localhost:11300&amp;#x27;])
 =&amp;gt; #&amp;lt;Beanstalk::Pool:0x00000101919bf8 @addrs=[&amp;quot;localhost:11300&amp;quot;], @watch_list=[&amp;quot;default&amp;quot;], @default_tube=nil, @connections={&amp;quot;localhost:11300&amp;quot;=&amp;gt;#&amp;lt;Beanstalk::Connection:0x00000101919978 @mutex=#&amp;lt;Mutex:0x000001019198d8&amp;gt;, @waiting=false, @addr=&amp;quot;localhost:11300&amp;quot;, @socket=#&amp;lt;TCPSocket:fd 3&amp;gt;, @last_used=&amp;quot;default&amp;quot;, @watch_list=[&amp;quot;default&amp;quot;]&amp;gt;}&amp;gt; 
ruby-1.9.2-p0 &amp;gt;&lt;/pre&gt;

&lt;p&gt;Vamos adicionar uma tarefa na fila na janela superior, usando o &lt;code&gt;put&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;Top Window&lt;/p&gt;
&lt;pre class="erb"&gt;ruby-1.9.2-p0 &amp;gt; beanstalk.put &amp;quot;hello&amp;quot;
 =&amp;gt; 1&lt;/pre&gt;

&lt;p&gt;Na outra janela, vamos trazer aquela tarefa com &lt;code&gt;reserve&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;Bottom Window&lt;/p&gt;
&lt;pre class="erb"&gt;ruby-1.9.2-p0 &amp;gt; job = beanstalk.reserve
 =&amp;gt; (job server=localhost:11300 id=1 size=5)&lt;/pre&gt;

&lt;p&gt;Podemos ent&amp;atilde;o ver o &lt;code&gt;body&lt;/code&gt; da tarefa e apag&amp;aacute;-la da fila.&lt;/p&gt;
 
&lt;p class="codeFilePath"&gt;Bottom Window&lt;/p&gt;
&lt;pre class="erb"&gt;ruby-1.9.2-p0 &amp;gt; job.body
 =&amp;gt; &amp;quot;hello&amp;quot; 
ruby-1.9.2-p0 &amp;gt; job.delete
 =&amp;gt; false&lt;/pre&gt;

&lt;p&gt;Se tentarmos dar &lt;code&gt;reserve&lt;/code&gt; em outra tarefa agora, o comando vai aguardar, pois n&amp;atilde;o h&amp;aacute; tarefas na fila.&lt;/p&gt;
 
&lt;p class="codeFilePath"&gt;Bottom Window&lt;/p&gt;
&lt;pre class="erb"&gt;ruby-1.9.2-p0 &amp;gt; job = beanstalk.reserve&lt;/pre&gt;

&lt;p&gt;Agora que adicionamos outra tarefa, ela ser&amp;aacute; retornada imediatamente.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;Top Window&lt;/p&gt;
&lt;pre class="erb"&gt;ruby-1.9.2-p0 &amp;gt; beanstalk.put &amp;quot;bacon&amp;quot;
 =&amp;gt; 2&lt;/pre&gt;
 
&lt;p class="codeFilePath"&gt;Bottom Window&lt;/p&gt;
&lt;pre class="erb"&gt;ruby-1.9.2-p0 &amp;gt; job = beanstalk.reserve
 =&amp;gt; (job server=localhost:11300 id=2 size=5)&lt;/pre&gt;

&lt;p&gt;A nova tarefa &amp;eacute; processada imediatamente. Isso ajuda na resposta do Go vs Go, pois significa que o computador vai responder assim que poss&amp;iacute;vel.&lt;/p&gt;
 
&lt;h3&gt;Usando o Beanstalk em uma aplica&amp;ccedil;&amp;atilde;o Rails&lt;/h3&gt;

&lt;p&gt;Vamos ver como usar o Beanstalkd em uma aplica&amp;ccedil;&amp;atilde;o Rails. Temos uma aplica&amp;ccedil;&amp;atilde;o simples que nos permite criar cidades. Tudo que precisamos fazer &amp;eacute; fornecer um c&amp;oacute;digo postal e uma cidade ser&amp;aacute; criada. O nome da cidade vir&amp;aacute; de um site externo.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/528/original/E243I01.png" width="800" height="348" alt="Our Rails application."/&gt;
&lt;/div&gt;

&lt;p&gt;Embora trazer o nome da cidade seja geralmente uma chamada r&amp;aacute;pida, uma requisi&amp;ccedil;&amp;atilde;o separada pode ser lenta, por isso vamos mov&amp;ecirc;-la para um processo em segundo plano.&lt;/p&gt;

&lt;p&gt;Antes estavamos usando a gem Beanstalk client diretamente, mas em uma aplica&amp;ccedil;&amp;atilde;o Rails vamos usar outra gem chamada &lt;a href="https://github.com/adamwiggins/stalker"&gt;Stalker&lt;/a&gt;. Ela usa a gem cliente e fornece uma interface melhor para trabalhar. Para usar o Stalker em nossa aplica&amp;ccedil;&amp;atilde;o Rails, s&amp;oacute; precisamos adicion&amp;aacute;-la ao &lt;code&gt;Gemfile&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/Gemfile&lt;/p&gt;
&lt;pre class="ruby"&gt;source &amp;#x27;http://rubygems.org&amp;#x27;

gem &amp;#x27;rails&amp;#x27;, &amp;#x27;3.0.3&amp;#x27;
gem &amp;#x27;nifty-generators&amp;#x27;
gem &amp;#x27;sqlite3-ruby&amp;#x27;, :require =&amp;gt; &amp;#x27;sqlite3&amp;#x27;
gem &amp;#x27;stalker&amp;#x27;&lt;/pre&gt;

&lt;p&gt;E vamos instalar executando o &lt;code&gt;bundle&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Podemos agora mover o c&amp;oacute;digo que traz os nomes das cidades para um processo separado em segundo plano. A action &lt;code&gt;create&lt;/code&gt; atualmente salva a nova cidade e ent&amp;atilde;o chama um m&amp;eacute;todo do modelo &lt;code&gt;City&lt;/code&gt; chamado &lt;code&gt;fetch_name&lt;/code&gt; para determinar o nome da cidade. Esse m&amp;eacute;todo chama uma API externa que traz o nome da cidade. &amp;Eacute; isso que queremos mover para um processo em segundo plano.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controllers/cities_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;def create
  @city = City.new(params[:city])
  if @city.save
    @city.fetch_name
    redirect_to city_path(@city), :notice =&amp;gt; &amp;quot;Successfully &amp;crarr;
      created city.&amp;quot;
  else
    render :action =&amp;gt; &amp;#x27;new&amp;#x27;
  end
end&lt;/pre&gt;

&lt;p&gt;Vamos modificar o c&amp;oacute;digo para que, em vez de chamar &lt;code&gt;@city.fetch_name&lt;/code&gt;, ele adicione uma tarefa na nossa fila. Podemos fazer isso chamando &lt;code&gt;Stalker.enqueue&lt;/code&gt;. Precisamos dar um identificador para a nova tarefa, ent&amp;atilde;o vamos cham&amp;aacute;-la de &lt;code&gt;city.fetch_name&lt;/code&gt;. Podemos tamb&amp;eacute;m passar op&amp;ccedil;&amp;otilde;es para a tarefa; vamos passar o &lt;code&gt;id&lt;/code&gt; da cidade que acabamos de salvar.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controllers/cities_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;def create
  @city = City.new(params[:city])
  if @city.save
    Stalker.enqueue(&amp;quot;city.fetch_name&amp;quot;, :id =&amp;gt; @city.id)
    redirect_to city_path(@city), :notice =&amp;gt; &amp;quot;Successfully &amp;crarr;
      created city.&amp;quot;
  else
    render :action =&amp;gt; &amp;#x27;new&amp;#x27;
  end
end&lt;/pre&gt;

&lt;p&gt;Agora precisamos criar uma nova tarefa Stalker para lidar com isso. Podemos em qualquer lugar na nossa aplica&amp;ccedil;&amp;atilde;o Rails; vamos criar no diret&amp;oacute;rio &lt;code&gt;config&lt;/code&gt;, um arquivo chamado &lt;code&gt;jobs.rb&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Stalker tem uma API simples para gerenciamento de tarefas. Tudo que precisamos fazer &amp;eacute; chamar o m&amp;eacute;todo &lt;code&gt;job&lt;/code&gt; e passar um identificador. Esse m&amp;eacute;todo tamb&amp;eacute;m recebe um bloco, que tem como argumentos, os argumentos passados para o &lt;code&gt;Stalker.enqueue&lt;/code&gt; anteriormente. Nesse bloco, pegamos a cidade com o id correto e chamamos o m&amp;eacute;todo &lt;code&gt;fetch_name&lt;/code&gt;. O Stalker n&amp;atilde;o carrega o ambiente do Rails por padr&amp;atilde;o, por isso &amp;eacute; necess&amp;aacute;rio dar &lt;code&gt;require&lt;/code&gt; no arquivo &lt;code&gt;config/environment.rb&lt;/code&gt; na primeira linha do c&amp;oacute;digo abaixo:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/config/jobs.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;require File.expand_path(&amp;quot;../environment&amp;quot;, __FILE__)

job &amp;quot;city.fetch_name&amp;quot; do |args|
  City.find(args[&amp;quot;id&amp;quot;]).fetch_name
end&lt;/pre&gt;

&lt;p&gt;Podemos executar nossas tarefas executando o comando &lt;code&gt;stalk&lt;/code&gt; passando o nome do arquivo que queremos executar.&lt;/p&gt;

&lt;pre class="terminal"&gt;$ stalk ./config/jobs.rb&lt;/pre&gt;
  
&lt;p&gt;Temos o Beanstalkd executando. Se criarmos uma nova cidade, seu nome ficar&amp;aacute; em branco.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/529/original/E243I02.png" width="802" height="343" alt="The new city has a blank name."/&gt;
&lt;/div&gt;

&lt;p&gt;Quando recarregamos a p&amp;aacute;gina algumas vezes, o nome aparece.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/530/original/E243I03.png" width="802" height="343" alt="The city name appears when we refresh the page."/&gt;
&lt;/div&gt;

&lt;p&gt;Isso mostra que a tarefa est&amp;aacute; sendo processada com sucesso em segundo plano. Se olharmos o log, vamos ver a tarefa listada.&lt;/p&gt;

&lt;pre class="terminal"&gt;[2010-12-09 19:04:49 +0000] -&amp;gt; city.fetch_name (id=2)
[2010-12-09 19:04:50 +0000] -&amp;gt; city.fetch_name finished in 374ms&lt;/pre&gt;

&lt;h3&gt;Otimizando o processo em segundo plano&lt;/h3&gt;

&lt;p&gt;Um problema da nossa tarefa &amp;eacute; que ela est&amp;aacute; carregando todo o ambiente Rails. Se tivermos v&amp;aacute;rios processos para lidar com as tarefas, isso vai nos levar a um gasto muito grande de mem&amp;oacute;ria. Ter o ambiente Rails dispon&amp;iacute;vel n&amp;atilde;o &amp;eacute; necess&amp;aacute;rio e podemos fazer o processo mais eficiente sem ele. Para fazer isso, vamos alterar a tarefa para ela acessar o banco de dados sem o ActiveRecord.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/config/jobs.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;require &amp;#x27;sqlite3&amp;#x27;
require &amp;#x27;json&amp;#x27;
require &amp;#x27;net/http&amp;#x27;

RAILS_ENV = ENV[&amp;quot;RAILS_ENV&amp;quot;] || &amp;quot;development&amp;quot;

db = SQLite3::Database.new(File.expand_path( &amp;crarr;
  &amp;quot;../../db/#{RAILS_ENV}.sqlite3&amp;quot;, __FILE__))

job &amp;quot;city.fetch_name&amp;quot; do |args|
  postcode = db.get_first_value(&amp;quot;SELECT postcode FROM &amp;crarr;
    cities WHERE id=?&amp;quot;, args[&amp;quot;id&amp;quot;])
  url = &amp;quot;http://ws.geonames.org/postalCodeLookupJSON?  &amp;crarr;
    postalcode=#{CGI.escape(postcode)}&amp;amp;country=GB&amp;quot;
  json = Net::HTTP.get_response(URI.parse(url)).body
  name = JSON.parse(json)[&amp;quot;postalcodes&amp;quot;].first[&amp;quot;placeName&amp;quot;]
  db.execute(&amp;quot;UPDATE cities SET name=? WHERE id=?&amp;quot;, &amp;crarr;
    args[&amp;quot;id&amp;quot;], name)
end&lt;/pre&gt;

&lt;p&gt;No c&amp;oacute;digo acima, pegamos o c&amp;oacute;digo postal no banco de dados e trazemos o nome da cidade atrav&amp;eacute;s da API. Depois fazemos o parser da resposta JSON para pegar o nome da cidade. E assim atualizamos o registro no banco de dados. Tudo isso &amp;eacute; feito sem usar o modelo &lt;code&gt;City&lt;/code&gt; ou qualquer coisa da aplica&amp;ccedil;&amp;atilde;o Rails. Isso vai manter o processo muito mais enxuto.&lt;/p&gt;

&lt;h3&gt;Tratamento de Erros&lt;/h3&gt;

&lt;p&gt;O que acontece se uma exce&amp;ccedil;&amp;atilde;o &amp;eacute; lan&amp;ccedil;ada quando tentamos pegar o nome da cidade? Nesses casos o Stalker vai gerar o log do erro e vai tentar executar um manipulador de erros. Podemos criar um manipulador escrevendo um m&amp;eacute;todo &lt;code&gt;error&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/config/jobs.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;error do |exception|
  # Code to handle the error.
end&lt;/pre&gt;

&lt;p&gt;Quando isso acontece o Stalker vai abandonar a tarefa no Beanstalk, isso significa que o Beanstalk n&amp;atilde;o vai tentar coloc&amp;aacute;-la na fila novamente, a menos que a gente use o comando kick. Para isso, conectamos por telnet diretamente no Benstalkd.&lt;/p&gt;

&lt;pre class="terminal"&gt;$ telnet localhost 11300
Trying ::1...
Connected to localhost.
Escape character is &amp;#x27;^]&amp;#x27;.&lt;/pre&gt;

&lt;p&gt;Depois de conectado, vamos executar o comando &lt;code&gt;kick&lt;/code&gt;, passando o n&amp;uacute;mero de tarefas que queremos colocar de volta na fila.&lt;/p&gt;

&lt;pre class="terminal"&gt;kick 10
KICKED 0&lt;/pre&gt;

&lt;p&gt;N&amp;atilde;o temos qualquer tarefa abandonada, ent&amp;atilde;o recebemos &lt;code&gt;KICKED 0&lt;/code&gt; como resposta.&lt;/p&gt;

&lt;p&gt;Agora podemos tratar exce&amp;ccedil;&amp;otilde;es de uma tarefa, mas e se o processo de segundo plano morrer completamente? Devemos monitorar o processo para assegurarmos que ele est&amp;aacute; funcionando. Podemos fazer isso usando a ferramenta &lt;a href="http://god.rubyforge.org"&gt;God&lt;/a&gt;. Falamos dessa ferramenta em detalhes no &lt;a href="http://railscasts.com/episodes/130-monitoring-with-god"&gt;epis&amp;oacute;dio 130&lt;/a&gt;. Abaixo est&amp;aacute; um arquivo de configura&amp;ccedil;&amp;atilde;o para executar tarefas Stalker em segundo plano. Uma vantagem deste m&amp;eacute;todo &amp;eacute; que ele automaticamente faz o daemon do processo para que n&amp;oacute;s n&amp;atilde;o tenhamos que nos preocupar com isso.&lt;/p&gt;

&lt;p&gt;Se voc&amp;ecirc; olhar o arquivo de configura&amp;ccedil;&amp;atilde;o abaixo, vai ver que ele chama o &lt;code&gt;stalk&lt;/code&gt; com nosso arquivo &lt;code&gt;jobs.rb&lt;/code&gt; passado como par&amp;acirc;metro. O resto do arquivo &amp;eacute; um conjunto bastante comum de configura&amp;ccedil;&amp;otilde;es que assegura que ele permane&amp;ccedil;a em funcionamento e n&amp;atilde;o comece a usar muita mem&amp;oacute;ria ou CPU.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/config/god.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;# run with: god -c config/god.rb
RAILS_ROOT = File.expand_path(&amp;quot;../..&amp;quot;, __FILE__)

God.watch do |w|
  w.name = &amp;quot;anycity-worker&amp;quot;
  w.interval = 30.seconds
  w.env = {&amp;quot;RAILS_ENV&amp;quot; =&amp;gt; &amp;quot;production&amp;quot;}
  w.start = &amp;quot;/usr/bin/stalk #{RAILS_ROOT}/config/jobs.rb&amp;quot;
  w.log = &amp;quot;#{RAILS_ROOT}/log/stalker.log&amp;quot;

  w.start_if do |start|
    start.condition(:process_running) do |c|
      c.running = false
    end
  end

  w.restart_if do |restart|
    restart.condition(:memory_usage) do |c|
      c.above = 50.megabytes
      c.times = [3, 5] # 3 out of 5 intervals
    end

    restart.condition(:cpu_usage) do |c|
      c.above = 50.percent
      c.times = 5
    end
  end

  w.lifecycle do |on|
    on.condition(:flapping) do |c|
      c.to_state = [:start, :restart]
      c.times = 5
      c.within = 5.minute
      c.transition = :unmonitored
      c.retry_in = 10.minutes
      c.retry_times = 5
      c.retry_within = 2.hours
    end
  end
end&lt;/pre&gt;

&lt;h3&gt;Persistindo Beanstalk&lt;/h3&gt;

&lt;p&gt;S&amp;oacute; mais uma coisa para se manter em mente &amp;eacute; que o Beanstalk por padr&amp;atilde;o n&amp;atilde;o &amp;eacute; persistente. Se voc&amp;ecirc; execut&amp;aacute;-lo como fizemos com op&amp;ccedil;&amp;atilde;o &lt;code&gt;-d&lt;/code&gt; e o processo morrer em seguida, todas as tarefas que estavam na fila aguardando para serem processadas s&amp;atilde;o perdidas, pois elas s&amp;atilde;o armazenadas na mem&amp;oacute;ria. Para tornar persistente, podemos execut&amp;aacute;-lo com a op&amp;ccedil;&amp;atilde;o &lt;code&gt;-b&lt;/code&gt; e passar-lhe o caminho para um diret&amp;oacute;rio binlog.&lt;/p&gt;

&lt;pre class="terminal"&gt;beanstalkd -d -b /Users/eifion/binlog&lt;/pre&gt;

&lt;p&gt;Dessa forma a fila ser&amp;aacute; restaurada caso o processo falhe.&lt;/p&gt;</description>
      <pubDate>Wed, 29 Dec 2010 23:17:27 +0000</pubDate>
      <guid>http://pt.asciicasts.com/episodes/243-beanstalkd-e-stalker</guid>
      <link>http://pt.asciicasts.com/episodes/243-beanstalkd-e-stalker</link>
    </item>
    <item>
      <title>Mongoid</title>
      <description>&lt;p&gt;H&amp;aacute; alguns meses atr&amp;aacute;s no Epis&amp;oacute;dio 194 [&lt;a href="http://railscasts.com/episodes/194-mongodb-and-mongomapper"&gt;ver&lt;/a&gt;, &lt;a href="http://railscasts.com/episodes/194-mongodb-and-mongomapper"&gt;ler&lt;/a&gt;] covered MongoDB e MongoMapper. MongoMapper &amp;eacute; uma gema grande, mas agora existe uma alternativa chamada &lt;a href="http://mongoid.org/"&gt;Mongoid&lt;/a&gt; que vale a pena considerar se voc&amp;ecirc; est&amp;aacute; pensando em usar MongoDB como o back-end de uma aplica&amp;ccedil;&amp;atilde;o Rails. Uma das coisas que faz stand Mongoid fora &amp;eacute; o seu site, que parece &amp;oacute;timo e que tem documenta&amp;ccedil;&amp;atilde;o detalhada. Mongoid &amp;eacute; um projeto de outros projetos open-source que voc&amp;ecirc; pode aprender.&lt;/p&gt;

&lt;h3&gt;Instalando o MongoDB&lt;/h3&gt;

&lt;p&gt;Se voc&amp;ecirc; ainda n&amp;atilde;o tem instalado em seu sistema o MongoDB a primeira coisa que voc&amp;ecirc; precisa fazer &amp;eacute; acessar o &lt;a href="http://www.mongodb.org/downloads"&gt;p&amp;aacute;gina de downloads do MongoDB&lt;/a&gt; e baixar os arquivos apropriados. Se voc&amp;ecirc; estiver usando Mac OS X, ent&amp;atilde;o voc&amp;ecirc; pode instalar MongoDB atravez do &lt;a href="http://mxcl.github.com/homebrew/"&gt;Homebrew&lt;/a&gt;. Uma vez instalado, voc&amp;ecirc; pode verificar se est&amp;aacute; funcionando MongoDB visitando &lt;code&gt;&lt;a href="http://localhost:28017"&gt;http://localhost:28017&lt;/a&gt;&lt;/code&gt;. Se voc&amp;ecirc; ver uma p&amp;aacute;gina como a abaixo, em seguida, significa que tudo est&amp;aacute; funcionando corretamente.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/506/original/E238I01.png" width="805" height="561" alt="The page we see when MongoDB is running correctly."/&gt;
&lt;/div&gt;

&lt;h3&gt;Criando uma nova aplica&amp;ccedil;&amp;atilde;o Rails utilizando o Mongoid&lt;/h3&gt;

&lt;p&gt;Agora que j&amp;aacute; temos o MongoDB instalado, vamos criar uma nova aplica&amp;ccedil;&amp;atilde;o Rails 3 que usa Mongoid. Como &amp;eacute; tradi&amp;ccedil;&amp;atilde;o de uma aplica&amp;ccedil;&amp;otilde;es Rails de exemplo, esta ser&amp;aacute; uma aplica&amp;ccedil;&amp;atilde;o de blog.&lt;/p&gt;
&lt;pre class="terminal"&gt;$ rails new blog&lt;/pre&gt;

&lt;p&gt;A primeira coisa que precisamos fazer &amp;eacute; adicionar a gema Mongoid ao Gemfile. No momento da vers&amp;atilde;o escrita &amp;eacute; a 2, que &amp;eacute; a vers&amp;atilde;o que o Rails 3 suporta, ainda est&amp;aacute; em beta, ent&amp;atilde;o vamos precisar especificar o n&amp;uacute;mero da vers&amp;atilde;o.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/Gemfile&lt;/p&gt;
&lt;pre class="ruby"&gt;
source &amp;#x27;http://rubygems.org&amp;#x27;

gem &amp;#x27;rails&amp;#x27;, &amp;#x27;3.0.1&amp;#x27;
gem &amp;#x27;sqlite3-ruby&amp;#x27;, :require =&amp;gt; &amp;#x27;sqlite3&amp;#x27;

gem &amp;#x27;mongoid&amp;#x27;, &amp;#x27;2.0.0.beta.19&amp;#x27;
gem &amp;#x27;bson_ext&amp;#x27;
&lt;/pre&gt;

&lt;p&gt;Precisamos tamb&amp;eacute;m de adicionar o &lt;a href="http://rubygems.org/gems/bson_ext"&gt;&lt;code&gt;bson_ext&lt;/code&gt; gem&lt;/a&gt;. BSON &amp;eacute; uma vers&amp;atilde;o bin&amp;aacute;ria do JSON e esta gema fornece algumas extens&amp;otilde;es C para acelerar a serializa&amp;ccedil;&amp;atilde;o Ruby BSON. Podemos, ent&amp;atilde;o, instalar as gema da maneira usual.&lt;/p&gt;
&lt;pre class="terminal"&gt;$ bundle install&lt;/pre&gt;

&lt;p&gt;Uma vez que as gemas tenham sido instaladas, precisaremos executar o gerador de configura&amp;ccedil;&amp;atilde;o do Mongoid para que ele possa criar o arquivo de configura&amp;ccedil;&amp;atilde;o YAML.&lt;/p&gt;

&lt;pre class="terminal"&gt;$ rails g mongoid:config&lt;/pre&gt;

&lt;p&gt;O arquivo padr&amp;atilde;o &amp;eacute; mostrado abaixo. Podemos deix&amp;aacute;-lo como ele &amp;eacute; enquanto estamos desenvolvendo a nossa aplica&amp;ccedil;&amp;atilde;o.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/config/mongoid.yml&lt;/p&gt;
&lt;pre class="ruby"&gt;
defaults: &amp;amp;defaults
  host: localhost
  # slaves:
  #   - host: slave1.local
  #     port: 27018
  #   - host: slave2.local
  #     port: 27019

development:
  &amp;lt;&amp;lt;: *defaults
  database: blog_development

test:
  &amp;lt;&amp;lt;: *defaults
  database: blog_test

# set these environment variables on your prod server
production:
  host: &amp;lt;%= ENV[&amp;#x27;MONGOID_HOST&amp;#x27;] %&amp;gt;
  port: &amp;lt;%= ENV[&amp;#x27;MONGOID_PORT&amp;#x27;] %&amp;gt;
  username: &amp;lt;%= ENV[&amp;#x27;MONGOID_USERNAME&amp;#x27;] %&amp;gt;
  password: &amp;lt;%= ENV[&amp;#x27;MONGOID_PASSWORD&amp;#x27;] %&amp;gt;
  database: &amp;lt;%= ENV[&amp;#x27;MONGOID_DATABASE&amp;#x27;] %&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Tudo est&amp;aacute; no lugar agora para n&amp;oacute;s poder come&amp;ccedil;ar a desenvolver a nossa aplica&amp;ccedil;&amp;atilde;o. Vamos come&amp;ccedil;ar criando um modelo &lt;code&gt;Artigo&lt;/code&gt; com os campos &lt;code&gt;nome&lt;/code&gt; e &lt;code&gt;conte&amp;uacute;do&lt;/code&gt;, e iremos usar o scaffolding do Rails para criar o controlador associado e visualiza&amp;ccedil;&amp;atilde;o de c&amp;oacute;digo.&lt;/p&gt;

&lt;pre class="terminal"&gt;$ rails g scaffold article name:string content:text
    invoke  mongoid
    create    app/models/article.rb&lt;/pre&gt;

&lt;p&gt;Mongoid fornece geradores para os modelos modo que o gerador Mongoid o modelo &amp;eacute; chamado quando um modelo &amp;eacute; criado e, portanto, o ActiveRecord n&amp;atilde;o &amp;eacute; usado. Se abrirmos o arquivo do modelo, iremos ver que &amp;eacute; uma classe simples foi incluida &lt;code&gt;Mongoid::Document&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/models/article.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
class Article
  include Mongoid::Document
  field :name, :type =&amp;gt; String
  field :content, :type =&amp;gt; String
end
&lt;/pre&gt;

&lt;p&gt;Uma diferen&amp;ccedil;a &amp;eacute; que esta classe vem a partir de uma classe model do ActiveRecord &amp;eacute; que cada campo &amp;eacute; explicitamente definido, junto com seu tipo. O tipo padr&amp;atilde;o &amp;eacute; &lt;code&gt;String&lt;/code&gt;, para que possamos remover os tipos desta classe, se quisermos.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/models/article.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
class Article
  include Mongoid::Document
  field :name
  field :content
end
&lt;/pre&gt;

&lt;p&gt;Agora a nossa aplica&amp;ccedil;&amp;atilde;o est&amp;aacute; pronto para ser executada. N&amp;oacute;s n&amp;atilde;o precisamos executar qualquer banco de dados como migra&amp;ccedil;&amp;atilde;o do MongoDB, com o schema-lesse podemos passar todos os campos que preferimos em um documento. Se voc&amp;ecirc; visitar a p&amp;aacute;gina &lt;code&gt;/articles&lt;/code&gt;, iremos ver a p&amp;aacute;gina usual gerada pelo scaffold, e podemos criar um novo &lt;code&gt;Artigo&lt;/code&gt;, assim como n&amp;oacute;s, se tiv&amp;eacute;ssemos um ActiveRecord como back-end.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/507/original/E238I02.png" width="801" height="280" alt="The articles page after a new article has been created."/&gt;
&lt;/div&gt;

&lt;h3&gt;Adicionando campos&lt;/h3&gt;

&lt;p&gt;Uma das grandes vantagens de se usar o schema-less como banco de dados, &amp;eacute; que &amp;eacute; bastante simples de adicionar novos campos ao modelo. Vamos dizer que se esqueceu de acrescentar uma data de publica&amp;ccedil;&amp;atilde;o do &lt;code&gt;Artigo&lt;/code&gt;. Para adicionar um s&amp;oacute; precisamos modificar a classe do modelo.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/models/article.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;class Article
  include Mongoid::Document
  field :name
  field :content
  field :published_on, :type =&amp;gt; Date
end&lt;/pre&gt;

&lt;p&gt;Para que possamos visualizar e modificar o campo da data de publica&amp;ccedil;&amp;atilde;o, iremos modificar o c&amp;oacute;digo da view e adicionar o novo campo ao formul&amp;aacute;rio.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/views/articles/_form.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;
 &amp;lt;div class=&amp;quot;field&amp;quot;&amp;gt;
    &amp;lt;%= f.label :name %&amp;gt;&amp;lt;br /&amp;gt;
    &amp;lt;%= f.text_field :name %&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;div class=&amp;quot;field&amp;quot;&amp;gt;
    &amp;lt;%= f.label :published_on %&amp;gt;&amp;lt;br /&amp;gt;
    &amp;lt;%= f.date_select :published_on %&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;div class=&amp;quot;field&amp;quot;&amp;gt;
    &amp;lt;%= f.label :content %&amp;gt;&amp;lt;br /&amp;gt;
    &amp;lt;%= f.text_area :content %&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;div class=&amp;quot;actions&amp;quot;&amp;gt;
    &amp;lt;%= f.submit %&amp;gt;
  &amp;lt;/div&amp;gt;
&lt;/pre&gt;  

&lt;p&gt;E tamb&amp;eacute;m a view para a a&amp;ccedil;&amp;atilde;o do &lt;code&gt;show&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/views/articles/show.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;
&amp;lt;p id=&amp;quot;notice&amp;quot;&amp;gt;&amp;lt;%= notice %&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;
  &amp;lt;b&amp;gt;Name:&amp;lt;/b&amp;gt;
  &amp;lt;%= @article.name %&amp;gt;
&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;
  &amp;lt;b&amp;gt;Content:&amp;lt;/b&amp;gt;
  &amp;lt;%= @article.content %&amp;gt;
&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;
  &amp;lt;b&amp;gt;Published:&amp;lt;/b&amp;gt;
  &amp;lt;%= @article.published_on %&amp;gt;
&amp;lt;/p&amp;gt;


&amp;lt;%= link_to &amp;#x27;Edit&amp;#x27;, edit_article_path(@article) %&amp;gt; |
&amp;lt;%= link_to &amp;#x27;Back&amp;#x27;, articles_path %&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Agora podemos editar o artigo que acabamos de criar e adicionar uma data de publica&amp;ccedil;&amp;atilde;o.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/508/original/E238I03.png" width="815" height="299" alt="Adding a published-on date to an article."/&gt;
&lt;/div&gt;

&lt;h3&gt;Valida&amp;ccedil;&amp;otilde;es&lt;/h3&gt;

&lt;p&gt;O Mongoid utiliza o ActiveModel, o que significa que muitas das funcionalidades que usamos no ActiveRecord est&amp;aacute; dispon&amp;iacute;vel para n&amp;oacute;s aqui tamb&amp;eacute;m, por exemplo valida&amp;ccedil;&amp;otilde;es, callbacks, dirty tracking, &lt;code&gt;attr_accessible&lt;/code&gt;, e assim por diante. Com isto, se torna mais f&amp;aacute;cil adicionar as valida&amp;ccedil;&amp;otilde;es de modelos como os ActiveRecord do Mongoid.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/models/article.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;class Article
  include Mongoid::Document
  field :name
  field :content
  field :published_on, :type =&amp;gt; Date
  validates_presence_of :name
end&lt;/pre&gt;

&lt;p&gt;Se tentarmos criar um artigo sem um nome agora, iremos come&amp;ccedil;ar a ver os erros de valida&amp;ccedil;&amp;atilde;o o mesmo que ver&amp;iacute;amos por um modelo equivalente ao ActiveRecord.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/509/original/E238I04.png" width="816" height="350" alt="Validation errors work just as they do with ActiveRecord models."/&gt;
&lt;/div&gt;

&lt;h3&gt;Associa&amp;ccedil;&amp;otilde;es&lt;/h3&gt;

&lt;p&gt;N&amp;atilde;o podemos ter um blog sem coment&amp;aacute;rios, ent&amp;atilde;o iremos criar um modelo para &lt;code&gt;Coment&amp;aacute;rio&lt;/code&gt; ao longo associa&amp;ccedil;&amp;atilde;o, modo que cada artigo pode ter muitos coment&amp;aacute;rios. H&amp;aacute; duas maneiras para definir as associa&amp;ccedil;&amp;otilde;es com Mongoid. A primeira &amp;eacute; atrav&amp;eacute;s de uma associa&amp;ccedil;&amp;atilde;o de refer&amp;ecirc;ncia. Esta se comporta de maneira similar &amp;agrave;s rela&amp;ccedil;&amp;otilde;es entre tabelas no ActiveRecord e bancos de dados relacionais em que existem dois registros separados que est&amp;atilde;o relacionados atrav&amp;eacute;s de uma coluna &lt;code&gt;id&lt;/code&gt;. A outra maneira &amp;eacute; uma associa&amp;ccedil;&amp;atilde;o incorporado, o que significaria, neste caso, os coment&amp;aacute;rios est&amp;atilde;o incorporados dentro do mesmo documento que o artigo.&lt;/p&gt;

&lt;p&gt;Em quanto voc&amp;ecirc; est&amp;aacute; decidindo qual destas abordagens, &amp;eacute; a utiliza&amp;ccedil;&amp;atilde;o que voc&amp;ecirc; precisa se perguntar se voc&amp;ecirc; realmente necessita dos registros associados por ficar por conta pr&amp;oacute;pria ou se voc&amp;ecirc; vai sempre acess&amp;aacute;-los atrav&amp;eacute;s do seu modelo pai. Neste caso, s&amp;oacute; vamos sempre estar recebendo coment&amp;aacute;rios atrav&amp;eacute;s de seu artigo associado por isso vamos usar uma associa&amp;ccedil;&amp;atilde;o incorporado. N&amp;oacute;s definimos o relacionamento na classe de &lt;code&gt;Artigo&lt;/code&gt; usando o m&amp;eacute;todo &lt;code&gt;embeds_many&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/models/article.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;class Article
  include Mongoid::Document
  field :name
  field :content
  field :published_on, :type =&amp;gt; Date
  validates_presence_of :name
  embeds_many :comments
end&lt;/pre&gt;

&lt;p&gt;Em seguida, vamos gerar o modelo de &lt;code&gt;Coment&amp;aacute;rio&lt;/code&gt;.&lt;/p&gt;

&lt;pre class="terminal"&gt;$ rails g model comment name:string content:text&lt;/pre&gt;

&lt;p&gt;Nesta nova classe &lt;code&gt;Coment&amp;aacute;rio&lt;/code&gt;, podemos agora definir a sua rela&amp;ccedil;&amp;atilde;o com o &lt;code&gt;Artigo&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/models/comment.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;class Comment
  include Mongoid::Document
  field :name
  field :content
  embedded_in :article, :inverse_of =&amp;gt; :comments
end&lt;/pre&gt;

&lt;p&gt;Usamos &lt;code&gt;embedded_in&lt;/code&gt; para definir a rela&amp;ccedil;&amp;atilde;o de um coment&amp;aacute;rio a um artigo. A op&amp;ccedil;&amp;atilde;o &lt;code&gt;inverse_of&lt;/code&gt; &amp;eacute; necess&amp;aacute;rio dizer ao Mongoid que o coment&amp;aacute;rio deve ser incorporado completamente.&lt;/p&gt;

&lt;p&gt;A fim de criar coment&amp;aacute;rios para cada artigo e v&amp;ecirc;-los vamos precisar criar um &lt;code&gt;CommentsController&lt;/code&gt; e algumas views, mas antes de fazermos isso iremos precisar alterar o arquivo de rotas. Para as associa&amp;ccedil;&amp;otilde;es incorporadas como esta, geralmente queremos usar rotas aninhadas como o objeto filho &amp;eacute; sempre acessado atrav&amp;eacute;s de seu pai e por isso iremos utilizar o nested do recurso coment&amp;aacute;rios em artigos.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/config/routes.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;Blog::Application.routes.draw do
  resources :articles do
    resources :comments
  end
end&lt;/pre&gt;

&lt;p&gt;Em seguida, iremos gerar o controller.&lt;/p&gt;

&lt;pre class="terminal"&gt;$ rails g controller comments&lt;/pre&gt;

&lt;p&gt;No controller iremos escrever uma &lt;code&gt;criar&lt;/code&gt; uma a&amp;ccedil;&amp;atilde;o para que possamos criar novas observa&amp;ccedil;&amp;otilde;es para um artigo. Com esta a&amp;ccedil;&amp;atilde;o ir&amp;aacute; encontrar um artigo com base no par&amp;acirc;metro &lt;code&gt;article_id&lt;/code&gt;, crie um coment&amp;aacute;rio para este artigo e, em seguida redirecionar de volta para a p&amp;aacute;gina do artigo.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controllers/comments_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;CommentsController &amp;lt; ApplicationController
  def create
    @article = Article.find(params[:article_id])
    @comment = @article.comments.create!(params[:comment])
    redirect_to @article, :notice =&amp;gt; &amp;quot;Comment created!&amp;quot;  
  end
end&lt;/pre&gt;

&lt;p&gt;Finalmente, iremos adicionar algum c&amp;oacute;digo na view dos artigos, que ir&amp;aacute; mostrar os coment&amp;aacute;rios de um artigo e permitir que os coment&amp;aacute;rios sejam adicionados.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/views/articles/show.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;&amp;lt;% if @article.comments.size &amp;gt; 0 %&amp;gt;
  &amp;lt;h2&amp;gt;Comments&amp;lt;/h2&amp;gt;
  &amp;lt;% for comment in @article.comments %&amp;gt;
    &amp;lt;h3&amp;gt;&amp;lt;%= comment.name %&amp;gt;&amp;lt;/h3&amp;gt;
    &amp;lt;p&amp;gt;&amp;lt;%= comment.content %&amp;gt;&amp;lt;/p&amp;gt;
  &amp;lt;% end %&amp;gt;
&amp;lt;% end %&amp;gt;

&amp;lt;h2&amp;gt;New Comment&amp;lt;/h2&amp;gt;

&amp;lt;%= form_for [@article, Comment.new] do |f| %&amp;gt;
  &amp;lt;p&amp;gt;&amp;lt;%= f.label :name %&amp;gt; &amp;lt;%= f.text_field :name %&amp;gt;&amp;lt;/p&amp;gt;
  &amp;lt;p&amp;gt;&amp;lt;%= f.text_area :content, :rows =&amp;gt; 10 %&amp;gt;&amp;lt;/p&amp;gt;
  &amp;lt;p&amp;gt;&amp;lt;%= f.submit %&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;% end %&amp;gt;&lt;/pre&gt;

&lt;p&gt;Ao visitar a p&amp;aacute;gina de um artigo agora n&amp;oacute;s iremos ser capazes de criar um novo coment&amp;aacute;rio e depois de ter submetido ser&amp;aacute; mostrado abaixo do artigo.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/510/original/E238I05.png" width="800" height="621" alt="Adding a comment to an article."/&gt;
&lt;/div&gt;

&lt;p&gt;Se dermos uma olhada no log do desenvolvimento, podemos ver as consultas do MongoDB. Quando criamos um coment&amp;aacute;rio agora, essa consulta foi feita.&lt;/p&gt;

&lt;pre class="terminal"&gt;
MONGODB blog_development[&amp;#x27;articles&amp;#x27;].update({&amp;quot;_id&amp;quot;=&amp;gt;BSON::ObjectId(&amp;#x27;4cd01fa4a74209eacc000003&amp;#x27;)}, 
{&amp;quot;$push&amp;quot;=&amp;gt;{&amp;quot;comments&amp;quot;=&amp;gt;{&amp;quot;_id&amp;quot;=&amp;gt;BSON::ObjectId(&amp;#x27;4cd04c74a74209ecb4000002&amp;#x27;), 
  &amp;quot;name&amp;quot;=&amp;gt;&amp;quot;Eifion&amp;quot;, &amp;quot;content&amp;quot;=&amp;gt;&amp;quot;I agree.&amp;quot;}}})&lt;/pre&gt;

&lt;p&gt;As atualiza&amp;ccedil;&amp;otilde;es que consultam um modelo de artigo e acrescenta um novo coment&amp;aacute;rio atribuir-lhe que os coment&amp;aacute;rios n&amp;atilde;o s&amp;atilde;o armazenados separadamente. Isto significa que, se abrirmos o console do Rails e contar todos os coment&amp;aacute;rios, teremos um resultado inesperado.&lt;/p&gt;

&lt;pre class="terminal"&gt;&amp;gt; Comment.count
 =&amp;gt; 0&lt;/pre&gt; 

&lt;p&gt;Os coment&amp;aacute;rios que temos s&amp;atilde;o incorporados em objetos e n&amp;atilde;o est&amp;atilde;o dispon&amp;iacute;veis a n&amp;iacute;vel global do documento. Para acess&amp;aacute;-los, sempre temos que atravessar seu artigo associado.&lt;/p&gt;

&lt;pre class="terminal"&gt;&amp;gt;   Article.first.comments.count
 =&amp;gt; 1&lt;/pre&gt;
 
&lt;p&gt;Para chegar aos atributos de um coment&amp;aacute;rio, n&amp;oacute;s sempre necessitamos come&amp;ccedil;ar esse coment&amp;aacute;rio atrav&amp;eacute;s de uma associa&amp;ccedil;&amp;atilde;o, como esta aplica&amp;ccedil;&amp;atilde;o, os coment&amp;aacute;rios s&amp;atilde;o incorporados aos registros.&lt;/p&gt;

&lt;h3&gt;Tipo de associa&amp;ccedil;&amp;otilde;es de refer&amp;ecirc;ncias&lt;/h3&gt;

&lt;p&gt;Se queremos um registro associado que tamb&amp;eacute;m esteja dispon&amp;iacute;vel como um documento separado, ent&amp;atilde;o iremos necessitar de um para criar uma associa&amp;ccedil;&amp;atilde;o de tipo de refer&amp;ecirc;ncia. N&amp;oacute;s iremos demonstrar isso modificando o nosso pedido para que possamos associar cada artigo de um autor. Primeiro iremos gerar um scaffold para um modelo novo &lt;code&gt;Autor&lt;/code&gt;.&lt;/p&gt;

&lt;pre class="terminal"&gt;$ rails g scaffold author name:string&lt;/pre&gt;

&lt;p&gt;Antes de demonstrar associa&amp;ccedil;&amp;otilde;es vamos dar uma r&amp;aacute;pida olhada em um recurso interessante do Mongoid. Se n&amp;oacute;s adicionamos um m&amp;eacute;todo essencial para Mongoid classe de modelo que a &lt;code&gt;key&lt;/code&gt;&amp;gt; ser&amp;aacute; usada como o &lt;code&gt;id&lt;/code&gt; para identificar esse modelo. N&amp;oacute;s iremos fazer o nome do atributo a chave para o &lt;code&gt;Autor&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/models/author.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;class Author
  include Mongoid::Document
  field :name
  key :name
end&lt;/pre&gt;

&lt;p&gt;Se criarmos um autor, agora, quando estamos redirecionado para a p&amp;aacute;gina do autor, vamos ver o &lt;code&gt;id&lt;/code&gt; na URL.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/511/original/E238I06.png" width="800" height="280" alt="The page for an author showing the name as an id."/&gt;
&lt;/div&gt;

&lt;p&gt;Se vamos utilizar esse recurso, ent&amp;atilde;o iremos precisar de assegurar o campo que escolhemos para usar como uma chave n&amp;atilde;o edit&amp;aacute;vel para que o documento tenha uma seq&amp;uuml;&amp;ecirc;ncia permanente como um &lt;code&gt;id&lt;/code&gt; que n&amp;atilde;o vai mudar toda a vida do documento.&lt;/p&gt;

&lt;p&gt;Voltar para associa&amp;ccedil;&amp;otilde;es de agora. Na classe &lt;code&gt;Autor&lt;/code&gt; usamos &lt;code&gt;references_many&lt;/code&gt; para definir o relacionamento com os artigos.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/models/author.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;class Author
  include Mongoid::Document
  field :name
  key :name
  references_many :articles
end&lt;/pre&gt;

&lt;p&gt;Ent&amp;atilde;o, no modelo de &lt;code&gt;Artigo&lt;/code&gt; que usamos o &lt;code&gt;referenced_in&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/models/article.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;class Article
  include Mongoid::Document
  field :name
  field :content
  field :published_on, :type =&amp;gt; Date
  validates_presence_of :name
  embeds_many :comments
  referenced_in :author
end&lt;/pre&gt;

&lt;p&gt;Podemos agora usar essa associa&amp;ccedil;&amp;atilde;o como far&amp;iacute;amos no ActiveRecord. Em nosso formul&amp;aacute;rio para editar um artigo, podemos adicionar uma &lt;code&gt;collection_select&lt;/code&gt; para que possamos selecionar um autor quando criar ou atualizar um artigo.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/views/articles/_form.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;&amp;lt;div class=&amp;quot;field&amp;quot;&amp;gt;
  &amp;lt;%= f.label :author_id %&amp;gt;&amp;lt;br /&amp;gt;
  &amp;lt;%= f.collection_select :author_id, Author.all, :id, :name %&amp;gt;
&amp;lt;/div&amp;gt;&lt;/pre&gt;

&lt;p&gt;Se modificarmos nosso artigo agora e selecionar um autor que vai pode ver que o autor do &lt;code&gt;id&lt;/code&gt; incorporado no artigo quando examin&amp;aacute;-lo no console.&lt;/p&gt;

&lt;pre class="terminal"&gt;&amp;gt; Article.first
 =&amp;gt; #&amp;lt;Article _id: 4cd01fa4a74209eacc000003, name: &amp;quot;Mongoid&amp;quot;, content: &amp;quot;it&amp;#x27;s awesome!&amp;quot;, published_on: 2010-11-02 00:00:00 UTC, author_id: &amp;quot;eifion-bedford&amp;quot;&amp;gt;&lt;/pre&gt; 
 
&lt;p&gt;Diferentemente da associa&amp;ccedil;&amp;atilde;o coment&amp;aacute;rios, no entanto, podemos acessar o autor separadamente.&lt;/p&gt;

&lt;pre class="terminal"&gt;&amp;gt; Author.first
 =&amp;gt; #&amp;lt;Author _id: eifion-bedford, name: &amp;quot;Eifion Bedford&amp;quot;&amp;gt;&lt;/pre&gt;
 
&lt;p&gt;Isso &amp;eacute; tudo para este epis&amp;oacute;dio sobre Mongoid. H&amp;aacute; muito que n&amp;atilde;o temos tratado aqui, mas a documenta&amp;ccedil;&amp;atilde;o &amp;eacute; bastante abrangente e ir&amp;aacute; dar-lhe quase tudo o que voc&amp;ecirc; precisa saber para usar o Mongoid e o MongoDB na sua aplica&amp;ccedil;&amp;atilde;o Rails.&lt;/p&gt;</description>
      <pubDate>Wed, 29 Dec 2010 23:07:27 +0000</pubDate>
      <guid>http://pt.asciicasts.com/episodes/238-mongoid</guid>
      <link>http://pt.asciicasts.com/episodes/238-mongoid</link>
    </item>
    <item>
      <title>Usando attr_accessible dinamicamente.</title>
      <description>&lt;p&gt;H&amp;aacute; mais de tr&amp;ecirc;s anos, no epis&amp;oacute;dio 26 [&lt;a href="http://railscasts.com/episodes/26-hackers-love-mass-assignment"&gt;assistir&lt;/a&gt;, &lt;a href="http://asciicasts.com/episodes/26-hackers-love-mass-assignment"&gt;ler&lt;/a&gt;] falamos sobre atribui&amp;ccedil;&amp;atilde;o em massa e como isso pode causar problemas de seguran&amp;ccedil;a. O Rails 3 foi lan&amp;ccedil;ado e possui v&amp;aacute;rias caracter&amp;iacute;sticas mais seguras que j&amp;aacute; v&amp;ecirc;m habilitadas por padr&amp;atilde;o, mas n&amp;atilde;o &amp;eacute; o caso das atribui&amp;ccedil;&amp;otilde;es em massa. Os modelos das aplica&amp;ccedil;&amp;otilde;es Rails precisam ter seus atributos protegidos, para evitar que usu&amp;aacute;rios mal intencionados atualizem esses atributos enviando-os para o servidor atrav&amp;eacute;s de requisi&amp;ccedil;&amp;otilde;es POST. Se voc&amp;ecirc; n&amp;atilde;o conhece esse problema, d&amp;ecirc; uma olhada no epis&amp;oacute;dio 26, mas o importante &amp;eacute; saber que sempre que voc&amp;ecirc; criar ou atualizar uma inst&amp;acirc;ncia de um modelo nos seus controllers, usando atribui&amp;ccedil;&amp;atilde;o em massa, &amp;eacute; necess&amp;aacute;rio usar o m&amp;eacute;todo &lt;code&gt;attr_accessible&lt;/code&gt; nos modelos, para proteger os atributos que voc&amp;ecirc; n&amp;atilde;o quer que sejam atualizados. Caso voc&amp;ecirc; n&amp;atilde;o fa&amp;ccedil;a isso, os usu&amp;aacute;rios poder&amp;atilde;o atualizar quaisquer atributos e isso pode levar a um enorme problema de seguran&amp;ccedil;a.&lt;/p&gt;

&lt;p&gt;&amp;Eacute; simples chamar o m&amp;eacute;todo&lt;code&gt;attr_accessible&lt;/code&gt; em cada modelo, por&amp;eacute;m existem dois problemas em potencial quando isso &amp;eacute; feito. O primeiro problema ocorre quando voc&amp;ecirc; est&amp;aacute; testando sua aplica&amp;ccedil;&amp;atilde;o. Algumas vezes voc&amp;ecirc; quer fazer atribui&amp;ccedil;&amp;atilde;o em massa durante os testes e com os modelos protegidos pelo &lt;code&gt;attr_accessible&lt;/code&gt; isso pode se tornar muito dif&amp;iacute;cil. Uma solu&amp;ccedil;&amp;atilde;o para esse problema &amp;eacute; usar &lt;code&gt;factories&lt;/code&gt;, como foi mostrado no epis&amp;oacute;dio 158  [&lt;a href="http://railscasts.com/episodes/158-factories-not-fixtures"&gt;assistir&lt;/a&gt;, &lt;a href="http://asciicasts.com/episodes/158-factories-not-fixtures"&gt;ler&lt;/a&gt;].&lt;/p&gt;

&lt;p&gt;O segundo problema &amp;eacute; que o &lt;code&gt;attr_accessible&lt;/code&gt; n&amp;atilde;o &amp;eacute; din&amp;acirc;mico. Os atributos que s&amp;atilde;o especificados nele para um dado modelo s&amp;atilde;o fixos. E alterar esses atributos baseado nas permiss&amp;otilde;es dos usu&amp;aacute;rios, por exemplo, pode ser dif&amp;iacute;cil. Isso acontecia no Rails 2, mas o Rails 3 fornece uma nova maneira de termos atributos din&amp;acirc;micos e vamos mostrar isso neste epis&amp;oacute;dio.&lt;/p&gt;

&lt;h3&gt;Nosso Wiki Site&lt;/h3&gt;

&lt;p&gt;Para demonstrar os atributos din&amp;acirc;micos, vamos usar um wiki site. Esse site tem alguns artigos e um artigo pode ser editado por qualquer pessoa. No formul&amp;aacute;rio de edi&amp;ccedil;&amp;atilde;o, juntamente com os campos nome e conte&amp;uacute;do, est&amp;aacute; um checkbox que permite que um usu&amp;aacute;rio marque um artigo como &amp;#x27;importante&amp;#x27;.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/502/original/E237I01.png" width="800" height="446" alt="Editing an article to mark it as important."/&gt;
&lt;/div&gt;

&lt;p&gt;Quando um artigo &amp;eacute; marcado como importante, seu t&amp;iacute;tulo aparece em vermelho.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/503/original/E237I02.png" width="800" height="366" alt="The page for an important article with a read headline."/&gt;
&lt;/div&gt;

&lt;p&gt;Vamos modificar a aplica&amp;ccedil;&amp;atilde;o de forma que somente os administradores possam alterar a import&amp;acirc;ncia de um artigo. Usu&amp;aacute;rios n&amp;atilde;o administradores n&amp;atilde;o devem poder alterar o campo &lt;code&gt;important&lt;/code&gt;. &amp;Eacute; f&amp;aacute;cil modificar o formul&amp;aacute;rio e mostrar o checkbox somente para os administradores, por&amp;eacute;m isso n&amp;atilde;o resolve o problema, pois ainda ser&amp;aacute; poss&amp;iacute;vel que os usu&amp;aacute;rios ignorem esse formul&amp;aacute;rio e fa&amp;ccedil;am uma requisi&amp;ccedil;&amp;atilde;o POST que modifique o campo &lt;code&gt;important&lt;/code&gt; de um artigo.&lt;/p&gt;

&lt;p&gt;A solu&amp;ccedil;&amp;atilde;o para esse problema est&amp;aacute; nas camadas de modelos e controllers, especificamente nas actions &lt;code&gt;create&lt;/code&gt; e &lt;code&gt;update&lt;/code&gt; do &lt;code&gt;ArticlesController&lt;/code&gt;, pois &amp;eacute; onde a atribui&amp;ccedil;&amp;atilde;o em massa acontece. Uma abordagem que poder&amp;iacute;amos ter para proteger o atributo &lt;code&gt;important&lt;/code&gt;, seria remov&amp;ecirc;-lo dos &lt;code&gt;params&lt;/code&gt; a menos que o usu&amp;aacute;rio atual seja um administrador.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controllers/articles_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
def update
  params[:article].delete(:important) unless admin?
  @article = Article.find(params[:id])
  if @article.update_attributes(params[:article])
    flash[:notice] = &amp;quot;Successfully updated article.&amp;quot;
    redirect_to @article
  else
    render :action =&amp;gt; &amp;#x27;edit&amp;#x27;
  end
end
&lt;/pre&gt;

&lt;p&gt;O problema dessa solu&amp;ccedil;&amp;atilde;o &amp;eacute; que temos que lembrar de fazer isso para todos os atributos que queremos proteger. E tamb&amp;eacute;m n&amp;atilde;o vai existir uma correla&amp;ccedil;&amp;atilde;o com a chamada ao &lt;code&gt;attr_accessible&lt;/code&gt; no model. Seria muito melhor se pud&amp;eacute;ssemos ter um &lt;code&gt;attr_accessible&lt;/code&gt; din&amp;acirc;mico.&lt;/p&gt;

&lt;p&gt;Vamos dar uma olhada na documenta&amp;ccedil;&amp;atilde;o da API do Rails para ver se encontramos algo sobre o &lt;a href="http://api.rubyonrails.org/classes/ActiveModel/MassAssignmentSecurity/ClassMethods.html#method-i-attr_accessible"&gt;&lt;code&gt;attr_accessible&lt;/code&gt;&lt;/a&gt; que possa ajudar. Uma coisa interessante mostrada na documenta&amp;ccedil;&amp;atilde;o &amp;eacute; que o &lt;code&gt;attr_accessible&lt;/code&gt; agora est&amp;aacute; no m&amp;oacute;dulo &lt;code&gt;ActiveModel::MassAssignmentSecurity&lt;/code&gt;, e n&amp;atilde;o mais diretamente no &lt;code&gt;ActiveRecord&lt;/code&gt;. Isso significa que ele pode ser inclu&amp;iacute;do e usado em qualquer classe, o que &amp;eacute; muito mais flex&amp;iacute;vel. No topo da documenta&amp;ccedil;&amp;atilde;o, tem um exemplo de uso do &lt;code&gt;ActiveModel::MassAssignmentSecurity&lt;/code&gt; diretamente no controller, em vez de estar no modelo, o que &amp;eacute; realmente uma boa ideia. Uma coisa realmente interessante &amp;eacute; o c&amp;oacute;digo que mostra como tornar o &lt;code&gt;attr_accessible&lt;/code&gt; din&amp;acirc;mico sobrescrevendo o m&amp;eacute;todo &lt;code&gt;mass_assignment_authorizer&lt;/code&gt;.&lt;/p&gt;

&lt;pre class="ruby"&gt;
def mass_assignment_authorizer
  admin ? admin_accessible_attributes : super
end
&lt;/pre&gt;

&lt;p&gt;O c&amp;oacute;digo acima muda o comportamento da aplica&amp;ccedil;&amp;atilde;o baseado no fato do usu&amp;aacute;rio ser um admin ou n&amp;atilde;o. Isso &amp;eacute; exatamente o que queremos fazer. Sobrescrevendo esse m&amp;eacute;todo nos nossos modelos, podemos alterar os campos que podem ser modificados pela atribui&amp;ccedil;&amp;atilde;o em massa usando qualquer condi&amp;ccedil;&amp;atilde;o.&lt;/p&gt;

&lt;p&gt;Nosso modelo &lt;code&gt;Article&lt;/code&gt; atualmente est&amp;aacute; assim:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/models/article.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
class Article &amp;lt; ActiveRecord::Base
  attr_accessible :name, :content, :important
end
&lt;/pre&gt;

&lt;p&gt;Essa &amp;eacute; uma classe simples somente com uma chamada ao &lt;code&gt;attr_accessible&lt;/code&gt; passando tr&amp;ecirc;s atributos. O atributo &lt;code&gt;:important&lt;/code&gt; &amp;eacute; o &amp;uacute;nico que queremos tornar din&amp;acirc;mico e podemos fazer isso sobrescrevendo o m&amp;eacute;todo &lt;code&gt;mass_assignment_authorizer&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/models/article.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
class Article &amp;lt; ActiveRecord::Base
  attr_accessible :name, :content
  
  private
  def mass_assignment_authorizer
    super + [:important]
  end
end
&lt;/pre&gt;

&lt;p&gt;Chamando &lt;code&gt;super&lt;/code&gt; no m&amp;eacute;todo &lt;code&gt;mass_assignment_authorizer&lt;/code&gt; estamos obtendo o comportamento padr&amp;atilde;o, o qual retorna uma &amp;quot;whitelist sanitizer&amp;quot;. Voc&amp;ecirc; n&amp;atilde;o precisa saber exatamente como isso funciona para poder usar. S&amp;oacute; precisa saber que voc&amp;ecirc; pode adicionar mais atributos a ele como fizemos anteriormente. Uma vez que adicionamos esse par&amp;acirc;metro extra, podemos remov&amp;ecirc;-lo da lista de par&amp;acirc;metros do &lt;code&gt;attr_accessible&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As altera&amp;ccedil;&amp;otilde;es que fizemos at&amp;eacute; agora n&amp;atilde;o alteraram o comportamento da nossa aplica&amp;ccedil;&amp;atilde;o toda, mas podemos tornar a acessibilidade do &lt;code&gt;:important&lt;/code&gt; din&amp;acirc;mica agora, pois ele est&amp;aacute; definido em uma vari&amp;aacute;vel de inst&amp;acirc;ncia em vez de estar no n&amp;iacute;vel da classe. Vamos fazer isso adicionando uma vari&amp;aacute;vel &amp;agrave; classe que vai conter uma lista de atributos que queremos tornar acess&amp;iacute;veis.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/models/article.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
class Article &amp;lt; ActiveRecord::Base
  attr_accessible :name, :content
  attr_accessor :accessible
  
  private
  def mass_assignment_authorizer
    super + (accessible || [])
  end
end
&lt;/pre&gt;  

&lt;p&gt;Qualquer par&amp;acirc;metro passado para o &lt;code&gt;accessible&lt;/code&gt; vai ser adicionamdo &amp;agrave; lista de atributos acess&amp;iacute;veis e podemos usar isso em nossos controllers. Vamos modificar a action update para que seja adicionado o par&amp;acirc;metro &lt;code&gt;:important&lt;/code&gt; somente se o usu&amp;aacute;rio atual for um admin.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controllers/articles_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
def update
  @article = Article.find(params[:id])
  @article.accessible = [:important] if admin?
  if @article.update_attributes(params[:article])
    flash[:notice] = &amp;quot;Successfully updated article.&amp;quot;
    redirect_to @article
  else
    render :action =&amp;gt; &amp;#x27;edit&amp;#x27;
  end
end
&lt;/pre&gt;

&lt;p&gt;Podemos iniciar nossa aplica&amp;ccedil;&amp;atilde;o para ver se as altera&amp;ccedil;&amp;otilde;es funcionaram. Se entramos na aplica&amp;ccedil;&amp;atilde;o com uma conta que n&amp;atilde;o &amp;eacute; de admin, e editarmos um artigo, marcando esse artigo como importante, quando estivermos de volta &amp;agrave; p&amp;aacute;gina de artigos, o t&amp;iacute;tulo estar&amp;aacute; preto, indicando que o campo &lt;code&gt;important&lt;/code&gt; n&amp;atilde;o foi alterado.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/504/original/E237I03.png" width="805" height="412" alt="The article is still not marked as important."/&gt;
&lt;/div&gt;

&lt;p&gt;Se transformarmos a nossa conta em administrador e editarmos o artigo novamente, o campo &lt;code&gt;important&lt;/code&gt; estar&amp;aacute; atualizado e o t&amp;iacute;tulo mudar&amp;aacute; de cor.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/505/original/E237I04.png" width="805" height="412" alt="The articles is now marked as important."/&gt;
&lt;/div&gt;

&lt;p&gt;Os admins devem poder editar quaisquer campos, por isso seria &amp;uacute;til se o &lt;code&gt;accessible&lt;/code&gt; suportasse uma op&amp;ccedil;&amp;atilde;o &lt;code&gt;:all&lt;/code&gt;, que nos permitiria facilmente deixar todos os atributos do modelo edit&amp;aacute;veis. Podemos fazer isso modificando o &lt;code&gt;mass_assignment_authorizer&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/models/article.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
def mass_assignment_authorizer
  if accessible == :all
    self.class.protected_attributes
  else
    super + (accessible || [])
  end
end
&lt;/pre&gt;

&lt;p&gt;O m&amp;eacute;todo agora verifica se o &lt;code&gt;accessible&lt;/code&gt; &amp;eacute; igual a &lt;code&gt;:all&lt;/code&gt;. Se &amp;eacute; igual, ent&amp;atilde;o precisamos retornar algo que tornar&amp;aacute; todos os atributos edit&amp;aacute;veis. Seria bom se pud&amp;eacute;ssemos retornar simplesmente um array vazio, mas infelizmente o objeto que &amp;eacute; retornado pelo &lt;code&gt;mass_assignment_authorizer&lt;/code&gt; &amp;eacute; um objeto sanitizer, ent&amp;atilde;o isso n&amp;atilde;o funciona. O jeito que temos trabalhado com isso &amp;eacute; meio hack, mas funciona bem: retornamos &lt;code&gt;self.class.protected_attributes&lt;/code&gt;. Isso &amp;eacute; usado pelo m&amp;oacute;dulo &lt;code&gt;MassAssignmentSecurity&lt;/code&gt; para prover uma lista negra de atributos que n&amp;atilde;o podem ser modificados. Como n&amp;oacute;s n&amp;atilde;o usamos &lt;code&gt;attr_protected&lt;/code&gt; nessa classe, isso vai permitir todos os atributos, que &amp;eacute; justamente o que queremos aqui. Podemos agora modificar o &lt;code&gt;ArticlesController&lt;/code&gt; para tornar todos os atributos do &lt;code&gt;Article&lt;/code&gt; acess&amp;iacute;veis, passando &lt;code&gt;:all&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controllers/articles_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
def update
  @article = Article.find(params[:id])
  @article.accessible = :all if admin?
  if @article.update_attributes(params[:article])
    flash[:notice] = &amp;quot;Successfully updated article.&amp;quot;
    redirect_to @article
  else
    render :action =&amp;gt; &amp;#x27;edit&amp;#x27;
  end
end
&lt;/pre&gt;

&lt;p&gt;Se testarmos isso na aplica&amp;ccedil;&amp;atilde;o, vamos ver que os admins ainda podem editar o atributo &lt;code&gt;important&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;No controller, precisamos ainda aplicar a op&amp;ccedil;&amp;atilde;o &lt;code&gt;accessible&lt;/code&gt; para a action &lt;code&gt;create&lt;/code&gt;. Se n&amp;oacute;s simplesmente aplicarmos como est&amp;aacute; n&amp;atilde;o vai funcionar.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controllers/articles_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
@article = Article.new(params[:article])
@article.accessible = :all if admin?
&lt;/pre&gt;

&lt;p&gt;N&amp;atilde;o funciona porque a atribui&amp;ccedil;&amp;atilde;o em massa acontece na chamada ao m&amp;eacute;todo &lt;code&gt;new&lt;/code&gt;, ent&amp;atilde;o aplicamos o &lt;code&gt;accessible&lt;/code&gt; tarde demais. Precisamos separar a cria&amp;ccedil;&amp;atilde;o de um novo Article da atribui&amp;ccedil;&amp;atilde;o dos seus atributos e fazer a chamada ao accessible entre os dois.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controllers/articles_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
def create
  @article = Article.new
  @article.accessible = :all if admin?
  @article.attributes = params[:article]
  if @article.save
    flash[:notice] = &amp;quot;Successfully created article.&amp;quot;
    redirect_to @article
  else
    render :action =&amp;gt; &amp;#x27;new&amp;#x27;
  end
end
&lt;/pre&gt;

&lt;p&gt;Voc&amp;ecirc; pode querer fazer isso de forma mais abstrata e remover a duplica&amp;ccedil;&amp;atilde;o no c&amp;oacute;digo das duas actions, mas isso depende de como o seu sistema de permiss&amp;otilde;es funciona, ent&amp;atilde;o vamos deixar por sua conta. Uma altera&amp;ccedil;&amp;atilde;o que ainda vamos fazer &amp;eacute; extrair o m&amp;eacute;todo &lt;code&gt;mass_assignment_authorizer&lt;/code&gt; para fora do modelo &lt;code&gt;Article&lt;/code&gt;, para que isso possa ser usado em todos os modelos da aplica&amp;ccedil;&amp;atilde;o.&lt;/p&gt;

&lt;p&gt;Vamos mover o m&amp;eacute;todo para um initializer. No diret&amp;oacute;rio &lt;code&gt;/config/initializers&lt;/code&gt;, vamos criar um novo arquivo chamado &lt;code&gt;accessible_attributes.rb&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/config/initializers/accessible_attributes.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
class ActiveRecord::Base
  attr_accessible
  attr_accessor :accessible
  
  private
  def mass_assignment_authorizer
    if accessible == :all
      self.class.protected_attributes
    else
      super + (accessible || [])
    end
  end
end
&lt;/pre&gt;

&lt;p&gt;Esse initializer modifica o &lt;code&gt;ActiveRecord::Base&lt;/code&gt; para o comportamento ser aplicado a todos os modelos. Note que ainda podemos chamar o &lt;code&gt;attr_accessible&lt;/code&gt; sem argumentos. Isso significa que o comportamento padr&amp;atilde;o ser&amp;aacute; de forma que nenhum atributo pode ser modificado atrav&amp;eacute;s de atribui&amp;ccedil;&amp;atilde;o em massa. E que vamos ter que adicionar uma chamada a &lt;code&gt;attr_accessible&lt;/code&gt; em cada modelo que tenha atributos edit&amp;aacute;veis. Podemos agora organizar o model Article assim:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/models/article.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
class Article &amp;lt; ActiveRecord::Base
  attr_accessible :name, :content
end
&lt;/pre&gt;

&lt;p&gt;&amp;Eacute; isso. N&amp;oacute;s fizemos o &lt;code&gt;attr_accessible&lt;/code&gt; completamente din&amp;acirc;mico e podemos alterar seus atributos baseado nas permiss&amp;otilde;es dos usu&amp;aacute;rios. O bom disso &amp;eacute; que tudo est&amp;aacute; bloqueado por padr&amp;atilde;o. E o acesso &amp;eacute; dado somente onde especificarmos explicitamente no c&amp;oacute;digo. Isso torna a atribui&amp;ccedil;&amp;atilde;o em massa um problema muito menor, pois por padr&amp;atilde;o todos os atributos est&amp;atilde;o seguros.&lt;/p&gt;</description>
      <pubDate>Tue, 09 Nov 2010 09:40:31 +0000</pubDate>
      <guid>http://pt.asciicasts.com/episodes/237-usando-attr-accessible-dinamicamente</guid>
      <link>http://pt.asciicasts.com/episodes/237-usando-attr-accessible-dinamicamente</link>
    </item>
    <item>
      <title>SimpleForm</title>
      <description>&lt;p&gt;H&amp;aacute; alguns meses, dois epis&amp;oacute;dios falaram sobre a gem Formtastic [&lt;a href="http://railscasts.com/episodes/184-formtastic-part-1"&gt;assistir&lt;/a&gt;, &lt;a href="http://asciicasts.com/episodes/184-formtastic-part-1"&gt;ler&lt;/a&gt;]. Ela oferece uma maneira pr&amp;aacute;tica de gerar o c&amp;oacute;digo para exibir formul&amp;aacute;rios em Rails. Nesse epis&amp;oacute;dio vamos dar uma olhada em uma outra gem chamada &lt;a href="http://github.com/plataformatec/simple_form"&gt;SimpleForm&lt;/a&gt;. Assim como Formtastic, SimpleForm fornece uma maneira simples de gerar o c&amp;oacute;digo dos formul&amp;aacute;rios nas views, se comparado com a maneira padr&amp;atilde;o do Rails. Se voc&amp;ecirc; conhece o Formtastic, ent&amp;atilde;o o SimpleForm vai parecer bem familiar, pois eles s&amp;atilde;o realmente muito semelhantes.&lt;/p&gt; 

&lt;p&gt;A grande pergunta aqui &amp;eacute;: dado que as gems s&amp;atilde;o similares, porque voc&amp;ecirc; deveria escolher usar SimpleForm em vez de Formtastic? Um motivo &amp;eacute; que o SimpleForm &amp;eacute; mais leve. Ela &amp;eacute; tamb&amp;eacute;m mais customiz&amp;aacute;vel e extens&amp;iacute;vel que o Formtastic. Se voc&amp;ecirc; usou o Formtastic e sente que ele se mete no seu caminho, ent&amp;atilde;o &amp;eacute; bom dar uma olhada no SimpleForm.&lt;/p&gt;

&lt;h3&gt;Integrando SimpleForm em uma Aplica&amp;ccedil;&amp;atilde;o&lt;/h3&gt;

&lt;p&gt;Para demonstrar o SimpleForm, vamos atualizar um formul&amp;aacute;rio escrito usando o c&amp;oacute;digo padr&amp;atilde;o de views do Rails para usar o SimpleForm. A aplica&amp;ccedil;&amp;atilde;o &amp;eacute; um simples com&amp;eacute;rcio eletr&amp;ocirc;nico com um n&amp;uacute;mero de produtos, cada qual pertence a uma categora e o formul&amp;aacute;rio que vamos modificar &amp;eacute; o formul&amp;aacute;rio de cria&amp;ccedil;&amp;atilde;o de um novo produto. Esse formul&amp;aacute;rio tem diferentes tipos de campos e ser&amp;aacute; um bom exemplo para usar o SimpleForm.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/481/original/E234I01.png" width="800" height="570" alt="The New Product form."/&gt;
&lt;/div&gt;

&lt;p&gt;Para usar o SimpleForm, temos primeiro que adicionar a gem no &lt;code&gt;Gemfile&lt;/code&gt; da aplica&amp;ccedil;&amp;atilde;o.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/Gemfile&lt;/p&gt;
&lt;pre class="ruby"&gt;
gem &amp;quot;simple_form&amp;quot;
&lt;/pre&gt;

&lt;p&gt;E para termos certeza de que est&amp;aacute; instalada, precisamos executar:&lt;/p&gt;
&lt;pre class="terminal"&gt;
$ bundle install
&lt;/pre&gt;

&lt;p&gt;Agora que a gem est&amp;aacute; instalada, precisamos executar um &lt;code&gt;generator&lt;/code&gt; que adicionar&amp;aacute; uns poucos arquivos que o SimpleForm precisa dentro da nossa aplica&amp;ccedil;&amp;atilde;o.&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ rails g simple_form:install
    &lt;span class="passed"&gt;create&lt;/span&gt;  config/initializers/simple_form.rb
    &lt;span class="passed"&gt;create&lt;/span&gt;  config/locales/simple_form.en.yml
    &lt;span class="passed"&gt;create&lt;/span&gt;  lib/templates/erb/scaffold/_form.html.erb
&lt;/pre&gt;    

&lt;p&gt;Esses arquivos gerados s&amp;atilde;o usados principalmente para customiza&amp;ccedil;&amp;atilde;o e iremos dar uma olhada neles rapidamente. Antes, vamos atualizar o c&amp;oacute;digo do nosso formul&amp;aacute;rio de cadastro de produtos que est&amp;aacute; assim:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/view/products/new.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;
&amp;lt;%= form_for @product do |f| %&amp;gt;
  &amp;lt;%= f.error_messages %&amp;gt;
  &amp;lt;p&amp;gt;
    &amp;lt;%= f.label :name %&amp;gt;
    &amp;lt;%= f.text_field :name %&amp;gt;
  &amp;lt;/p&amp;gt;
  &amp;lt;p&amp;gt;
    &amp;lt;%= f.label :price %&amp;gt;
    &amp;lt;%= f.text_field :price %&amp;gt;
  &amp;lt;/p&amp;gt;
  &amp;lt;p&amp;gt;
    &amp;lt;%= f.label :released_on %&amp;gt;
    &amp;lt;%= f.date_select :released_on %&amp;gt;
  &amp;lt;/p&amp;gt;
  &amp;lt;p&amp;gt;
    &amp;lt;%= f.label :category_id %&amp;gt;
    &amp;lt;%= f.collection_select :category_id, Category.all, :id, :name %&amp;gt;
  &amp;lt;/p&amp;gt;
  &amp;lt;p&amp;gt;
    &amp;lt;%= f.label :rating %&amp;gt;
    &amp;lt;%= f.select :rating, 1..5 %&amp;gt;
  &amp;lt;/p&amp;gt;
  &amp;lt;p&amp;gt;
    &amp;lt;%= f.label :discontinued %&amp;gt;
    &amp;lt;%= f.check_box :discontinued %&amp;gt;
  &amp;lt;/p&amp;gt;
  &amp;lt;p&amp;gt;&amp;lt;%= f.submit %&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/pre&gt;

&lt;p&gt;As duas principais mudan&amp;ccedil;as que precisamos fazer s&amp;atilde;o substituir o &lt;code&gt;form_for&lt;/code&gt; pelo &lt;code&gt;simple_form_for&lt;/code&gt; e substituir cada par de labels e inputs com um dos m&amp;eacute;todos do SimpleForm.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/view/products/new.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;
&amp;lt;%= simple_form_for @product do |f| %&amp;gt;
  &amp;lt;%= f.error_messages %&amp;gt;
  &amp;lt;%= f.input :name %&amp;gt;
  &amp;lt;%= f.input :price %&amp;gt;
  &amp;lt;%= f.input :released_on %&amp;gt;
  &amp;lt;%= f.association :category %&amp;gt;
  &amp;lt;%= f.input :rating %&amp;gt;
  &amp;lt;%= f.input :discontinued %&amp;gt;
  &amp;lt;%= f.button :submit %&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Para a maior parte dos controles no formul&amp;aacute;rio, podemos usar o m&amp;eacute;todo&lt;code&gt;f.input&lt;/code&gt;. Um campo onde precisamos usar algo diferente &amp;eacute; o &lt;code&gt;category&lt;/code&gt;. No formul&amp;aacute;rio original, esse campo usava &lt;code&gt;collection_select&lt;/code&gt; para renderizar um menu drop down contendo todas as categorias.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/view/products/new.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;
&amp;lt;%= f.collection_select :category_id, Category.all, :id, :name %&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Com o SimpleForm, podemos substituir por &lt;code&gt;f.association&lt;/code&gt;, que faz a mesma coisa.&lt;/p&gt;

&lt;p&gt;Podemos recarregar o formul&amp;aacute;rio e ver como ele est&amp;aacute; sendo renderizado pelo SimpleForm.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/482/original/E234I02.png" width="800" height="490" alt="The form rendered with SimpleForm."/&gt;
&lt;/div&gt;

&lt;p&gt;O formul&amp;aacute;rio parece um pouco diferente agora pois n&amp;atilde;o tem mais o estilo que tinha anteriormente. Mas &amp;eacute; f&amp;aacute;cil alterar nosso css para adicionar alguns estilos e classes que o SimpleForm usa em seus formul&amp;aacute;rios.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/public/stylesheets/application.css&lt;/p&gt;
&lt;pre class="css"&gt;
.simple_form label {
  float: left;
  width: 100px;
  text-align: right;
  margin: 2px 10px;
}

.simple_form div.input {
  margin-bottom: 10px;
}

.simple_form div.boolean, .simple_form input[type=&amp;#x27;submit&amp;#x27;] {
  margin-left: 120px;
}

.simple_form div.boolean label {
  float: none;
  margin: 0;
}
&lt;/pre&gt;

&lt;p&gt;Quando voc&amp;ecirc; usar o SimpleForm em sua pr&amp;oacute;pria aplica&amp;ccedil;&amp;atilde;o, vai querer customizar o estilo de acordo com o design da sua aplica&amp;ccedil;&amp;atilde;o. O CSS acima vai te dar uma ideia de quais os nomes das classes usados nos elementos HTML que o SimpleForm gera. Com o estilo acima aplicado, nosso formul&amp;aacute;rio parece um pouco melhor.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/483/original/E234I03.png" width="800" height="469" alt="The form now has CSS added."/&gt;
&lt;/div&gt;

&lt;h3&gt;Personalizando Campos&lt;/h3&gt;

&lt;p&gt;Para os campos que usamos &lt;code&gt;f.input&lt;/code&gt;, o SimpleForm automaticamente detectou cada tipo de coluna, de modo que o campo &amp;quot;Released on&amp;quot; est&amp;aacute; renderizado como data e &amp;quot;Discontinued&amp;quot; est&amp;aacute; renderizado com um checkbox, pois ele representa uma coluna &lt;code&gt;boolean&lt;/code&gt;. Sendo uma associa&amp;ccedil;&amp;atilde;o, o campo &amp;quot;Category&amp;quot; foi renderizado como um menu drop down com uma op&amp;ccedil;&amp;atilde;o em branco. Se voc&amp;ecirc; quiser customizar esse campo, pode fazer isso adicionando algumas op&amp;ccedil;&amp;otilde;es. Por exemplo, podemos remover a op&amp;ccedil;&amp;atilde;o em branco do &amp;quot;Category&amp;quot; adicionando a op&amp;ccedil;&amp;atilde;o &lt;code&gt;:include_blank&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/view/products/new.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;
&amp;lt;%= f.association :category, :include_blank =&amp;gt; false %&amp;gt;
&lt;/pre&gt;

&lt;p&gt;O formul&amp;aacute;rio original tem uma lista drop down para o campo rating, mas isso agora foi substitu&amp;iacute;do por um campo texto. Podemos restaurar esse drop down usando a op&amp;ccedil;&amp;atilde;o &lt;code&gt;:collection&lt;/code&gt; passando um range pra ela.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/view/products/new.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;
&amp;lt;%= f.input :rating, :collection =&amp;gt; 1..5 %&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Se queremos a lista renderizada como radio buttons, podemos usar a op&amp;ccedil;&amp;atilde;o &lt;code&gt;:as&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/view/products/new.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;
&amp;lt;%= f.input :rating, :collection =&amp;gt; 1..5, :as =&amp;gt; :radio %&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Quando recarregamos o formul&amp;aacute;rio, vemos que a op&amp;ccedil;&amp;atilde;o em branco n&amp;atilde;o existe mais no menu drop down e que o campo rating foi renderizado como radio buttons.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/484/original/E234I04.png" width="800" height="423" alt="The rating field is now rendered as a series of radio buttons."/&gt;
&lt;/div&gt;

&lt;p&gt;Outra grande caracter&amp;iacute;stica do SimpleForm &amp;eacute; detectar automaticamente os campos obrigat&amp;oacute;rios. Podemos demonstrar isso fazendo os campos &lt;code&gt;name&lt;/code&gt; e &lt;code&gt;price&lt;/code&gt; obrigat&amp;oacute;rios no modelo &lt;code&gt;Product&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/models/product.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
class Product &amp;lt; ActiveRecord::Base
  attr_accessible :name, :price, :released_on, :category_id, 
  :rating, :discontinued
  belongs_to :category  
  validates_presence_of :name, :price
end
&lt;/pre&gt;

&lt;p&gt;Isso &amp;eacute; tudo que precisamos fazer. Quando recarregarmos o formul&amp;aacute;rio, vamos ver esses campos marcados com aster&amp;iacute;scos e se tentarmos submeter o formul&amp;aacute;rio sem preencher esses campos, vamos ver uma mensagem de erro.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/485/original/E234I05.png" width="800" height="586" alt="The form showing the required field errors."/&gt;
&lt;/div&gt;

&lt;p&gt;Podemos tamb&amp;eacute;m adicionar um aviso para cada campo. Vamos supor que queremos informar que o pre&amp;ccedil;o deve ser dado em libras esterlinas. S&amp;oacute; precisamos adicionar uma op&amp;ccedil;&amp;atilde;o &lt;code&gt;:hint&lt;/code&gt; a esse campo.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/apps/views/products/_form.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;
&amp;lt;%= f.input :price, :hint =&amp;gt; &amp;quot;prices should be in UKP.&amp;quot; %&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Isso adicionar&amp;aacute; uma mensagem informativa depois do campo no formul&amp;aacute;rio.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/486/original/E234I06.png" width="800" height="442" alt="The Price field now has a hint."/&gt;
&lt;/div&gt;

&lt;p&gt;H&amp;aacute; mais informa&amp;ccedil;&amp;otilde;es sobre as op&amp;ccedil;&amp;otilde;es que podem ser usadas no &lt;a href="http://github.com/plataformatec/simple_form#readme"&gt;README&lt;/a&gt; do SimpleForm. Vale a pena dar uma olhada no &lt;a href="http://github.com/justinfrench/formtastic#readme"&gt;README do Formtastic&lt;/a&gt; tamb&amp;eacute;m, pois muitas op&amp;ccedil;&amp;otilde;es que ele usa tamb&amp;eacute;m podem ser usadas pelo SimpleForm.&lt;/p&gt;

&lt;h3&gt;Personalizando o SimpleForm&lt;/h3&gt;

&lt;p&gt;Quando executamos o gerador do SimpleForm, ele criou tr&amp;ecirc;s arquivos.&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ rails g simple_form:install
    &lt;span class="passed"&gt;create&lt;/span&gt;  config/initializers/simple_form.rb
    &lt;span class="passed"&gt;create&lt;/span&gt;  config/locales/simple_form.en.yml
    &lt;span class="passed"&gt;create&lt;/span&gt;  lib/templates/erb/scaffold/_form.html.erb
&lt;/pre&gt;

&lt;p&gt;Se quisermos customizar o SimpleForm em toda a aplica&amp;ccedil;&amp;atilde;o, podemos modificar esses arquivos. O primeiro cont&amp;eacute;m algumas op&amp;ccedil;&amp;otilde;es comentadas e muitas configura&amp;ccedil;&amp;otilde;es podem ser feitas aqui. Por exemplo, podemos alterar a ordem que cada campo &amp;eacute; renderizado; podemos alterar a tag html que envolve cada campo e podemos alterar o tamanho padr&amp;atilde;o de cada campo de texto. Queremos campos de texto mais estreitos na nossa aplica&amp;ccedil;&amp;atilde;o, ent&amp;atilde;o vamos alterar o valor padr&amp;atilde;o de &lt;code&gt;50&lt;/code&gt; para &lt;code&gt;30&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/config/initializers/simple_form.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
# Use this setup block to configure all options available in SimpleForm.
SimpleForm.setup do |config|

  # Other options removed...

  # Default size for text inputs.
  config.default_input_size = 30
end
&lt;/pre&gt;

&lt;p&gt;Outro arquivo que foi gerado, foi de idiomas e &amp;eacute; onde podemos internacionalizar os formul&amp;aacute;rios.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/config/locales/simple_form.en.yml&lt;/p&gt;
&lt;pre class="ruby"&gt;
en:
  simple_form:
    &amp;quot;yes&amp;quot;: &amp;#x27;Yes&amp;#x27;
    &amp;quot;no&amp;quot;: &amp;#x27;No&amp;#x27;
    required:
      text: &amp;#x27;required&amp;#x27;
      mark: &amp;#x27;*&amp;#x27;
      # You can uncomment the line below if you need to overwrite the whole required html.
      # When using html, text and mark won&amp;#x27;t be used.
      # html: &amp;#x27;&lt;abbr title="required"&gt;*&lt;/abbr&gt;&amp;#x27;
    error_notification:
      default_message: &amp;quot;Some errors were found, please take a look:&amp;quot;
    # Labels and hints examples
    # labels:
    #   password: &amp;#x27;Password&amp;#x27;
    #   user:
    #     new:
    #       email: &amp;#x27;E-mail para efetuar o sign in.&amp;#x27;
    #     edit:
    #       email: &amp;#x27;E-mail.&amp;#x27;
    # hints:
    #   username: &amp;#x27;User name to sign in.&amp;#x27;
    #   password: &amp;#x27;No special characters, please.&amp;#x27;
&lt;/pre&gt;

&lt;p&gt;Mesmo se a aplica&amp;ccedil;&amp;atilde;o n&amp;atilde;o precisa mostrar m&amp;uacute;ltiplos idiomas esse arquivo ainda &amp;eacute; &amp;uacute;til para alterar alguns textos do SimpleForm, como o texto que &amp;eacute; apresentado nos campos obrigat&amp;oacute;rios.&lt;/p&gt;

&lt;p&gt;O &amp;uacute;ltimo arquivo gerado sobrescreve o partial de formul&amp;aacute;rios do gerador do scaffold.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/lib/templates/erb/scaffold/_form.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;
&amp;lt;%%= simple_form_for(@&amp;lt;%= singular_name %&amp;gt;) do |f| %&amp;gt;
  &amp;lt;%% if @&amp;lt;%= singular_name %&amp;gt;.errors.any? %&amp;gt;
    &amp;lt;div id=&amp;quot;error_explanation&amp;quot;&amp;gt;
      &amp;lt;h2&amp;gt;&amp;lt;%%= pluralize(@&amp;lt;%= singular_name %&amp;gt;.errors.count, &amp;quot;error&amp;quot;) %&amp;gt; prohibited this &amp;lt;%= singular_name %&amp;gt; from being saved:&amp;lt;/h2&amp;gt;

      &amp;lt;ul&amp;gt;
      &amp;lt;%% @&amp;lt;%= singular_name %&amp;gt;.errors.full_messages.each do |msg| %&amp;gt;
        &amp;lt;li&amp;gt;&amp;lt;%%= msg %&amp;gt;&amp;lt;/li&amp;gt;
      &amp;lt;%% end %&amp;gt;
      &amp;lt;/ul&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;%% end %&amp;gt;

  &amp;lt;div class=&amp;quot;inputs&amp;quot;&amp;gt;
  &amp;lt;%- attributes.each do |attribute| -%&amp;gt;
    &amp;lt;%%= f.&amp;lt;%= attribute.reference? ? :association : :input %&amp;gt; :&amp;lt;%= attribute.name %&amp;gt; %&amp;gt;
  &amp;lt;%- end -%&amp;gt;
  &amp;lt;/div&amp;gt;

  &amp;lt;div class=&amp;quot;actions&amp;quot;&amp;gt;
    &amp;lt;%%= f.button :submit %&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;%% end %&amp;gt;
&lt;/pre&gt;

&lt;p&gt;No Rails 3, podemos sobrescrever qualquer arquivo template de um &lt;code&gt;generator&lt;/code&gt; adicionando em nossa aplica&amp;ccedil;&amp;atilde;o. Ent&amp;atilde;o se quisermos customizar o jeito que um generator funciona, para atender a nossa forma de trabalho, podemos simplesmente criar um novo arquivo template.&lt;/p&gt;

&lt;p&gt;Por esse epis&amp;oacute;dio &amp;eacute; s&amp;oacute;. O SimpleForm torna f&amp;aacute;cil criar formul&amp;aacute;rios em suas aplica&amp;ccedil;&amp;otilde;es Rails e vale muito a pena dar uma olhada nele.&lt;/p&gt;</description>
      <pubDate>Wed, 13 Oct 2010 21:54:08 +0000</pubDate>
      <guid>http://pt.asciicasts.com/episodes/234-simple-form</guid>
      <link>http://pt.asciicasts.com/episodes/234-simple-form</link>
    </item>
    <item>
      <title>Atualizando para o Rails 3 Parte 3</title>
      <description>&lt;p&gt;Neste epis&amp;oacute;dio, vamos terminar nossa s&amp;eacute;rie sobre a atualiza&amp;ccedil;&amp;atilde;o de uma aplica&amp;ccedil;&amp;atilde;o Rails 2 para o Rails 3. Fizemos um bom progresso at&amp;eacute; agora, temos todos os testes da aplica&amp;ccedil;&amp;atilde;o passando e usamos o plugin de atualiza&amp;ccedil;&amp;atilde;o do Rails para encontrar e corrigir a maioria das &amp;aacute;reas que necessitam de atualiza&amp;ccedil;&amp;atilde;o para o Rails 3. Ainda existem coisas que precisam ser corrigidas nas views e vamos nos concentrar nisso neste epis&amp;oacute;dio.&lt;/p&gt;

&lt;h3&gt;Removendo Avisos de C&amp;oacute;digo Obsoleto&lt;/h3&gt;

&lt;p&gt;Antes de come&amp;ccedil;armos consertando as views, vamos dar outra olhada nos testes. At&amp;eacute; o final do &amp;uacute;ltimo epis&amp;oacute;dio, todos os testes da aplica&amp;ccedil;&amp;atilde;o estavam passando, mas havia um grande n&amp;uacute;mero de avisos de c&amp;oacute;digo obsoleto (deprecated) mostrado enquanto executavam. Vamos executar os testes novamente, agora para ver se podemos reduzir o n&amp;uacute;mero de avisos.&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ rake spec

# large amount of output snipped.

.DEPRECATION WARNING: error_messages_for was removed from Rails and is now available as a plugin. Please install it with `rails plugin install git://github.com/rails/dynamic_form.git`. (called from _app_views_sponsors__form_html_erb___2363957037552137609_2171491000_4161310651677273387 at /Users/eifion/rails/apps_for_asciicasts/ep227/railscasts/app/views/sponsors/_form.html.erb:2)
&lt;span class="passed"&gt;...................................................&lt;/span&gt;

&lt;span class="passed"&gt;Finished in 3.24 seconds&lt;/span&gt;
&lt;span class="passed"&gt;152 examples, 0 failures&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;Os testes continuam passando, mas ainda h&amp;aacute; um grande n&amp;uacute;mero de advert&amp;ecirc;ncias. Felizmente, a maioria delas s&amp;atilde;o duplicadas ent&amp;atilde;o n&amp;atilde;o deve dar muito trabalho retir&amp;aacute;-las.&lt;/p&gt;

&lt;p&gt;Cortamos a maior parte da sa&amp;iacute;da do &lt;code&gt;rake spec&lt;/code&gt; executado acima, mas deixamos o aviso final. Os m&amp;eacute;todos &lt;code&gt;error_messages_for&lt;/code&gt; e &lt;code&gt;error_messages_on&lt;/code&gt; est&amp;atilde;o obsoletos no Rails 3 e podemos substitu&amp;iacute;-los por um c&amp;oacute;digo personalizado que percorre o &lt;code&gt;errors.full_messages&lt;/code&gt; para exibir os erros. Os m&amp;eacute;todos antigos ainda est&amp;atilde;o dispon&amp;iacute;veis como um plugin, assim n&amp;oacute;s vamos tomar o caminho mais f&amp;aacute;cil e usar esse plugin. As instru&amp;ccedil;&amp;otilde;es para instal&amp;aacute;-lo foram mostradas no aviso acima.&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ rails plugin install git://github.com/rails/dynamic_form.git
Initialized empty Git repository in /Users/eifion/rails/apps_for_asciicasts/ep227/railscasts/vendor/plugins/dynamic_form/.git/
remote: Counting objects: 22, done.
remote: Compressing objects: 100% (17/17), done.
remote: Total 22 (delta 2), reused 0 (delta 0)
Unpacking objects: 100% (22/22), done.
From git://github.com/rails/dynamic_form
 * branch            HEAD       -&amp;gt; FETCH_HEAD
&lt;/pre&gt; 
 
&lt;p&gt;Com o plugin instalado, quando executamos &lt;code&gt;rake spec&lt;/code&gt; novamente, o aviso desapareceu. H&amp;aacute; outros erros, por&amp;eacute;m, e um dos que aparecem com frequ&amp;ecirc;ncia &amp;eacute; o seguinte:&lt;/p&gt;

&lt;pre class="terminal"&gt;
DEPRECATION WARNING: subclasses is deprecated and will be removed from Rails 3.0 (use descendants instead). (called from block (2 levels) in load_models 
at /Users/eifion/.rvm/gems/ruby-1.9.2-rc2/gems/thinking-sphinx-2.0.0.rc1/lib/thinking_sphinx/context.rb:58)
&lt;/pre&gt;

&lt;p&gt;Esse erro &amp;eacute; da biblioteca &lt;a href="http://freelancing-god.github.com/ts/en/"&gt;Thinking Sphinx&lt;/a&gt;. Se voc&amp;ecirc; estiver recebendo erros de um plugin, vale a pena verificar o issue tracker desse plugin para ver se existem problemas constantes relacionados com o erro que voc&amp;ecirc; est&amp;aacute; vendo. Sen&amp;atilde;o podemos adicionar um e talvez isso seja corrigido para a pr&amp;oacute;xima vers&amp;atilde;o. (Alternativamente, voc&amp;ecirc; pode sempre dar fork no c&amp;oacute;digo e corrigir o erro voc&amp;ecirc; mesmo.)&lt;/p&gt;
  
&lt;p&gt;No caso do Thinking Sphinx, esse problema j&amp;aacute; foi detectado e corrigido, mas n&amp;atilde;o foi inclu&amp;iacute;do na vers&amp;atilde;o mais recente da gem no momento da escrita desse epis&amp;oacute;dio. Para remover esse aviso de nossa aplica&amp;ccedil;&amp;atilde;o, podemos dizer ao bundler para obter o c&amp;oacute;digo do Thinking Sphinx de um reposit&amp;oacute;rio git em vez de uma gem.&lt;/p&gt;

&lt;p&gt;Assim, em nossa Gemfile, em vez de incluir Thinking Sphinx da seguinte forma:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/Gemfile&lt;/p&gt;
&lt;pre class="ruby"&gt;
gem &amp;#x27;thinking-sphinx&amp;#x27;, &amp;#x27;&amp;gt;=2.0.0.rc1&amp;#x27;, :require =&amp;gt; &amp;#x27;thinking_sphinx&amp;#x27;
&lt;/pre&gt;

&lt;p&gt;vamos inclu&amp;iacute;-lo assim:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/Gemfile&lt;/p&gt;
&lt;pre class="ruby"&gt;
gem &amp;#x27;thinking-sphinx&amp;#x27;, :require =&amp;gt; &amp;#x27;thinking_sphinx&amp;#x27;, :git =&amp;gt; &amp;quot;git://github.com/freelancing-god/thinking-sphinx.git&amp;quot;, :branch =&amp;gt; &amp;quot;rails3&amp;quot;
&lt;/pre&gt;

&lt;p&gt;Temos que executar &lt;code&gt;bundle install&lt;/code&gt; novamente para que ele baixe o Thinking Sphinx do seu reposit&amp;oacute;rio git. Nossa aplica&amp;ccedil;&amp;atilde;o agora usar&amp;aacute; essa vers&amp;atilde;o em vez da &amp;uacute;ltima gem. Quando rodamos nossos specs novamente, todas passam sem avisos. &lt;/p&gt;

&lt;pre class="terminal"&gt;
$ rake spec
&lt;span class="passed"&gt;........................................................................................................................................................&lt;/span&gt;

&lt;span class="passed"&gt;Finished in 3.3 seconds&lt;/span&gt;
&lt;span class="passed"&gt;152 examples, 0 failures&lt;/span&gt;
&lt;/pre&gt;

&lt;h3&gt;Consertando as Views&lt;/h3&gt;

&lt;p&gt;Com os avisos de c&amp;oacute;digo obsoleto resolvidos, podemos nos concentrar nas views. Ao executarmos a aplica&amp;ccedil;&amp;atilde;o, o primeiro erro que se destaca &amp;eacute; a aus&amp;ecirc;ncia da barra lateral na p&amp;aacute;gina de epis&amp;oacute;dios.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/443/original/E227I01.png" width="805" height="550" alt="The episodes page with the missing sidebar."/&gt;
&lt;/div&gt;

&lt;p&gt;Uma parte da p&amp;aacute;gina t&amp;atilde;o grande como essa deve ser coberta por um teste, mesmo que apenas para testar a sua exist&amp;ecirc;ncia. Se f&amp;ocirc;ssemos atualizar essa aplica&amp;ccedil;&amp;atilde;o para produ&amp;ccedil;&amp;atilde;o, ent&amp;atilde;o ir&amp;iacute;amos escrever um teste para cobrir essa funcionalidade, mas n&amp;atilde;o vamos fazer isso aqui.&lt;/p&gt; 

&lt;p&gt;Se dermos uma olhada no arquivo de layout, o c&amp;oacute;digo que gera a barra lateral &amp;eacute; o seguinte:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/views/layouts/application.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;
&amp;lt;%= yield(:side) || render(:partial =&amp;gt; &amp;#x27;shared/side&amp;#x27;) %&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Esse c&amp;oacute;digo ir&amp;aacute; produzir o conte&amp;uacute;do da barra lateral e se ele retornar &lt;code&gt;nil&lt;/code&gt; ser&amp;aacute; renderizado o partial da lateral em seu lugar. O problema aqui &amp;eacute; que em vers&amp;otilde;es anteriores do Rails, &lt;code&gt;yield&lt;/code&gt; retornava &lt;code&gt;nil&lt;/code&gt; se a chamada apropriada ao &lt;code&gt;content_for&lt;/code&gt; estivesse faltando na p&amp;aacute;gina, enquanto no Rails 3 retorna uma string vazia, ent&amp;atilde;o a segunda parte do c&amp;oacute;digo nunca ser&amp;aacute; chamada.&lt;/p&gt;

&lt;p&gt;Para corrigir isso, podemos usar o &lt;code&gt;content_for?&lt;/code&gt; que retorna &lt;code&gt;true&lt;/code&gt; se a &amp;aacute;rea de conte&amp;uacute;do foi definida para uma p&amp;aacute;gina. Se tiver sido definida, vamos mostrar seu conte&amp;uacute;do, caso contr&amp;aacute;rio vamos usar a barra lateral.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/views/layouts/application.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;
&amp;lt;%= content_for?(:side) ? yield(:side) : render(:partial=&amp;gt; &amp;#x27;shared/side&amp;#x27;) %&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Ao recarregar a p&amp;aacute;gina agora, a barra lateral &amp;eacute; exibida.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/444/original/E227I02.png" width="801" height="545" alt="The sidebar has been restored."/&gt;
&lt;/div&gt;

&lt;p&gt;H&amp;aacute; ainda outros problemas nas views para serem corrigidos. Se formos ver a p&amp;aacute;gina de um &amp;uacute;nico epis&amp;oacute;dio, veremos que a exibi&amp;ccedil;&amp;atilde;o das notas est&amp;aacute; sendo escapada. &lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/445/original/E227I03.png" width="801" height="545" alt="The escaped HTML on the episode page."/&gt;
&lt;/div&gt;

&lt;p&gt;O conte&amp;uacute;do para aquela parte da p&amp;aacute;gina passa pelo m&amp;eacute;todo &lt;code&gt;textilize&lt;/code&gt; que &amp;eacute; definido no m&amp;oacute;dulo &lt;code&gt;ApplicationHelper&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/helpers/application_helper.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
module ApplicationHelper
  def textilize(text)
    Textilizer.new(text).to_html unless text.blank?
  end
end
&lt;/pre&gt;

&lt;p&gt;Esse m&amp;eacute;todo retorna um HTML como uma string. No Rails 3, se voc&amp;ecirc; vai passar uma string de HTML para ser exibida em uma view, a string dever&amp;aacute; ser marcada como HTML-safe, caso contr&amp;aacute;rio ser&amp;aacute; automaticamente escapada. Para marcar a string como segura, s&amp;oacute; precisamos chamar o m&amp;eacute;todo &lt;code&gt;html_safe&lt;/code&gt; para ela.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/helpers/application_helper.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
module ApplicationHelper
  def textilize(text)
    Textilizer.new(text).to_html.html_safe unless text.blank?
  end
end
&lt;/pre&gt;

&lt;p&gt;Agora, a string foi marcada como segura e n&amp;atilde;o ser&amp;aacute; mais escapada. Isso &amp;eacute; abordado com mais detalhes no epis&amp;oacute;dio 204 [&lt;a href="http://railscasts.com/episodes/204-xss-protection-in-rails-3"&gt;assistir&lt;/a&gt;, &lt;a href="http://asciicasts.com/episodes/204-xss-protection-in-rails-3"&gt;ler&lt;/a&gt;]. Ao recarregarmos a p&amp;aacute;gina novamente a exibi&amp;ccedil;&amp;atilde;o das notas &amp;eacute; renderizada corretamente.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/446/original/E227I04.png" width="801" height="545" alt="The show notes are now shown correctly."/&gt;
&lt;/div&gt;

&lt;p&gt;H&amp;aacute; ainda um pequeno problema nessa p&amp;aacute;gina: a barra de t&amp;iacute;tulo deve incluir o nome do epis&amp;oacute;dio. Esse problema &amp;eacute; espec&amp;iacute;fico para a forma como os t&amp;iacute;tulos s&amp;atilde;o tratados nessa aplica&amp;ccedil;&amp;atilde;o. Um m&amp;eacute;todo helper &lt;code&gt;title&lt;/code&gt; &amp;eacute; usado, o qual define uma vari&amp;aacute;vel de inst&amp;acirc;ncia ao inv&amp;eacute;s de usar &lt;code&gt;content_for&lt;/code&gt; para definir o t&amp;iacute;tulo.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/helpers/layout_helper.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
module LayoutHelper
  def title(page_title, show_title = true)
    @content_for_title = page_title.to_s
    @show_title = show_title
  end
end
&lt;/pre&gt;

&lt;p&gt;Para corrigir isso, devemos definir o conte&amp;uacute;do para o t&amp;iacute;tulo usando &lt;code&gt;content_for&lt;/code&gt;, assim:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/helpers/layout_helper.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
module LayoutHelper
  def title(page_title, show_title = true)
    content_for(:title, page_title.to_s)
    @show_title = show_title
  end
end
&lt;/pre&gt;

&lt;p&gt;Agora, quando chamamos &lt;code&gt;yield(:title)&lt;/code&gt; no layout, o t&amp;iacute;tulo ser&amp;aacute; definido corretamente. Podemos passar o conte&amp;uacute;do em si como um bloco ou, como temos aqui, como um segundo argumento.&lt;/p&gt;

&lt;h3&gt;Corrigindo Links de Destroy&lt;/h3&gt;

&lt;p&gt;O erro seguinte &amp;eacute; na se&amp;ccedil;&amp;atilde;o de administra&amp;ccedil;&amp;atilde;o da aplica&amp;ccedil;&amp;atilde;o. Na p&amp;aacute;gina a seguir est&amp;aacute; uma lista de objetos do modelo, cada um com um link &lt;code&gt;edit&lt;/code&gt; e &lt;code&gt;destroy&lt;/code&gt;.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/447/original/E227I05.png" width="800" height="480" alt="The Spam Questions page."/&gt;
&lt;/div&gt;

&lt;p&gt;O problema aqui est&amp;aacute; com os links &lt;code&gt;destroy&lt;/code&gt;. Quando clicamos em um deles, seremos levados para a action show, em vez da action &lt;code&gt;destroy&lt;/code&gt;. A raz&amp;atilde;o pela qual a a&amp;ccedil;&amp;atilde;o de exclus&amp;atilde;o n&amp;atilde;o &amp;eacute; chamada, &amp;eacute; que o JavaScript usado para os links &lt;code&gt;destroy&lt;/code&gt; foi feito n&amp;atilde;o obstrutivo no Rails 3. Se olharmos no HTML para um dos links, n&amp;oacute;s vamos ver que o JavaScript n&amp;atilde;o &amp;eacute; mais embutido no link &lt;code&gt;destroy&lt;/code&gt;. Em vez disso, h&amp;aacute; dois atributos HTML 5 personalizados que come&amp;ccedil;am com &lt;code&gt;data-&lt;/code&gt; e deve haver algum JavaScript que ir&amp;aacute; detectar esses atributos e alterar a requisi&amp;ccedil;&amp;atilde;o para uma requisi&amp;ccedil;&amp;atilde;o DELETE.&lt;/p&gt;

&lt;pre class="ruby"&gt;
&amp;lt;tr&amp;gt;
  &amp;lt;td&amp;gt;What does the M stand for in MVC?&amp;lt;/td&amp;gt;
  &amp;lt;td&amp;gt;model&amp;lt;/td&amp;gt;
  &amp;lt;td&amp;gt;&amp;lt;a href=&amp;quot;/spam_questions/1/edit&amp;quot;&amp;gt;Edit&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;
  &amp;lt;td&amp;gt;&amp;lt;a href=&amp;quot;/spam_questions/1&amp;quot; data-confirm=&amp;quot;Are you sure?&amp;quot; data-method=&amp;quot;delete&amp;quot; rel=&amp;quot;nofollow&amp;quot;&amp;gt;Destroy&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Como essa aplica&amp;ccedil;&amp;atilde;o usa jQuery, &amp;eacute; preciso baixar o arquivo &lt;a href="http://github.com/rails/jquery-ujs/blob/master/src/rails.js"&gt;rails.js&lt;/a&gt; personalizado do projeto jquery-UJS. Se estiv&amp;eacute;ssemos usando Prototype, ent&amp;atilde;o n&amp;atilde;o ter&amp;iacute;amos necessidade de fazer isso, pois o arquivo correto j&amp;aacute; est&amp;aacute; inclu&amp;iacute;do no diret&amp;oacute;rio &lt;code&gt;/public/javascripts&lt;/code&gt;. Fizemos o download do arquivo e copiamos para o diret&amp;oacute;rio &lt;code&gt;javascripts&lt;/code&gt;, ent&amp;atilde;o vamos precisar adicionar uma refer&amp;ecirc;ncia a ele na tag &lt;code&gt;head&lt;/code&gt; do layout. N&amp;oacute;s tamb&amp;eacute;m precisamos adicionar uma meta tag csrf para prevenir ataques cross-site request forgery.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/application/layouts/application.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;
&amp;lt;%= javascript_include_tag &amp;#x27;jquery&amp;#x27;, &amp;#x27;rails&amp;#x27;, &amp;#x27;application&amp;#x27; %&amp;gt;
&amp;lt;%= csrf_meta_tag %&amp;gt;
&lt;/pre&gt;

&lt;p&gt;O uso de JavaScript n&amp;atilde;o obstrutivo no Rails 3 &amp;eacute; abordado no epis&amp;oacute;dio 205 [&lt;a href="http://railscasts.com/episodes/205-unobtrusive-javascript"&gt;assistir&lt;/a&gt;, &lt;a href="http://asciicasts.com/episodes/205-unobtrusive-javascript"&gt;ler&lt;/a&gt;].&lt;/p&gt;  

&lt;p&gt;Como estamos no arquivo de layout, vamos atualizar a aplica&amp;ccedil;&amp;atilde;o para usar HTML 5, alterando o DOCTYPE e a tag &lt;code&gt;html&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/application/layouts/application.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Existem outras coisas que precisamos fazer para tornar a aplica&amp;ccedil;&amp;atilde;o totalmente HTML 5. Podemos verificar o c&amp;oacute;digo atrav&amp;eacute;s de um validador para descobrir o que tem que ser mudado.&lt;/p&gt;

&lt;p&gt;Com o novo arquivo &lt;code&gt;rails.js&lt;/code&gt; no lugar, quando recarregarmos a p&amp;aacute;gina Spam Questions, e tentarmos deletar uma das perguntas, a confirma&amp;ccedil;&amp;atilde;o JavaScript ser&amp;aacute; mostrada e a pergunta ser&amp;aacute; apagada, se clicarmos em OK.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/448/original/E227I06.png" width="420" height="153" alt="The destroy links now work."/&gt;
&lt;/div&gt;

&lt;p&gt;A &amp;uacute;ltima altera&amp;ccedil;&amp;atilde;o que podemos fazer com o c&amp;oacute;digo da view &amp;eacute; remover todas as chamadas ao m&amp;eacute;todo &lt;code&gt;h&lt;/code&gt;. Nas views do Rails 2, qualquer sa&amp;iacute;da que precis&amp;aacute;vamos escapar c&amp;oacute;digo HTML tinha que ser tratada com o m&amp;eacute;todo &lt;code&gt;h&lt;/code&gt;. Todas as sa&amp;iacute;das no Rails 3 s&amp;atilde;o escapadas por padr&amp;atilde;o. Ent&amp;atilde;o podemos arrumar as views, passando por elas e eliminando esses m&amp;eacute;todos &lt;code&gt;h&lt;/code&gt;. Esse assunto foi coberto no epis&amp;oacute;dio 204 [&lt;a href="http://railscasts.com/episodes/204-xss-protection-in-rails-3"&gt;assistir&lt;/a&gt;, &lt;a href="http://asciicasts.com/episodes/204-xss-protection-in-rails-3"&gt;ler&lt;/a&gt;]. Deixar o m&amp;eacute;todo n&amp;atilde;o ir&amp;aacute; causar quaisquer problemas, mas o c&amp;oacute;digo ficar&amp;aacute; mais limpo sem ele.&lt;/p&gt; 

&lt;h3&gt;Removendo Arquivos Obsoletos&lt;/h3&gt;

&lt;p&gt;Estamos chegando ao final da atualiza&amp;ccedil;&amp;atilde;o agora. Tudo est&amp;aacute; funcionando, mas precisamos eliminar alguns dos arquivos que n&amp;atilde;o precisamos mais. Quando geramos a nova aplica&amp;ccedil;&amp;atilde;o Rails 3, foi criada uma nova p&amp;aacute;gina de boas-vindas e esta ter&amp;aacute; que ser removida.&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ rm public/index.html
&lt;/pre&gt;

&lt;p&gt;O mesmo se aplica a imagem do Rails que &amp;eacute; mostrada na p&amp;aacute;gina de boas-vindas.&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ rm public/images/rails.png
&lt;/pre&gt;

&lt;p&gt;Existem tamb&amp;eacute;m os arquivos na pasta &lt;code&gt;/script&lt;/code&gt; que n&amp;atilde;o s&amp;atilde;o mais usados pelo Rails 3 e podem ser removidos.&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ ls script
about		destroy		process	setup
autospec	generate		rails		setup_test
console	performance	runner	spec
dbconsole	plugin		server	spec_server
&lt;/pre&gt;

&lt;p&gt;Apenas o script &lt;code&gt;rails&lt;/code&gt; &amp;eacute; usado pelo Rails 3 e assim podemos remover os outros, como &lt;code&gt;console&lt;/code&gt;, &lt;code&gt;server&lt;/code&gt; e assim por diante.&lt;/p&gt;

&lt;p&gt;Isso &amp;eacute; tudo para essa s&amp;eacute;rie sobre a atualiza&amp;ccedil;&amp;atilde;o de uma aplica&amp;ccedil;&amp;atilde;o Rails 2 para Rails 3. Tenha em mente que muitas coisas que n&amp;oacute;s cobrimos s&amp;atilde;o espec&amp;iacute;ficas para a aplica&amp;ccedil;&amp;atilde;o Railscasts e n&amp;atilde;o h&amp;aacute; nenhuma maneira onde n&amp;oacute;s poder&amp;iacute;amos cobrir tudo o que  &amp;eacute; necess&amp;aacute;rio para atualizar qualquer aplica&amp;ccedil;&amp;atilde;o para o Rails 3. Se voc&amp;ecirc; tiver avisos de c&amp;oacute;digo obsoleto ou mensagens de erro, ent&amp;atilde;o h&amp;aacute; chances de que algu&amp;eacute;m j&amp;aacute; tenha tido o mesmo problema e uma pesquisa no Google trar&amp;aacute; a uma solu&amp;ccedil;&amp;atilde;o. Tamb&amp;eacute;m vale a pena conferir os outros epis&amp;oacute;dios que abrangem Rails 3.&lt;/p&gt;

&lt;p&gt;Um grande n&amp;uacute;mero de problemas que voc&amp;ecirc; vai encontrar quando atualizar uma aplica&amp;ccedil;&amp;atilde;o ser&amp;aacute; causado por plugins. O site Rails Plugins9 tem uma grande lista de plugins e diz se s&amp;atilde;o compat&amp;iacute;veis com o Rails 3 ou n&amp;atilde;o. Se voc&amp;ecirc; tiver problemas com um plugin espec&amp;iacute;fico, tamb&amp;eacute;m vale a pena verificar o reposit&amp;oacute;rio no Github para ver se h&amp;aacute; uma vers&amp;atilde;o compat&amp;iacute;vel com Rails 3  dispon&amp;iacute;vel.&lt;/p&gt;</description>
      <pubDate>Tue, 14 Sep 2010 19:54:03 +0000</pubDate>
      <guid>http://pt.asciicasts.com/episodes/227-atualizando-para-o-rails-3-parte-3</guid>
      <link>http://pt.asciicasts.com/episodes/227-atualizando-para-o-rails-3-parte-3</link>
    </item>
    <item>
      <title>Atualizando para o Rails 3 Parte 2</title>
      <description>&lt;p&gt;No &amp;uacute;ltimo epis&amp;oacute;dio, n&amp;oacute;s mostramos como atualizar uma aplica&amp;ccedil;&amp;atilde;o Rails 2 para Rails 3, usando o site Railscasts como exemplo. Chegamos at&amp;eacute; a iniciar a aplica&amp;ccedil;&amp;atilde;o sem erros, mas ainda h&amp;aacute; algumas coisas que precisamos consertar ou atualizar. Estaremos falando sobre isso aqui&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/440/original/E226I01.png" width="800" height="506" alt="The site is now up and running."/&gt;
&lt;/div&gt;

&lt;p&gt;Uma maneira &amp;oacute;bvia de ver o que ainda precisa ser consertado &amp;eacute; executando os tests ou specs da aplica&amp;ccedil;&amp;atilde;o. Mas antes vale a pena tomar alguns minutos para olhar a aplica&amp;ccedil;&amp;atilde;o executando atrav&amp;eacute;s do navegador, para que possamos detectar erros &amp;oacute;bvios. Quando fazemos isso na aplica&amp;ccedil;&amp;atilde;o do Railscasts, rapidamente descobrimos que enquanto a p&amp;aacute;gina de listagem dos epis&amp;oacute;dios funciona, a p&amp;aacute;gina de visualiza&amp;ccedil;&amp;atilde;o de um epis&amp;oacute;dio lan&amp;ccedil;a o seguinte erro:&lt;/p&gt;

&lt;pre class="terminal"&gt;
uninitialized constant ApplicationHelper::Textilizer
&lt;/pre&gt;

&lt;p&gt;Na aplica&amp;ccedil;&amp;atilde;o, &lt;code&gt;Textilizer&lt;/code&gt; &amp;eacute; uma classe implementada na pasta &lt;code&gt;/lib&lt;/code&gt;. Isso est&amp;aacute; causando um problema, pois por padr&amp;atilde;o, no primeiro Release Candidate do Rails 3, os arquivos da pasta &lt;code&gt;/lib&lt;/code&gt; n&amp;atilde;o s&amp;atilde;o mais inclu&amp;iacute;dos automaticamente no &lt;code&gt;load path&lt;/code&gt; da aplica&amp;ccedil;&amp;atilde;o. Para consertar isso, podemos fazer o &lt;code&gt;require&lt;/code&gt; dos arquivos manualmente ou podemos adicionar essa pasta ao &lt;code&gt;load path&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Vamos escolher a segunda op&amp;ccedil;&amp;atilde;o e adicionar a pasta ao &lt;code&gt;autoload_paths&lt;/code&gt;. H&amp;aacute; uma linha comentada no arquivo &lt;code&gt;/config/application.rb&lt;/code&gt; que podemos descomentar para fazer isso.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/config/application.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
# Custom directories with classes and modules you want to be autoloadable.
config.autoload_paths += %W(#{Rails.root}/lib)
&lt;/pre&gt;

&lt;p&gt;A equipe do Rails ainda est&amp;aacute; trabalhando na melhor maneira de manipular arquivos da pasta &lt;code&gt;/lib&lt;/code&gt;, ent&amp;atilde;o isso pode mudar para o vers&amp;atilde;o final do Rails 3.&lt;/p&gt;

&lt;p&gt;Quando recarregamos a p&amp;aacute;gina, temos um erro diferente.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/441/original/E226I02.png" width="800" height="364" alt="The show page is still throwing errors."/&gt;
&lt;/div&gt;

&lt;p&gt;A p&amp;aacute;gina agora apresenta um erro relacionado a falta de uma constante &lt;code&gt;APP_CONFIG&lt;/code&gt;. Essa constante est&amp;aacute; definida no arquivo &lt;code&gt;/config/preinitializer.rb&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/config/preinitializer.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
# load app_config.yml
require &amp;#x27;yaml&amp;#x27;
APP_CONFIG = YAML.load(File.read(&amp;quot;#{Rails.root}/config/app_config.yml&amp;quot;))
&lt;/pre&gt;

&lt;p&gt;Em uma aplica&amp;ccedil;&amp;atilde;o Rails 2, esse arquivo &amp;eacute; onde colocamos algumas coisas que queremos definir antes da aplica&amp;ccedil;&amp;atilde;o ser carregada. Nesse caso isso &amp;eacute; usado para carregar um arquivo YAML. O arquivo &lt;code&gt;preinitializer.rb&lt;/code&gt; n&amp;atilde;o &amp;eacute; suportado no Rails 3, ent&amp;atilde;o qualquer c&amp;oacute;digo dele deve ser movido para o arquivo &lt;code&gt;/config/application.rb&lt;/code&gt;. O c&amp;oacute;digo do arquivo preinitializer.rb precisa ficar bem no topo desse arquivo, antes da linha &lt;code&gt;require &amp;#x27;rails/all&amp;#x27;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;N&amp;atilde;o podemos simplesmente colar o c&amp;oacute;digo como est&amp;aacute;, pois ele usa o m&amp;eacute;todo &lt;code&gt;Rails.root&lt;/code&gt;, o qual n&amp;atilde;o est&amp;aacute; dispon&amp;iacute;vel antes do &lt;code&gt;require &amp;#x27;rails/all&amp;#x27;&lt;/code&gt;. Em vez disso, teremos que fazer refer&amp;ecirc;ncia em rela&amp;ccedil;&amp;atilde;o ao arquivo  &lt;code&gt;application.rb&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/config/application.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
require File.expand_path(&amp;#x27;../boot&amp;#x27;, __FILE__)

# load app_config.yml
require &amp;#x27;yaml&amp;#x27;
APP_CONFIG = YAML.load(File.read(File.expand_path(&amp;#x27;../app_config.yml&amp;#x27;, __FILE__)))

require &amp;#x27;rails/all&amp;#x27;
&lt;/pre&gt;

&lt;p&gt;Quando recarregamos a p&amp;aacute;gina novamente, ela n&amp;atilde;o parece muito certa. O HTML na se&amp;ccedil;&amp;atilde;o de notas est&amp;aacute; sendo &amp;quot;escapado&amp;quot; e a barra lateral direita n&amp;atilde;o foi encontrada. Mas, basicamente, a p&amp;aacute;gina carrega e isso &amp;eacute; bom o suficiente para uma primeira varredura atrav&amp;eacute;s da aplica&amp;ccedil;&amp;atilde;o, pois tudo que estamos fazendo &amp;eacute; passar por cada p&amp;aacute;gina para ver se alguma exce&amp;ccedil;&amp;atilde;o aparece. Agora que consertamos as p&amp;aacute;ginas que apresentaram exce&amp;ccedil;&amp;otilde;es, podemos fazer uma segunda varredura e corrigir erros nas views, como o erro abaixo:&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/442/original/E226I03.png" width="798" height="538" alt="The page loads but looks wrong."/&gt;
&lt;/div&gt;

&lt;h3&gt;Executando os Testes da Aplica&amp;ccedil;&amp;atilde;o&lt;/h3&gt;

&lt;p&gt;Se executarmos &lt;code&gt;rake rails:upgrade:check&lt;/code&gt; novamente, veremos que ainda h&amp;aacute; uma grande lista de coisas para consertar. S&amp;atilde;o principalmente coisas que se tornaram obsoletas (deprecated), que ainda continuam funcionando no Rails 3, mas &amp;eacute; improv&amp;aacute;vel que continuem no Rails 3.1. Como as mudan&amp;ccedil;as que precisamos fazer s&amp;atilde;o para coisas obsoletas e n&amp;atilde;o erros, vamos dar uma olhada no conjunto de testes da aplica&amp;ccedil;&amp;atilde;o e ver se todos os testes passam antes de fazermos alguma altera&amp;ccedil;&amp;atilde;o no c&amp;oacute;digo.&lt;/p&gt;

&lt;p&gt;A fim de obtermos os testes executando, precisamos adicionar uma gem ao nosso &lt;code&gt;Gemfile&lt;/code&gt;. S&amp;oacute; vamos querer que essa gem seja carregada nos ambientes relevantes, ent&amp;atilde;o vamos usar o m&amp;eacute;todo &lt;code&gt;group&lt;/code&gt; para fazer isso. Pode parecer que queremos instalar as gems apenas para o ambiente de testes, mas as gems que incluem tarefas Rake, como RSpec, tamb&amp;eacute;m ter&amp;atilde;o que ser inclu&amp;iacute;das no ambiente de desenvolvimento.&lt;/p&gt;

&lt;p&gt;A aplica&amp;ccedil;&amp;atilde;o Railscasts usa &lt;a href="http://rubygems.org/gems/mocha"&gt;Mocha&lt;/a&gt; para mocking, juntamente com &lt;a href="http://rspec.info/"&gt;RSpec&lt;/a&gt; e &lt;a href="http://rubygems.org/gems/factory_girl"&gt;Factory Girl&lt;/a&gt; portanto vamos precisar adicionar o seguinte c&amp;oacute;digo ao &lt;code&gt;Gemfile&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/Gemfile&lt;/p&gt;
&lt;pre class="ruby"&gt;
group :development, :test do
  gem &amp;quot;mocha&amp;quot;
  gem &amp;quot;rspec-rails&amp;quot;, &amp;quot;&amp;gt;= 2.0.0.beta.19&amp;quot;
  gem &amp;quot;factory_girl_rails&amp;quot;
end
&lt;/pre&gt;

&lt;p&gt;Para termos certeza de que essas gems est&amp;atilde;o instaladas, vamos executar &lt;code&gt;bundle install&lt;/code&gt; novamente. Para executarmos o RSpec, precisamos executar seu gerador. O gerador ir&amp;aacute; substituir os arquivos instalados do RSpec.&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ rails g rspec:install
      &lt;span class="passed"&gt;create&lt;/span&gt;  .rspec
       &lt;span class="info"&gt;exist&lt;/span&gt;  spec
    &lt;span class="failed"&gt;conflict&lt;/span&gt;  spec/spec_helper.rb
Overwrite /Users/eifion/rails/apps_for_asciicasts/ep226/railscasts/spec/spec_helper.rb? (enter &amp;quot;h&amp;quot; for help) [Ynaqdh] Y
       &lt;span class="forced"&gt;force&lt;/span&gt;  spec/spec_helper.rb
      &lt;span class="passed"&gt;create&lt;/span&gt;  autotest
      &lt;span class="passed"&gt;create&lt;/span&gt;  autotest/discover.rb
&lt;/pre&gt;      

&lt;p&gt;O novo arquivo &lt;code&gt;spec_helper.rb&lt;/code&gt; precisar&amp;aacute; sofrer uma pequena altera&amp;ccedil;&amp;atilde;o antes de continuarmos. Por padr&amp;atilde;o ele usar&amp;aacute; o RSpec para mocking, ent&amp;atilde;o precisamos atualizar o &lt;code&gt;config.mock_with&lt;/code&gt; para usar o Mocha.&lt;/p&gt;

&lt;p&gt;A aplica&amp;ccedil;&amp;atilde;o tamb&amp;eacute;m tem algumas macros para o RSpec no arquivo &lt;code&gt;/spec/controller_macros.rb&lt;/code&gt; e eles precisar&amp;atilde;o ser inclu&amp;iacute;dos. Mais acima, no arquivo &lt;code&gt;spec_helper&lt;/code&gt;, est&amp;aacute; uma linha que inclui tudo abaixo do diret&amp;oacute;rio &lt;code&gt;support&lt;/code&gt;, ent&amp;atilde;o tudo que precisamos fazer &amp;eacute; criar esse diret&amp;oacute;rio abaixo do &lt;code&gt;spec&lt;/code&gt; e mover o arquivo para ele. Agora precisamos adicionar o &lt;code&gt;config.include&lt;/code&gt; para incluir nossas macros ao RSpec. Depois dessas altera&amp;ccedil;&amp;otilde;es, o arquivo vai ficar assim:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/spec/spec/helper.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
# This file is copied to ~/spec when you run &amp;#x27;ruby script/generate rspec&amp;#x27;
# from the project root directory.
ENV[&amp;quot;RAILS_ENV&amp;quot;] ||= &amp;#x27;test&amp;#x27;
require File.expand_path(&amp;quot;../../config/environment&amp;quot;, __FILE__)
require &amp;#x27;rspec/rails&amp;#x27;

# Requires supporting files with custom matchers and macros, etc,
# in ./support/ and its subdirectories.
Dir[&amp;quot;#{File.dirname(__FILE__)}/support/**/*.rb&amp;quot;].each {|f| require f}

RSpec.configure do |config|
  config.mock_with :mocha
  config.fixture_path = &amp;quot;#{::Rails.root}/spec/fixtures&amp;quot;
  config.use_transactional_fixtures = true
  config.include ControllerMacros
end
&lt;/pre&gt;

&lt;p&gt;Agora estamos prontos para executarmos as specs e vermos quantas delas passam. Sabemos que haver&amp;aacute; um grande n&amp;uacute;mero de advert&amp;ecirc;ncias de c&amp;oacute;digo obsoleto (deprecated), por&amp;eacute;m no momento estamos procurando apenas testes falhando.&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ rake spec
&lt;/pre&gt;

&lt;p&gt;Esse comando produz uma grande quantidade de mensagens e ent&amp;atilde;o mostra que o teste deu um erro. A linha relevante &amp;eacute;:&lt;/p&gt;

&lt;pre class="terminal"&gt;
/Users/eifion/rails/apps_for_asciicasts/ep226/railscasts/spec/controllers/episodes_controller_spec.rb:5:in `block in &amp;lt;top (required)&amp;gt;&amp;#x27;: undefined local variable or method `integrate_views&amp;#x27; for :Class (NameError)
&lt;/pre&gt;

&lt;p&gt;Se voc&amp;ecirc; tiver mensagens de erro como essa e n&amp;atilde;o souber como resolv&amp;ecirc;-los, vale a pena pesquisar o erro no Google para ver se algu&amp;eacute;m j&amp;aacute; teve o mesmo problema e achou uma solu&amp;ccedil;&amp;atilde;o. Neste caso, a corre&amp;ccedil;&amp;atilde;o &amp;eacute; simples. O m&amp;eacute;todo &lt;code&gt;integrate_views&lt;/code&gt; foi renomeado para &lt;code&gt;render_views&lt;/code&gt; e ent&amp;atilde;o precisamos mudar isso na aplica&amp;ccedil;&amp;atilde;o.&lt;/p&gt;

&lt;p&gt;Uma vez feito isso podemos executar os specs novamente. Vamos ver mais uma vez uma grande quantidade de mensagens de c&amp;oacute;digo obsoleto mas dentre todos os testes apenas quatro falharam.&lt;/p&gt;

&lt;pre class="terminal"&gt;
Finished in 3.53 seconds
&lt;span class="failed"&gt;152 examples, 4 failures&lt;/span&gt;

1) CommentsController as guest index action should render index template for rss with xml
    Failure/Error: response.should have_tag(&amp;#x27;title&amp;#x27;, :text =&amp;gt; &amp;#x27;Railscasts Comments&amp;#x27;)
    &lt;span class="failed"&gt;undefined method `has_tag?&amp;#x27; for #&amp;lt;ActionController::TestResponse:0x000001040f2dc8&amp;gt;&lt;/span&gt;
    # ./spec/controllers/comments_controller_spec.rb:16:in `block (2 levels) in &amp;lt;main&amp;gt;&amp;#x27;

2) EpisodesController as guest index action should render index template for rss with xml
    Failure/Error: response.should have_tag(&amp;#x27;title&amp;#x27;, :text =&amp;gt; &amp;#x27;Railscasts&amp;#x27;)
    &lt;span class="failed"&gt;undefined method `has_tag?&amp;#x27; for #&amp;lt;ActionController::TestResponse:0x00000104007710&amp;gt;&lt;/span&gt;
    # ./spec/controllers/episodes_controller_spec.rb:26:in `block (2 levels) in &amp;lt;top (required)&amp;gt;&amp;#x27;

3) EpisodesController as guest index action should render index template for rss with xml for iPod
    Failure/Error: response.should have_tag(&amp;#x27;title&amp;#x27;, :text =&amp;gt; /Railscasts.+iPod/)
    &lt;span class="failed"&gt;undefined method `has_tag?&amp;#x27; for #&amp;lt;ActionController::TestResponse:0x00000102e2dd00&amp;gt;&lt;/span&gt;
    # ./spec/controllers/episodes_controller_spec.rb:33:in `block (2 levels) in &amp;lt;top (required)&amp;gt;&amp;#x27;

4) EpisodesController as guest show action should render show template for rss with xml
    Failure/Error: response.should have_tag(&amp;#x27;title&amp;#x27;, :text =&amp;gt; /Comments/)
    &lt;span class="failed"&gt;undefined method `has_tag?&amp;#x27; for #&amp;lt;ActionController::TestResponse:0x000001041f03b0&amp;gt;&lt;/span&gt;
    # ./spec/controllers/episodes_controller_spec.rb:65:in `block (2 levels) in &amp;lt;top (required)&amp;gt;&amp;#x27;
&lt;/pre&gt;    
    
&lt;p&gt;Todas as falhas foram causadas pela mesma coisa: o m&amp;eacute;todo &lt;code&gt;have_tag&lt;/code&gt;. Novamente uma r&amp;aacute;pida pesquisa na internet ir&amp;aacute; ajudar aqui. Podemos verificar que isso est&amp;aacute; relacionado ao Webrat e que o m&amp;eacute;todo &lt;code&gt;have_tag&lt;/code&gt; foi removido. Atualmente h&amp;aacute; um m&amp;eacute;todo similar chamado &lt;code&gt;have_selector&lt;/code&gt; que pode ser usado no lugar do outro. As op&amp;ccedil;&amp;otilde;es para o &lt;code&gt;have_selector&lt;/code&gt; s&amp;atilde;o um pouco diferentes. Precisamos substituir a op&amp;ccedil;&amp;atilde;o &lt;code&gt;:text&lt;/code&gt; pela &lt;code&gt;:content&lt;/code&gt;, por exemplo.&lt;/p&gt;

&lt;pre class="ruby"&gt;
response.should have_tag(&amp;#x27;title&amp;#x27;, :text =&amp;gt; &amp;#x27;Railscasts&amp;#x27;)
&lt;/pre&gt;

&lt;p&gt;ficar&amp;aacute;&lt;/p&gt;

&lt;pre class="ruby"&gt;
response.should have_selector(&amp;#x27;title&amp;#x27;, :content =&amp;gt; &amp;#x27;Railscasts&amp;#x27;)
&lt;/pre&gt;

&lt;p&gt;Feito isso, executamos os testes novamente e dessa vez todos passam.&lt;/p&gt;

&lt;pre class="terminal"&gt;
Finished in 3.44 seconds
&lt;span class="passed"&gt;152 examples, 0 failures&lt;/span&gt;
&lt;/pre&gt;

&lt;h3&gt;Removendo c&amp;oacute;digo obsoleto&lt;/h3&gt;

&lt;p&gt;Agora que todos os testes passaram, podemos come&amp;ccedil;ar a trabalhar com a lista que o &lt;code&gt;rake rails:upgrade:check&lt;/code&gt; gera e reduzir a quantidade de mensagens de c&amp;oacute;digo obsoleto. O primeiro item da lista &amp;eacute; sobre as chamadas do ActiveRecord.&lt;/p&gt;

&lt;pre class="terminal"&gt;
&lt;span class="failed"&gt;Soon-to-be-deprecated ActiveRecord calls&lt;/span&gt;
Methods such as find(:all), find(:first), finds with conditions, and the :joins option will soon be deprecated.
More information: &lt;span class="url"&gt;http://m.onkey.org/2010/1/22/active-record-query-interface&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;Isso se refere a partes do c&amp;oacute;digo que usam a antiga sintaxe &lt;code&gt;find&lt;/code&gt;, como este m&amp;eacute;todo no modelo &lt;code&gt;Episode&lt;/code&gt; que leva um hash de condi&amp;ccedil;&amp;otilde;es:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/models/episode.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
def self.primitive_search(query)
  find(:all, :conditions =&amp;gt; primitive_search_conditions(query))
end
&lt;/pre&gt;

&lt;p&gt;N&amp;oacute;s podemos atualizar c&amp;oacute;digos como esse usando o novo m&amp;eacute;todo &lt;code&gt;where&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/models/episode.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
def self.primitive_search(query)
  where(primitive_search_conditions(query))
end
&lt;/pre&gt;

&lt;p&gt;A nova sintaxe de query do ActiveRecord foi abordada no epis&amp;oacute;dio 202 [&lt;a href="http://railscasts.com/episodes/202-active-record-queries-in-rails-3"&gt;assista&lt;/a&gt;, &lt;a href="http://asciicasts.com/episodes/202-active-record-queries-in-rails-3"&gt;leia&lt;/a&gt;] ent&amp;atilde;o para mais detalhes sobre esse assunto d&amp;ecirc; uma olhada l&amp;aacute;.&lt;/p&gt;

&lt;p&gt;O pr&amp;oacute;ximo erro na lista &amp;eacute; este:&lt;/p&gt;

&lt;pre class="terminal"&gt;
&lt;span class="failed"&gt;named_scope is now just scope&lt;/span&gt;
The named_scope method has been renamed to just scope.
More information: &lt;span class="url"&gt;http://github.com/rails/rails/commit/d60bb0a9e4be2ac0a9de9a69041a4ddc2e0cc914&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;Essa &amp;eacute; outra coisa f&amp;aacute;cil de arrumar. S&amp;oacute; precisamos percorrer nossos modelos e substituir qualquer chamada ao m&amp;eacute;todo &lt;code&gt;named_scope&lt;/code&gt; por &lt;code&gt;scope&lt;/code&gt;. Os argumentos tamb&amp;eacute;m precisar&amp;atilde;o ser atualizados para usar a nova sintaxe do Rails 3. Por exemplo, no modelo &lt;code&gt;Comment&lt;/code&gt;:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/models/comment.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
named_scope :recent, :order =&amp;gt; &amp;quot;created_at DESC&amp;quot;
&lt;/pre&gt;

&lt;p&gt;ficar&amp;aacute;&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/models/comment.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
scope :recent, order(&amp;quot;created_at DESC&amp;quot;)
&lt;/pre&gt;

&lt;p&gt;Note que como vamos percorrendo a aplica&amp;ccedil;&amp;atilde;o e fazendo essas altera&amp;ccedil;&amp;otilde;es, devemos manter rodando nossos testes para termos certeza de que nada est&amp;aacute; sendo quebrado.&lt;/p&gt;

&lt;p&gt;O pr&amp;oacute;ximo item depois do &lt;code&gt;named_scope&lt;/code&gt; s&amp;atilde;o as rotas. O plugin rails upgrade inclui uma tarefa rake para atualizar o arquivo de rotas mas &amp;eacute; melhor fazer isso manualmente e aproveitar a oportunidade para limp&amp;aacute;-lo.&lt;/p&gt;

&lt;p&gt;O arquivo de rotas atualmente est&amp;aacute; assim:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/config/routes.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
Railscasts::Application.routes.draw do |map|
  map.resources :spam_questions

  map.resources :spam_checks

  map.with_options :controller =&amp;gt; &amp;#x27;info&amp;#x27; do |info|
    info.about &amp;#x27;about&amp;#x27;, :action =&amp;gt; &amp;#x27;about&amp;#x27;
    info.contest &amp;#x27;contest&amp;#x27;, :action =&amp;gt; &amp;#x27;contest&amp;#x27;
    info.feeds &amp;#x27;feeds&amp;#x27;, :action =&amp;gt; &amp;#x27;feeds&amp;#x27;
    info.give_back &amp;#x27;give_back&amp;#x27;, :action =&amp;gt; &amp;#x27;give_back&amp;#x27;
  end
  
  map.login &amp;#x27;login&amp;#x27;, :controller =&amp;gt; &amp;#x27;sessions&amp;#x27;, :action =&amp;gt; &amp;#x27;new&amp;#x27;
  map.logout &amp;#x27;logout&amp;#x27;, :controller =&amp;gt; &amp;#x27;sessions&amp;#x27;, :action =&amp;gt; &amp;#x27;destroy&amp;#x27;
  
  map.resources :sponsors
  map.resources :comments
  map.resources :tags
  map.resources :episodes, :collection =&amp;gt; { :archive =&amp;gt; :get }
  map.resources :sessions
  map.resources :spam_reports, :member =&amp;gt; { :confirm =&amp;gt; :post }, :collection =&amp;gt; { :confirm =&amp;gt; :post }
  
  map.root :episodes
end
&lt;/pre&gt;

&lt;p&gt;A nova sintaxe de rotas foi abordada em detalhes no epis&amp;oacute;dio 203 [&lt;a href="http://railscasts.com/episodes/203-routing-in-rails-3"&gt;assista&lt;/a&gt;, &lt;a href="http://asciicasts.com/episodes/203-routing-in-rails-3"&gt;leia&lt;/a&gt;] por isso n&amp;atilde;o vamos falar sobre isso aqui. Ap&amp;oacute;s as altera&amp;ccedil;&amp;otilde;es, o arquivo ficar&amp;aacute; parecido com isto:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/config/routes.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
Railscasts::Application.routes.draw do
  root :to =&amp;gt; &amp;quot;episodes#index&amp;quot;
  
  match &amp;quot;about&amp;quot; =&amp;gt; &amp;quot;info#about&amp;quot;, :as =&amp;gt; &amp;quot;about&amp;quot;
  match &amp;quot;contest&amp;quot; =&amp;gt; &amp;quot;info#contest&amp;quot;, :as =&amp;gt; &amp;quot;contest&amp;quot;
  match &amp;quot;feeds&amp;quot; =&amp;gt; &amp;quot;info#feeds&amp;quot;, :as =&amp;gt; &amp;quot;feeds&amp;quot;
  match &amp;quot;give_back&amp;quot; =&amp;gt; &amp;quot;info#give_back&amp;quot;, :as =&amp;gt; &amp;quot;give_back&amp;quot;
  match &amp;quot;login&amp;quot; =&amp;gt; &amp;quot;sessions#new&amp;quot;, :as =&amp;gt; &amp;quot;login&amp;quot;
  match &amp;quot;logout&amp;quot; =&amp;gt; &amp;quot;sessions#destroy&amp;quot;, :as =&amp;gt; &amp;quot;logout&amp;quot;
  
  resources :sponsors
  resources :comments
  resources :tags
  resources :episodes do
    collection do
      get :archive
    end
  end
  resources :sessions
  resources :spam_questions
  resources :spam_checks
  resources :spam_reports do
    member do
      post :confirm
    end
    collection do
      post :confirm
    end
  end
end
&lt;/pre&gt;

&lt;p&gt;O novo arquivo de rotas &amp;eacute; um pouco maior, mas parece um pouco mais limpo.&lt;/p&gt;

&lt;p&gt;Os &amp;uacute;ltimos itens s&amp;atilde;o as chamadas aos helpers ERb obsoletos.&lt;/p&gt;

&lt;pre class="terminal"&gt;
&lt;span class="failed"&gt;Deprecated ERb helper calls&lt;/span&gt;
Block helpers that use concat (e.g., form_for) should use &amp;lt;%= instead of &amp;lt;%.  The current form will continue to work for now, but you will get deprecation warnings since this form will go away in the future.
More information: &lt;span class="url"&gt;http://weblog.rubyonrails.org/&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;No c&amp;oacute;digo das views nas aplica&amp;ccedil;&amp;otilde;es Rails 3 &amp;eacute; algumas vezes necess&amp;aacute;rio usar &lt;code&gt;&amp;lt;%=&lt;/code&gt; em vez de &lt;code&gt;&amp;lt;%&lt;/code&gt; no in&amp;iacute;cio dos blocos de sa&amp;iacute;da de conte&amp;uacute;do, como o &lt;code&gt;form_for&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Um exemplo disso est&amp;aacute; no c&amp;oacute;digo do arquivo &lt;code&gt;archive.htmo.erb&lt;/code&gt;.&lt;/p&gt;
  
&lt;p class="codeFilePath"&gt;/app/views/episodes/archive.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;
&amp;lt;% form_tag archive_episodes_path, :method =&amp;gt; &amp;#x27;get&amp;#x27; do %&amp;gt;
  &amp;lt;p&amp;gt;
    &amp;lt;%= text_field_tag :search, params[:search] %&amp;gt;
    &amp;lt;%= submit_tag &amp;quot;Search&amp;quot;, :name =&amp;gt; nil %&amp;gt;
  &amp;lt;/p&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/pre&gt;

&lt;p&gt;O &lt;code&gt;form_tag&lt;/code&gt; nesse c&amp;oacute;digo vai inserir conte&amp;uacute;do em torno do que est&amp;aacute; dentro de seu bloco de modo que precisamos modificar isso para usar um sinal de igual.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/views/episodes/archive.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;
&amp;lt;%= form_tag archive_episodes_path, :method =&amp;gt; &amp;#x27;get&amp;#x27; do %&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Nem todos os blocos no c&amp;oacute;digo das views precisam ser alterados, apesar do &lt;code&gt;rake rails:upgrade:check&lt;/code&gt; dizer para fazer isso. Por exemplo, no c&amp;oacute;digo abaixo temos uma repeti&amp;ccedil;&amp;atilde;o atrav&amp;eacute;s de cada item de um hash e n&amp;atilde;o queremos adicionar um sinal de igual, pois o c&amp;oacute;digo n&amp;atilde;o adiciona qualquer c&amp;oacute;digo em torno do que est&amp;aacute; dentro do bloco.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/views/episodes/archive.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;
&amp;lt;% @episode_months.each do |month, episodes| %&amp;gt;
  &amp;lt;h2&amp;gt;&amp;lt;%=h month.strftime(&amp;#x27;%B %Y&amp;#x27;) %&amp;gt;&amp;lt;/h2&amp;gt;
  &amp;lt;% for episode in episodes %&amp;gt;
    &amp;lt;div&amp;gt;
      &amp;lt;%= episode.position %&amp;gt;.
      &amp;lt;%= link_to episode.name, episode %&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;% end %&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Mais informa&amp;ccedil;&amp;otilde;es sobre isso dispon&amp;iacute;vel no epis&amp;oacute;dio 208 [&lt;a href="http://railscasts.com/episodes/208-erb-blocks-in-rails-3"&gt;assista&lt;/a&gt;, &lt;a href="http://asciicasts.com/episodes/208-erb-blocks-in-rails-3"&gt;leia&lt;/a&gt;].&lt;/p&gt;

&lt;p&gt;Mesmo depois de terminar a corre&amp;ccedil;&amp;atilde;o de todos os c&amp;oacute;digos das views, o &lt;code&gt;rake rails:upgrade:check&lt;/code&gt; ainda mostra erros, por&amp;eacute;m esses s&amp;atilde;o falsos, pois est&amp;aacute; indicando todos os blocos em todas as views. Lembre-se de que voc&amp;ecirc; s&amp;oacute; quer mudar as que tem conte&amp;uacute;do de sa&amp;iacute;da, como &lt;code&gt;form_for&lt;/code&gt;, &lt;code&gt;form_tag&lt;/code&gt;, &lt;code&gt;div_for&lt;/code&gt; e assim por diante. Se voc&amp;ecirc; est&amp;aacute; inseguro quanto a saber se um bloco deve ser alterado para usar o sinal de igual, deixe como est&amp;aacute; e verifique se h&amp;aacute; avisos de c&amp;oacute;digo obsoleto (deprecated) nos testes ou log de desenvolvimento.&lt;/p&gt;

&lt;p&gt;Agora que terminamos de usar o plugin upgrade, podemos desinstalar, executando:&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ rails plugin remove rails_upgrade
&lt;/pre&gt;

&lt;p&gt;N&amp;oacute;s fizemos um grande progresso na atualiza&amp;ccedil;&amp;atilde;o da aplica&amp;ccedil;&amp;atilde;o para Rails 3. Os testes agora passam e n&amp;oacute;s removemos todo o c&amp;oacute;digo obsoleto. Temos ainda os problemas que vimos anteriormente, onde parte do HTML estava sendo escapado e estava faltando a barra lateral. N&amp;oacute;s vamos falar sobre tudo isso no pr&amp;oacute;ximo epis&amp;oacute;dio.&lt;/p&gt;</description>
      <pubDate>Wed, 25 Aug 2010 22:09:38 +0000</pubDate>
      <guid>http://pt.asciicasts.com/episodes/226-atualizando-para-o-rails-3-parte-2</guid>
      <link>http://pt.asciicasts.com/episodes/226-atualizando-para-o-rails-3-parte-2</link>
    </item>
    <item>
      <title>Atualizando para o Rails 3 Parte 1</title>
      <description>&lt;p&gt;O primeiro release candidate do Rails 3.0 j&amp;aacute; foi lan&amp;ccedil;ado. Esse &amp;eacute; um &amp;oacute;timo momento para experimentar o Rails 3, se voc&amp;ecirc; j&amp;aacute; n&amp;atilde;o tiver feito isso, e para ver quais mudan&amp;ccedil;as precisam ser feitas em suas aplica&amp;ccedil;&amp;otilde;es Rails 2 para atualiz&amp;aacute;-las. Neste epis&amp;oacute;dio vamos mostrar como atualizar uma aplica&amp;ccedil;&amp;atilde;o Rails 2.3 para Rails 3.0.&lt;/p&gt;

&lt;p&gt;J&amp;aacute; existe uma s&amp;eacute;rie de epis&amp;oacute;dios sobre Rails 3.0 que voc&amp;ecirc; pode assistir ou ler e n&amp;oacute;s vamos fazer refer&amp;ecirc;ncias a alguns epis&amp;oacute;dios relevantes enquanto trabalhamos com a atualiza&amp;ccedil;&amp;atilde;o. A aplica&amp;ccedil;&amp;atilde;o que vamos come&amp;ccedil;ar a atualizar &amp;eacute; o site railscasts.com. O c&amp;oacute;digo fonte est&amp;aacute; dispon&amp;iacute;vel no &lt;a href="http://github.com/ryanb/railscasts"&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Mesmo se voc&amp;ecirc; n&amp;atilde;o estiver pronto para usar Rails 3 em produ&amp;ccedil;&amp;atilde;o, ainda vale a pena tentar atualizar as aplica&amp;ccedil;&amp;otilde;es Rails 2 s&amp;oacute; para ver quais problemas voc&amp;ecirc; ter&amp;aacute; que enfrentar. Se suas aplica&amp;ccedil;&amp;otilde;es usam Git para controle de vers&amp;atilde;o, &amp;eacute; f&amp;aacute;cil criar um branch separado para experimentar. Vamos criar um novo branch chamado &lt;code&gt;rails3&lt;/code&gt;.&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ git checkout -b rails3
Switched to a new branch &amp;#x27;rails3&amp;#x27;
&lt;/pre&gt;

&lt;h3&gt;Antes de come&amp;ccedil;armos a atualiza&amp;ccedil;&amp;atilde;o&lt;/h3&gt;

&lt;p&gt;Antes de atualizar uma aplica&amp;ccedil;&amp;atilde;o para o Rails 3, devemos atualiz&amp;aacute;-la para a &amp;uacute;ltima vers&amp;atilde;o do Rails 2.3, que no momento &amp;eacute; o Rails 2.3.8. Da mesma forma, qualquer gem que a aplica&amp;ccedil;&amp;atilde;o usa, deve ser atualizada para a vers&amp;atilde;o mais recente. Desta forma, vamos garantir que n&amp;atilde;o existem problemas de compatibilidade com as vers&amp;otilde;es mais recentes.&lt;/p&gt;

&lt;p&gt;Uma vez que tenhamos atualizado o Rails e as gems, devemos executar nossos testes. Ter uma boa su&amp;iacute;te de testes automatizados ajudar&amp;aacute; a garantir que tudo ainda est&amp;aacute; funcionando como deveria.&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ rake spec
(in /Users/eifion/rails/apps_for_asciicasts/ep225/railscasts)
DEPRECATION WARNING: Rake tasks in vendor/plugins/hoptoad_notifier/tasks 
........................................................................................................................................................

152 examples, 0 failures
&lt;/pre&gt;

&lt;p&gt;Todos os testes passaram. Ent&amp;atilde;o estamos prontos para a atualiza&amp;ccedil;&amp;atilde;o.&lt;/p&gt;

&lt;h3&gt;Atualizando o Ruby e Instalando o Rails 3&lt;/h3&gt;

&lt;p&gt;Para a atualiza&amp;ccedil;&amp;atilde;o, queremos utilizar a &amp;uacute;ltima vers&amp;atilde;o do Ruby em um ambiente limpo para a aplica&amp;ccedil;&amp;atilde;o Rails 3, por isso vamos usar o &lt;a href="http://rvm.beginrescueend.com"&gt;rvm&lt;/a&gt; para instalar a &amp;uacute;ltima vers&amp;atilde;o do Ruby 1.9.2 e instalar o Rails 3.0. O rvm &amp;eacute; atualizado frequentemente, por isso vamos garantir que temos a vers&amp;atilde;o mais recente executando &lt;code&gt;update rvm&lt;/code&gt; antes de instalar o Ruby.&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ rvm update

rvm 0.1.40 by Wayne E. Seguin (wayneeseguin@gmail.com) [http://rvm.beginrescueend.com/]

info: fetching rvm-0.1.43.tar.gz

info: Extracting rvm-0.1.43.tar.gz ...

info: Installing rvm-0.1.43...
&lt;/pre&gt;

&lt;p&gt;Uma vez que o rvm est&amp;aacute; atualizado, precisamos recarreg&amp;aacute;-lo. Podemos fazer isso, executando:&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ rvm reload
&lt;/pre&gt;

&lt;p&gt;Agora podemos usar o rvm para instalar o Ruby 1.9.2.&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ rvm install 1.9.2
&lt;/pre&gt;

&lt;p&gt;Esse comando ir&amp;aacute; baixar, compilar e instalar a &amp;uacute;ltima vers&amp;atilde;o do Ruby 1.9.2, atualmente em rc2. Quando estiver conclu&amp;iacute;do (pode demorar alguns minutos) poderemos mudar para a nova vers&amp;atilde;o e verificar se ela funciona.&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ rvm 1.9.2
$ ruby -v
ruby 1.9.2dev (2010-07-11 revision 28618) [x86_64-darwin10.4.0]
&lt;/pre&gt;

&lt;p&gt;Agora que sabemos que estamos rodando a vers&amp;atilde;o correta do Ruby, podemos instalar a gem do Rails 3.0 release candidate.&lt;/p&gt;

&lt;pre class="terminal"&gt;
gem install rails --pre
&lt;/pre&gt;

&lt;p&gt;Note que como estamos usando uma vers&amp;atilde;o do Ruby instalada com rvm, n&amp;atilde;o precisamos usar sudo para instalar gems.&lt;/p&gt;

&lt;h3&gt;Come&amp;ccedil;ando a atualiza&amp;ccedil;&amp;atilde;o&lt;/h3&gt;

&lt;p&gt;Agora temos uma nova instala&amp;ccedil;&amp;atilde;o do Ruby e o Rails 3.0. Ent&amp;atilde;o estamos prontos para come&amp;ccedil;ar a atualizar nossa aplica&amp;ccedil;&amp;atilde;o. Para nos ajudar, temos o &lt;a href="http://github.com/rails/rails_upgrade"&gt;rails_upgrade plugin&lt;/a&gt;, que &amp;eacute; um plugin oficial que podemos usar para ver quais altera&amp;ccedil;&amp;otilde;es precisamos fazer. Para instalar o rails_upgrade, primeiro precisamos voltar para o Rails 2, que est&amp;aacute; instalado no ambiente do Ruby do sistema.&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ rvm system
&lt;/pre&gt;

&lt;p&gt;Agora podemos instalar o plugin.&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ script/plugin install git://github.com/rails/rails_upgrade.git
&lt;/pre&gt;

&lt;p&gt;Ser&amp;aacute; apresentada uma &lt;a href="http://github.com/rails/rails_upgrade/blob/master/install.rb"&gt;documenta&amp;ccedil;&amp;atilde;o &amp;uacute;til&lt;/a&gt; depois da instala&amp;ccedil;&amp;atilde;o. Um dos principais comandos que ele acrescenta &amp;eacute; o &lt;code&gt;rake rails:upgrade:check&lt;/code&gt;. Quando executamos esse comando no diret&amp;oacute;rio da nossa aplica&amp;ccedil;&amp;atilde;o, ele ir&amp;aacute; mostrar uma lista de tudo que precisa ser atualizado em nossa aplica&amp;ccedil;&amp;atilde;o. A sa&amp;iacute;da &amp;eacute; muito longa para mostrar aqui, mas como exemplo, veremos a primeira parte.&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ rake rails:upgrade:check

(in /Users/eifion/rails/apps_for_asciicasts/ep225/railscasts)
Old router API
The router API has totally changed.
More information: http://yehudakatz.com/2009/12/26/the-rails-3-router-rack-it-up/

The culprits: 
	- config/routes.rb
&lt;/pre&gt;	

&lt;p&gt;Antes de come&amp;ccedil;armos a atualiza&amp;ccedil;&amp;atilde;o, vamos executar &lt;code&gt;rake rails:upgrade:backup&lt;/code&gt;. Isso ir&amp;aacute; fazer backup de alguns dos principais arquivos que s&amp;atilde;o suscet&amp;iacute;veis de altera&amp;ccedil;&amp;atilde;o durante a atualiza&amp;ccedil;&amp;atilde;o.&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ rake rails:upgrade:backup
(in /Users/eifion/rails/apps_for_asciicasts/ep225/railscasts)
DEPRECATION WARNING: Rake tasks in vendor/plugins/hoptoad_notifier/tasks are deprecated. Use lib/tasks instead. (called from /Library/Ruby/Gems/1.8/gems/rails-2.3.8/lib/tasks/rails.rb:10)

* backing up .gitignore to .gitignore.rails2
* backing up app/controllers/application_controller.rb to app/controllers/application_controller.rb.rails2
* backing up app/helpers/application_helper.rb to app/helpers/application_helper.rb.rails2
* backing up config/routes.rb to config/routes.rb.rails2
* backing up config/environment.rb to config/environment.rb.rails2
* backing up config/environments/development.rb to config/environments/development.rb.rails2
* backing up config/environments/production.rb to config/environments/production.rb.rails2
* backing up config/database.yml to config/database.yml.rails2

This is a list of the files analyzed and backed up (if they existed);
you will probably not want the generator to replace them since
you probably modified them (but now they&amp;#x27;re safe if you accidentally do!).

- .gitignore
- app/controllers/application_controller.rb
- app/helpers/application_helper.rb
- config/routes.rb
- config/environment.rb
- config/environments/development.rb
- config/environments/production.rb
- config/environments/staging.rb
- config/database.yml
- config.ru
- doc/README_FOR_APP
- test/test_helper.rb
&lt;/pre&gt;

&lt;p&gt;Come&amp;ccedil;aremos a atualizar criando uma nova aplica&amp;ccedil;&amp;atilde;o Rails 3 no diret&amp;oacute;rio da aplica&amp;ccedil;&amp;atilde;o. Para fazer isso, &amp;eacute; necess&amp;aacute;rio voltar ao ambiente do Ruby 1.9.2.&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ rvm 1.9.2
&lt;/pre&gt;

&lt;p&gt;Agora podemos criar a nova aplica&amp;ccedil;&amp;atilde;o Rails 3 com:&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ rails new .
&lt;/pre&gt;

&lt;p&gt;Como estamos criando uma nova aplica&amp;ccedil;&amp;atilde;o no mesmo diret&amp;oacute;rio de uma existente, seremos questionados sobre sobrescrever alguns arquivos existentes. Se n&amp;atilde;o temos certeza se o arquivo deve ser sobrescrito, podemos usar a op&amp;ccedil;&amp;atilde;o &lt;code&gt;d&lt;/code&gt; para ver as diferen&amp;ccedil;as entre o arquivo existente e o que vai sobrescrever.&lt;/p&gt;

&lt;p&gt;N&amp;oacute;s fizemos backup dos arquivos mais importantes e podemos sobrescrever todos os arquivos conflitantes, exceto esses:&lt;/p&gt;

&lt;ul style="list-style-type:disc; list-style-position: inside;"&gt;
 &lt;li&gt;&lt;code&gt;/README&lt;/code&gt;&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;/app/views/layouts/application.html.erb&lt;/code&gt;&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;/public/javascripts/application.js&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
 
&lt;p&gt;Os outros arquivos, ou n&amp;atilde;o tiveram mudan&amp;ccedil;as, ou t&amp;ecirc;m backup, nos permitindo refazer quaisquer altera&amp;ccedil;&amp;otilde;es na nova vers&amp;atilde;o a medida que avan&amp;ccedil;amos.&lt;/p&gt;

&lt;p&gt;Nossa aplica&amp;ccedil;&amp;atilde;o est&amp;aacute; agora atualizada para o Rails 3.0, mas ainda temos que percorrer os arquivos que fizemos backup e copiar qualquer c&amp;oacute;digo que seja espec&amp;iacute;fico da nossa aplica&amp;ccedil;&amp;atilde;o. Cada arquivo que foi feito backup, est&amp;aacute; em seu diret&amp;oacute;rio original com uma extens&amp;atilde;o &lt;code&gt;.rails2&lt;/code&gt;. Ent&amp;atilde;o s&amp;oacute; precisamos abrir cada arquivo de backup, juntamente com a nova vers&amp;atilde;o, e copiar os c&amp;oacute;digos que precisam ser mantidos.&lt;/p&gt;

&lt;p&gt;Vamos come&amp;ccedil;ar com o arquivo de rotas. A sintaxe das rotos mudou, mas a antiga ainda funciona no Rails 3, embora esteja obsoleta (deprecated). Nesse momento podemos apenas copiar as rotas do arquivo de backup para o novo arquivo de rotas e vamos testar isso depois.&lt;/p&gt;

&lt;p&gt;Em seguida vamos dar uma olhada no arquivo &lt;code&gt;/config/environment.rb&lt;/code&gt;. Corrigir esse arquivo vai dar um pouco mais de trabalho, pois a configura&amp;ccedil;&amp;atilde;o mudou bastante no Rails 3. O arquivo padr&amp;atilde;o dos ambientes est&amp;aacute; bem menor pois as op&amp;ccedil;&amp;otilde;es de configura&amp;ccedil;&amp;atilde;o n&amp;atilde;o est&amp;atilde;o mais l&amp;aacute;, foram para o arquivo &lt;code&gt;/config/application.rb&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Existem tr&amp;ecirc;s coisas no backup do &lt;code&gt;environment.rb&lt;/code&gt; que precisamos considerar. A primeira &amp;eacute; a configura&amp;ccedil;&amp;atilde;o do time zone.&lt;/p&gt;

&lt;pre class="terminal"&gt;
config.time_zone = &amp;#x27;Pacific Time (US &amp;amp; Canada)&amp;#x27;
&lt;/pre&gt;

&lt;p&gt;Essa linha pode ser movida para o arquivo &lt;code&gt;/config/application.rb&lt;/code&gt;.&lt;/p&gt; 

&lt;p&gt;A segunda parte &amp;eacute; o c&amp;oacute;digo da sess&amp;atilde;o.&lt;/p&gt;

&lt;pre class="terminal"&gt;
config.action_controller.session = {
  :session_key =&amp;gt; APP_CONFIG[&amp;#x27;session_key&amp;#x27;],
  :secret      =&amp;gt; APP_CONFIG[&amp;#x27;session_secret&amp;#x27;]
}
&lt;/pre&gt;

&lt;p&gt;No Rails 3 esse c&amp;oacute;digo pertence a um arquivo initializer e se olharmos esse arquivo, vamos ver o c&amp;oacute;digo para configurar os dados de sess&amp;atilde;o da aplica&amp;ccedil;&amp;atilde;o.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/config/initializers/session_store.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
# Be sure to restart your server when you modify this file.

Railscasts::Application.config.session_store :cookie_store, :key =&amp;gt; &amp;#x27;_railscasts_session&amp;#x27;

# Use the database for sessions instead of the cookie-based default,
# which shouldn&amp;#x27;t be used to store highly confidential information
# (create the session table with &amp;quot;rake db:sessions:create&amp;quot;)
# Railscasts::Application.config.session_store :active_record_store
&lt;/pre&gt;

&lt;p&gt;Podemos deixar esse c&amp;oacute;digo como est&amp;aacute; por enquanto. Vamos alterar isso depois, mas isso n&amp;atilde;o ser&amp;aacute; necess&amp;aacute;rio para ter o site instalado e funcionando.&lt;/p&gt;

&lt;p&gt;Finalmente, no final do arquivo de backup do &lt;code&gt;environment.rb&lt;/code&gt; est&amp;aacute; o c&amp;oacute;digo de configura&amp;ccedil;&amp;atilde;o das gems da aplica&amp;ccedil;&amp;atilde;o.&lt;/p&gt;

&lt;pre class="ruby"&gt;
config.gem &amp;quot;RedCloth&amp;quot;, :lib =&amp;gt; &amp;#x27;redcloth&amp;#x27;, :version =&amp;gt; &amp;quot;&amp;gt;= 4.0&amp;quot;
config.gem &amp;quot;coderay&amp;quot;
config.gem &amp;#x27;acts-as-list&amp;#x27;
config.gem &amp;#x27;will_paginate&amp;#x27;
config.gem &amp;#x27;thinking-sphinx&amp;#x27;, :lib =&amp;gt; &amp;#x27;thinking_sphinx&amp;#x27;
config.gem &amp;#x27;whenever&amp;#x27;, :lib =&amp;gt; false
&lt;/pre&gt;

&lt;p&gt;Esse c&amp;oacute;digo pode ser copiado para o &lt;code&gt;Gemfile&lt;/code&gt;, que est&amp;aacute; no diret&amp;oacute;rio raiz da aplica&amp;ccedil;&amp;atilde;o. A sintaxe foi ligeiramente modificada e o c&amp;oacute;digo precisa ser alterado assim:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/Gemfile&lt;/p&gt;
&lt;pre class="ruby"&gt;
gem &amp;quot;RedCloth&amp;quot;, &amp;quot;&amp;gt;=4.0&amp;quot;, :require =&amp;gt; &amp;#x27;redcloth&amp;#x27;
gem &amp;quot;coderay&amp;quot;
gem &amp;#x27;acts-as-list&amp;#x27;
gem &amp;#x27;will_paginate&amp;#x27;
gem &amp;#x27;thinking-sphinx&amp;#x27;, :require =&amp;gt; &amp;#x27;thinking_sphinx&amp;#x27;
gem &amp;#x27;whenever&amp;#x27;, :require =&amp;gt; false
&lt;/pre&gt;

&lt;p&gt;Al&amp;eacute;m de alterar o &lt;code&gt;config.gem&lt;/code&gt; para &lt;code&gt;gem&lt;/code&gt; em cada linha, h&amp;aacute; algumas outras altera&amp;ccedil;&amp;otilde;es que precisamos fazer. O n&amp;uacute;mero da vers&amp;atilde;o agora &amp;eacute; passado como segundo par&amp;acirc;metro e a op&amp;ccedil;&amp;atilde;o &lt;code&gt;:lib&lt;/code&gt; foi renomeada para &lt;code&gt;:required&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Feito isso, precisamos executar &lt;code&gt;bundle install&lt;/code&gt; para ter certeza de que todas as gems necess&amp;aacute;rias est&amp;atilde;o instaladas. Para mais informa&amp;ccedil;&amp;otilde;es sobre o bundler e instala&amp;ccedil;&amp;atilde;o de gems voc&amp;ecirc; pode &lt;a href="http://railscasts.com/episodes/201-bundler"&gt;assistir&lt;/a&gt; ou &lt;a href="http://asciicasts.com/episodes/201-bundler"&gt;ler&lt;/a&gt; o epis&amp;oacute;dio 201. N&amp;atilde;o vamos falar em copiar os c&amp;oacute;digos dos outros arquivos de backup, mas deve ser bastante simples transferir o c&amp;oacute;digo necess&amp;aacute;rio do backup para o novo arquivo.&lt;/p&gt;

&lt;p&gt;Com as gems instaladas, vamos tentar iniciar o servidor para ver se a aplica&amp;ccedil;&amp;atilde;o ser&amp;aacute; iniciada.&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ rails s
/Users/eifion/.rvm/gems/ruby-1.8.7-p299/gems/will_paginate-2.3.14/lib/will_paginate.rb:39:in `enable_activerecord&amp;#x27;: 
undefined method `returning&amp;#x27; for WillPaginate:Module (NoMethodError)
# rest of error truncated&amp;hellip;
&lt;/pre&gt;

&lt;p&gt;N&amp;atilde;o foi. E o motivo foi um erro no c&amp;oacute;digo da gem &lt;code&gt;will_paginate&lt;/code&gt;, onde temos um m&amp;eacute;todo &lt;code&gt;returning&lt;/code&gt; indefinido. Esse m&amp;eacute;todo estava dispon&amp;iacute;vel no Rails 2, mas foi removido no Rails 3.&lt;/p&gt;

&lt;p&gt;Em casos como esse, vale a pena chegar o site &lt;a href="http://rubygems.org"&gt;RubyGems&lt;/a&gt; para ver se h&amp;aacute; dispon&amp;iacute;vel uma nova vers&amp;atilde;o da gem em prerelease compat&amp;iacute;vel com o Rails 3. No caso do &lt;code&gt;will_paginate&lt;/code&gt; existe e podemos usar, acrescentando o n&amp;uacute;mero da vers&amp;atilde;o da gem em nosso &lt;code&gt;Gemfile&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/Gemfile&lt;/p&gt;
&lt;pre class="terminal"&gt;
gem &amp;#x27;will_paginate&amp;#x27;, &amp;#x27;&amp;gt;=3.0.pre&amp;#x27;
&lt;/pre&gt;

&lt;p&gt;Se executarmos &lt;code&gt;bundle install&lt;/code&gt; novamente, a vers&amp;atilde;o prerelease da gem ser&amp;aacute; instalada e poderemos usar. Agora podemos tentar iniciar o servidor de novo.&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ rails s
/Users/eifion/.rvm/gems/ruby-1.8.7-p299/gems/after_commit-1.0.7/lib/after_commit/active_record.rb:15:in `include_after_commit_extensions&amp;#x27;: undefined method `subclasses_of&amp;#x27; for Object:Class (NoMethodError)
	from /Users/eifion/.rvm/gems/ruby-1.8.7-p299/gems/after_commit-1.0.7/lib/after_commit.rb:81
	from /Users/eifion/.rvm/gems/ruby-1.8.7-p299/gems/thinking-sphinx-1.3.18/lib/thinking_sphinx.rb:2:in `require&amp;#x27;
	from /Users/eifion/.rvm/gems/ruby-1.8.7-p299/gems/thinking-sphinx-1.3.18/lib/thinking_sphinx.rb:2
&lt;/pre&gt;

&lt;p&gt;Esse erro parece ter sido causado pela gem Thinking Sphinx. Novamente h&amp;aacute; uma vers&amp;atilde;o prerelease dispon&amp;iacute;vel que podemos usar. Ent&amp;atilde;o temos que fazer outra altera&amp;ccedil;&amp;atilde;o no &lt;code&gt;Gemfile&lt;/code&gt; e da&amp;iacute; executar o &lt;code&gt;bundle install&lt;/code&gt; de novo.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/Gemfile&lt;/p&gt;
&lt;pre class="ruby"&gt;
gem &amp;#x27;thinking-sphinx&amp;#x27;, &amp;#x27;&amp;gt;=2.0.0.rc1&amp;#x27;, :require =&amp;gt; &amp;#x27;thinking_sphinx&amp;#x27;
&lt;/pre&gt;

&lt;p&gt;Vamos tentar iniciar o servidor de novo.&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ rails s
DEPRECATION WARNING: railtie_name is deprecated and has no effect. (called from &amp;lt;class:Railtie&amp;gt; at /Users/eifion/.rvm/gems/ruby-1.9.2-rc2/gems/will_paginate-3.0.pre/lib/will_paginate/railtie.rb:6)
=&amp;gt; Booting WEBrick
=&amp;gt; Rails 3.0.0.rc application starting in development on http://0.0.0.0:3000
=&amp;gt; Call with -d to detach
=&amp;gt; Ctrl-C to shutdown server
Exiting
/Users/eifion/rails/apps_for_asciicasts/ep225/railscasts/config/routes.rb:2:in `block in &amp;lt;top (required)&amp;gt;&amp;#x27;: undefined local variable or method `map&amp;#x27; for #&amp;lt;ActionDispatch::Routing::Mapper:0x00000101dffde8&amp;gt; (NameError)
&lt;/pre&gt;

&lt;p&gt;Dessa vez temos algo novo. O servidor tenta iniciar mas reclama sobre uma vari&amp;aacute;vel ou m&amp;eacute;todo indefinido chamado &lt;code&gt;map&lt;/code&gt; nas rotas. Conforme n&amp;oacute;s colamos o antigo c&amp;oacute;digo das rotas no novo arquivo de rotas, estamos usando uma vari&amp;aacute;vel &lt;code&gt;map&lt;/code&gt;, mas a vari&amp;aacute;vel n&amp;atilde;o &amp;eacute; passada para o bloco, pois ela n&amp;atilde;o &amp;eacute; obrigat&amp;oacute;ria no Rails 3. N&amp;oacute;s ainda podemos usar a antiga sintaxe de rotas e passar essa vari&amp;aacute;vel.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/config/routes.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
Railscasts::Application.routes.draw do |map|
  map.resources :spam_questions

  map.resources :spam_checks

  map.with_options :controller =&amp;gt; &amp;#x27;info&amp;#x27; do |info|
    info.about &amp;#x27;about&amp;#x27;, :action =&amp;gt; &amp;#x27;about&amp;#x27;
    info.contest &amp;#x27;contest&amp;#x27;, :action =&amp;gt; &amp;#x27;contest&amp;#x27;
    info.feeds &amp;#x27;feeds&amp;#x27;, :action =&amp;gt; &amp;#x27;feeds&amp;#x27;
    info.give_back &amp;#x27;give_back&amp;#x27;, :action =&amp;gt; &amp;#x27;give_back&amp;#x27;
  end
  
  map.login &amp;#x27;login&amp;#x27;, :controller =&amp;gt; &amp;#x27;sessions&amp;#x27;, :action =&amp;gt; &amp;#x27;new&amp;#x27;
  map.logout &amp;#x27;logout&amp;#x27;, :controller =&amp;gt; &amp;#x27;sessions&amp;#x27;, :action =&amp;gt; &amp;#x27;destroy&amp;#x27;
  
  map.resources :sponsors
  map.resources :comments
  map.resources :tags
  map.resources :episodes, :collection =&amp;gt; { :archive =&amp;gt; :get }
  map.resources :sessions
  map.resources :spam_reports, :member =&amp;gt; { :confirm =&amp;gt; :post }, :collection =&amp;gt; { :confirm =&amp;gt; :post }
  
  map.root :episodes
end
&lt;/pre&gt;

&lt;p&gt;Quando tentamos iniciar o servidor pela quarta vez, temos sorte e ele inicia sem erros.&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ rails s
DEPRECATION WARNING: railtie_name is deprecated and has no effect. (called from &amp;lt;class:Railtie&amp;gt; at /Users/eifion/.rvm/gems/ruby-1.9.2-rc2/gems/will_paginate-3.0.pre/lib/will_paginate/railtie.rb:6)
=&amp;gt; Booting WEBrick
=&amp;gt; Rails 3.0.0.rc application starting in development on http://0.0.0.0:3000
=&amp;gt; Call with -d to detach
=&amp;gt; Ctrl-C to shutdown server
[2010-08-05 19:30:22] INFO  WEBrick 1.3.1
[2010-08-05 19:30:22] INFO  ruby 1.9.2 (2010-07-11) [x86_64-darwin10.4.0]
[2010-08-05 19:30:22] INFO  WEBrick::HTTPServer#start: pid=9933 port=3000
&lt;/pre&gt;

&lt;p&gt;Se visitarmos a p&amp;aacute;gina principal no navegador, vamos ver a p&amp;aacute;gina inicial padr&amp;atilde;o, pois ela foi recriada no diret&amp;oacute;rio &lt;code&gt;/public&lt;/code&gt; quando criamos a aplica&amp;ccedil;&amp;atilde;o Rails 3. Podemos ver nessa p&amp;aacute;gina, que o ambiente correto est&amp;aacute; sendo usado.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/439/original/E225I01.png" width="807" height="538" alt="The default home page of our updates application."/&gt;
&lt;/div&gt;

&lt;p&gt;Embora tenhamos iniciado o servidor com sucesso, ainda temos muitas coisas que precisamos corrigir, como vemos quando executamos &lt;code&gt;rails:upgrade:check&lt;/code&gt; novamente. Tamb&amp;eacute;m precisamos executar nossas &lt;code&gt;specs&lt;/code&gt; de novo para ver se elas passam. N&amp;oacute;s vamos fazer isso no pr&amp;oacute;ximo epis&amp;oacute;dio.&lt;/p&gt;</description>
      <pubDate>Sun, 08 Aug 2010 19:57:46 +0000</pubDate>
      <guid>http://pt.asciicasts.com/episodes/225-atualizando-para-o-rails-3-parte-1</guid>
      <link>http://pt.asciicasts.com/episodes/225-atualizando-para-o-rails-3-parte-1</link>
    </item>
    <item>
      <title>Controllers no Rails 3</title>
      <description>  &lt;p&gt;Enquanto as principais mudan&amp;ccedil;as nos controllers do Rails 3 aconteceram nos &amp;quot;bastidores&amp;quot;, existem algumas diferen&amp;ccedil;as para os desenvolvedores. Este epis&amp;oacute;dio vai cobrir algumas das novas funcionalidades que foram adicionadas.&lt;/p&gt;

	&lt;h3&gt;Par&amp;acirc;metros no Log&lt;/h3&gt;

	&lt;p&gt;A primeira mudan&amp;ccedil;a que vamos mostrar &amp;eacute; no &lt;code&gt;ApplicationController&lt;/code&gt;. Em uma aplica&amp;ccedil;&amp;atilde;o Rails 2, voc&amp;ecirc; pode filtrar certos par&amp;acirc;metros para n&amp;atilde;o aparecerem em texto simples no arquivo de log, usando o m&amp;eacute;todo &lt;code&gt;filter_parameter_logging&lt;/code&gt;, como mostrado aqui:&lt;/p&gt;

	&lt;p class="codeFilePath"&gt;/app/controllers/application_controller.rb&lt;/p&gt;
	&lt;pre class="ruby"&gt;
		class ApplicationController &amp;lt; ActionController::Base
	  	protect_from_forgery
	  	filter_parameter_logging :password
		end
	&lt;/pre&gt;

&lt;p&gt;Esse m&amp;eacute;todo foi substitu&amp;iacute;do (deprecated) no Rails 3 e deve ser removido da sua aplica&amp;ccedil;&amp;atilde;o. A filtragem de par&amp;acirc;metros est&amp;aacute; configurada agora no arquivo &lt;code&gt;/config/application.rb&lt;/code&gt;. O c&amp;oacute;digo que configura os par&amp;acirc;metros que devem ser filtrados est&amp;aacute; no final do arquivo.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/config/application.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
# Configure sensitive parameters which will be filtered from the log file.
config.filter_parameters += [:password]
&lt;/pre&gt;

&lt;p&gt;Essa linha &amp;eacute; adicionada por padr&amp;atilde;o nas novas aplica&amp;ccedil;&amp;otilde;es Rails 3. &amp;Eacute; f&amp;aacute;cil esquecer de adicionar filtragem em uma aplica&amp;ccedil;&amp;atilde;o, ent&amp;atilde;o &amp;eacute;  bom ter essa funcionalidade como padr&amp;atilde;o. Isso ir&amp;aacute;, da forma que est&amp;aacute;, filtrar somente o par&amp;acirc;metro de senha. Ser&amp;aacute; necess&amp;aacute;rio alterar se outro par&amp;acirc;metro, como um n&amp;uacute;mero de cart&amp;atilde;o de cr&amp;eacute;dito, precisar ser filtrado tamb&amp;eacute;m.&lt;/p&gt;

&lt;h3&gt;Modos de Redirecionamento&lt;/h3&gt;

&lt;p&gt;Em seguida vamos dar uma olhada no &lt;code&gt;ProductsController&lt;/code&gt; de uma aplica&amp;ccedil;&amp;atilde;o de loja virtual que tenho escrito. E em como redirecionamentos s&amp;atilde;o tratados quando uma action, como &lt;code&gt;create&lt;/code&gt; ou &lt;code&gt;update&lt;/code&gt;, &amp;eacute; chamada em um controller t&amp;iacute;pico Rails, com os sete m&amp;eacute;todos habituais RESTful. Se olharmos o c&amp;oacute;digo do m&amp;eacute;todo &lt;code&gt;create&lt;/code&gt;, veremos que depois de validado, o  &lt;code&gt;Product&lt;/code&gt; foi salvo, a action define uma mensagem &lt;code&gt;flash&lt;/code&gt; e ent&amp;atilde;o redireciona para a action &lt;code&gt;show&lt;/code&gt; do produto rec&amp;eacute;m-criado.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controllers/products_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
def create
  @product = Product.new(params[:product])
  if @product.save
    flash[:notice] = &amp;quot;Successfully created product.&amp;quot;
    redirect_to @product
  else
    render :action =&amp;gt; &amp;#x27;new&amp;#x27;
  end
end
&lt;/pre&gt;

&lt;p&gt;Esse comportamento &amp;eacute; bastante comum em um controller e no Rails 3 podemos combinar essas duas linhas de modo que a mensagem &lt;code&gt;flash&lt;/code&gt; torna-se um par&amp;acirc;metro do m&amp;eacute;todo &lt;code&gt;redirect_to&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controllers/products_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
def create
  @product = Product.new(params[:product])
  if @product.save
    redirect_to @product, :notice =&amp;gt; &amp;quot;Successfully created product.&amp;quot;
  else
    render :action =&amp;gt; &amp;#x27;new&amp;#x27;
  end
end
&lt;/pre&gt;

&lt;p&gt;As mensagens &lt;code&gt;:notice&lt;/code&gt; ou &lt;code&gt;:alert&lt;/code&gt; v&amp;atilde;o funcionar aqui, mas qualquer outro tipo de mensagem &lt;code&gt;flash&lt;/code&gt; ter&amp;aacute; que ser incorporada em um &lt;code&gt;:flash&lt;/code&gt; hash. Esse recurso tamb&amp;eacute;m foi adicionado ao Rails 2.3.6, por isso, se voc&amp;ecirc; estiver usando a vers&amp;atilde;o mais recente do Rails 2, ent&amp;atilde;o voc&amp;ecirc; pode usar esse atalho tamb&amp;eacute;m.&lt;/p&gt;

&lt;p&gt;O m&amp;eacute;todo &lt;code&gt;redirect_to&lt;/code&gt; acima tem uma inst&amp;acirc;ncia de um model como par&amp;acirc;metro. Passar um objeto do model &lt;code&gt;Product&lt;/code&gt;, como &lt;code&gt;@product&lt;/code&gt;, &amp;eacute; um atalho para o uso do m&amp;eacute;todo &lt;code&gt;product_path(@product)&lt;/code&gt;. Isso &amp;eacute; traduzido para o path da action &lt;code&gt;show&lt;/code&gt; desse produto. Se quis&amp;eacute;ssemos redirecionar para a p&amp;aacute;gina de edi&amp;ccedil;&amp;atilde;o, em vez disso, poder&amp;iacute;amos usar &lt;code&gt;edit_product_path(@product)&lt;/code&gt;. Mas existe um outro atalho que podemos usar. Em vez de escrever:&lt;/p&gt;

&lt;pre class="ruby"&gt;
redirect_to edit_product_path(@product)
&lt;/pre&gt; 

&lt;p&gt;Poder&amp;iacute;amos escrever:&lt;/p&gt;

&lt;pre class="ruby"&gt;
redirect_to [:edit, @product]
&lt;/pre&gt;

&lt;p&gt;Isso ser&amp;aacute; traduzido para o mesmo path da action edit do produto acima, mas com um pouco menos de c&amp;oacute;digo. Como o &lt;code&gt;:notice&lt;/code&gt;, essa op&amp;ccedil;&amp;atilde;o acima tamb&amp;eacute;m funciona na &amp;uacute;ltima vers&amp;atilde;o do Rails 2. Esse atalho funciona com recursos aninhados tamb&amp;eacute;m. Ent&amp;atilde;o se um produto pertence a uma categoria, ele pode ser redirecionado com:&lt;/p&gt;

&lt;pre class="ruby"&gt;
redirect_to [@category, @product]
&lt;/pre&gt;

&lt;p&gt;Essa t&amp;eacute;cnica de usar array funciona em qualquer lugar que voc&amp;ecirc; precisa gerar uma URL e pode ser usado no c&amp;oacute;digo das views em um m&amp;eacute;todo &lt;code&gt;link_to&lt;/code&gt;, bem como nos controllers.&lt;/p&gt;

&lt;h3&gt;Cookies Permanentes&lt;/h3&gt;

&lt;p&gt;O pr&amp;oacute;ximo recurso novo que vamos demonstrar s&amp;atilde;o os cookies permanentes. Digamos que quando um usu&amp;aacute;rio cria um novo produto, queremos armazenar o &lt;code&gt;id&lt;/code&gt; do produto em um cookie. Podemos usar o m&amp;eacute;todo &lt;code&gt;cookies&lt;/code&gt; para fazer isso:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controllers/proucts_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
def create
  @product = Product.new(params[:product])
  if @product.save
    cookies[:last_product_id] = @product.id
    redirect_to @product, :notice =&amp;gt; &amp;quot;Successfully created product.&amp;quot;
  else
    render :action =&amp;gt; &amp;#x27;new&amp;#x27;
  end
end
&lt;/pre&gt;

&lt;p&gt;Esse c&amp;oacute;digo cria um cookie de sess&amp;atilde;o que durar&amp;aacute; apenas enquanto o usu&amp;aacute;rio mant&amp;eacute;m a sua janela do navegador aberta. Para criar um cookie com uma data de validade expl&amp;iacute;cita no Rails 2, ter&amp;iacute;amos que transformar o valor em um hash e definir um tempo de validade expl&amp;iacute;cito assim:&lt;/p&gt;

&lt;pre class="ruby"&gt;
cookies[:last_product_id] = { :value =&amp;gt; @product_id, :expires =&amp;gt; 1.month.from_now }
&lt;/pre&gt;

&lt;p&gt;No Rails 3 (no Rails 2.3.6 e acima), podemos usar o novo m&amp;eacute;todo &lt;code&gt;cookies.permanent&lt;/code&gt; para criar um cookie com um tempo de vida longo.&lt;/p&gt;

&lt;pre class="ruby"&gt;
cookies.permanent[:last_product_id] = @product.id
&lt;/pre&gt;

&lt;p&gt;N&amp;oacute;s tamb&amp;eacute;m podemos criar cookies assinados dessa forma. Por enquanto n&amp;atilde;o entramos em detalhes sobre isso aqui, mas h&amp;aacute; um &lt;a href="http://m.onkey.org/2010/2/5/signed-and-permanent-cookies-in-rails-3"&gt;&amp;oacute;timo post&lt;/a&gt; no blog do Pratik Naik sobre esse assunto, que merece leitura. Essencialmente podemos usar o m&amp;eacute;todo &lt;code&gt;cookies.permanent.signed&lt;/code&gt; para gerar um cookie criptografado e l&amp;ecirc;-lo novamente mais tarde. Note que vamos precisar obter o &lt;code&gt;cookie_verifier_secret&lt;/code&gt; em nossa aplica&amp;ccedil;&amp;atilde;o para isso funcionar.&lt;/p&gt;

&lt;h3&gt;Usando &lt;code&gt;respond_with&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;A &amp;uacute;ltima coisa que vamos mostrar neste epis&amp;oacute;dio &amp;eacute; provavelmente a mais significativa mudan&amp;ccedil;a nos controller do Rails 3: &lt;code&gt;respond_with&lt;/code&gt;. N&amp;oacute;s vamos demonstrar isso adicionando um servi&amp;ccedil;o REST sobre uma interface XML para o nosso &lt;code&gt;ProductsController&lt;/code&gt;. Isso significa que cada uma das actions do controller ter&amp;aacute; que devolver uma resposta XML, al&amp;eacute;m de sua resposta padr&amp;atilde;o HTML.&lt;/p&gt;

&lt;p&gt;Em uma aplica&amp;ccedil;&amp;atilde;o Rails 2, n&amp;oacute;s implementar&amp;iacute;amos isso usando &lt;code&gt;respond_to&lt;/code&gt; em cada action, assim:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controllers/products_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
def index
  @products = Product.all
  respond_to do |format|
    format.html
    format.xml { render :xml =&amp;gt; @products }
  end
end
&lt;/pre&gt;

&lt;p&gt;Dentro do bloco &lt;code&gt;respond_to&lt;/code&gt; especificamos cada um dos formatos que a action responde, renderizando a vers&amp;atilde;o XML do array de produtos para uma requisi&amp;ccedil;&amp;atilde;o XML. Essa abordagem pode tornar-se inc&amp;ocirc;moda se for necess&amp;aacute;rio fazer isso para cada action de um controller.&lt;/p&gt;

&lt;p&gt;No Rails 3, podemos substituir esse c&amp;oacute;digo por uma chamada ao m&amp;eacute;todo &lt;code&gt;respond_with&lt;/code&gt;, passando o objeto apropriado, nesse caso, o array de produtos. Para o &lt;code&gt;respond_with&lt;/code&gt; funcionar tamb&amp;eacute;m precisamos usar o m&amp;eacute;todo de classe &lt;code&gt;respond_to&lt;/code&gt; para especificar quais tipos MIME o controller deve responder e assim o &lt;code&gt;respond_with&lt;/code&gt; sabe o que responder com em cada action.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controllers/products_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
class ProductsController &amp;lt; ApplicationController
  respond_to :html, :xml
  
  def index
    @products = Product.all
    respond_with @products
    end
  end

  # Other methods
end
&lt;/pre&gt;

&lt;p&gt;Agora que mudamos o nosso &lt;code&gt;ProductsController&lt;/code&gt; para usar &lt;code&gt;respond_with&lt;/code&gt;, vamos ver se as altera&amp;ccedil;&amp;otilde;es funcionaram. Se visitarmos a p&amp;aacute;gina index de produtos em um navegador, vamos ver a action index com o HTML renderizado como n&amp;oacute;s esperamos.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="http://asciicasts.com/system/photos/433/original/E224I01.png" width="800" height="333" alt="The products index page."/&gt;
&lt;/div&gt;

&lt;p&gt;E se acrescentarmos &lt;code&gt;.xml&lt;/code&gt; &amp;agrave; URL, vamos obter a resposta XML.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="http://asciicasts.com/system/photos/434/original/E224I02.png" width="801" height="199" alt="The products index page as XML.	"/&gt;
&lt;/div&gt;

&lt;p&gt;Como o m&amp;eacute;todo &lt;code&gt;respond_with&lt;/code&gt; funciona? Para uma simples requisi&amp;ccedil;&amp;atilde;o GET, como &lt;code&gt;index&lt;/code&gt;, ele procura, de acordo com o MIME type apropriado, pelo arquivo da view correspondente, como o arquivo &lt;code&gt;.html.erb&lt;/code&gt;, e renderiza. Se o &lt;code&gt;respond_with&lt;/code&gt; n&amp;atilde;o conseguir encontrar o arquivo da view, ent&amp;atilde;o ele vai tentar chamar um m&amp;eacute;todo como o &lt;code&gt;to_xml&lt;/code&gt; ou o &lt;code&gt;to_json&lt;/code&gt; para deixar o objeto que foi passado no formato adequado.&lt;/p&gt;

&lt;p&gt;Sabendo disso, podemos atualizar os m&amp;eacute;todos &lt;code&gt;show&lt;/code&gt; e &lt;code&gt;new&lt;/code&gt; no &lt;code&gt;ProductsController&lt;/code&gt; para usar o &lt;code&gt;respond_with&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controller/products_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
def show
  @product = Product.find(params[:id])
  respond_with @product
end

def new
  @product = Product.new
  respond_with @product
end
&lt;/pre&gt;

&lt;p&gt;A action &lt;code&gt;create&lt;/code&gt; &amp;eacute; mais complicada, pois ela tem alguns c&amp;oacute;digos HTML espec&amp;iacute;ficos, como por exemplo, as chamadas para &lt;code&gt;redirect_to&lt;/code&gt; e &lt;code&gt;render&lt;/code&gt;. N&amp;oacute;s n&amp;atilde;o queremos usar esses c&amp;oacute;digos em uma resposta XML. Podemos contornar o problema removendo-os do m&amp;eacute;todo e adicionando uma chamada para &lt;code&gt;respond_with&lt;/code&gt;, deixando o m&amp;eacute;todo parecido com este:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controllers/products_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
def create
  @product = Product.new(params[:product])
  if @product.save
    cookies[:last_product_id] = @product.id
    flash[:notice] = &amp;quot;Successfully created product.&amp;quot;
  end
  respond_with(@product)
end
&lt;/pre&gt;

&lt;p&gt;N&amp;oacute;s podemos fazer isso porque o &lt;code&gt;respond_with&lt;/code&gt; ir&amp;aacute; automaticamente redirecionar ou renderizar, dependendo se o objeto passado para ele &amp;eacute; v&amp;aacute;lido. Podemos agora acrescentar &lt;code&gt;respond_with&lt;/code&gt; aos outros m&amp;eacute;todos do controller, removendo qualquer c&amp;oacute;digo HTML espec&amp;iacute;fico. O c&amp;oacute;digo do nosso controller ser&amp;aacute; parecido com este:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controllers/products_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
class ProductsController &amp;lt; ApplicationController
  respond_to :html, :xml
  
  def index
    @products = Product.all
    respond_with @products
  end
  
  def show
    @product = Product.find(params[:id])
    respond_with @product
  end

  def new
    @product = Product.new
    respond_with @product
  end
  
  def create
    @product = Product.new(params[:product])
    if @product.save
      cookies[:last_product_id] = @product.id
      flash[:notice] = &amp;quot;Successfully created product.&amp;quot;
    end
    respond_with(@product)
  end

  def edit
    @product = Product.find(params[:id])
    respond_with(@product)
  end

  def update
    @product = Product.find(params[:id])
    if @product.update_attributes(params[:product])
      flash[:notice] = &amp;quot;Successfully updated product.&amp;quot;
    end
    respond_with(@product)
  end
  
  def destroy
    @product = Product.find(params[:id])
    @product.destroy
    flash[:notice] = &amp;quot;Successfully destroyed product.&amp;quot;
    respond_with(@product)
  end
end
&lt;/pre&gt;

&lt;p&gt;O m&amp;eacute;todo &lt;code&gt;respond_with&lt;/code&gt; pode ser um pouco confuso, por isso aqui vai um resumo.&lt;/p&gt;

&lt;p&gt;Para uma requisi&amp;ccedil;&amp;atilde;o GET, &lt;code&gt;respond_with&lt;/code&gt; procurar&amp;aacute; primeiro por uma view que responde ao formato espec&amp;iacute;fico. Se encontrar ir&amp;aacute; renderiz&amp;aacute;-la; caso contr&amp;aacute;rio ele ir&amp;aacute; chamar &lt;code&gt;to_xml&lt;/code&gt; (ou qualquer outro formato que foi solicitado) no objeto que foi passado para ele.&lt;/p&gt;

&lt;p&gt;Para qualquer outro tipo de solicita&amp;ccedil;&amp;atilde;o, &lt;code&gt;respond_with&lt;/code&gt; primeiro verifica se o objeto passado tem algum erro. Se isso acontecer, ent&amp;atilde;o a view apropriada ser&amp;aacute; renderizada (por exemplo, &lt;code&gt;new&lt;/code&gt; para a action &lt;code&gt;create&lt;/code&gt; e &lt;code&gt;edit&lt;/code&gt; para a action &lt;code&gt;update&lt;/code&gt;). Se n&amp;atilde;o houver nenhum erro, ent&amp;atilde;o ele ir&amp;aacute; redirecionar para a p&amp;aacute;gina espec&amp;iacute;fica do objeto (ou seja, a action &lt;code&gt;show&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;N&amp;oacute;s podemos testar isso editando um de nossos produtos.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="http://asciicasts.com/system/photos/435/original/E224I03.png" width="800" height="378" alt="Editing a product."/&gt;
&lt;/div&gt;

&lt;p&gt;Ao clicar no bot&amp;atilde;o &amp;quot;Update Product&amp;quot; a action &lt;code&gt;update&lt;/code&gt; &amp;eacute; chamada e &lt;code&gt;respond_with&lt;/code&gt; ir&amp;aacute; executar um redirecionamento para a p&amp;aacute;gina do produto.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="http://asciicasts.com/system/photos/436/original/E224I04.png" width="800" height="358" alt="The product has been successfully updated."/&gt;
&lt;/div&gt;

&lt;p&gt;Da mesma forma, se clicarmos no link &amp;quot;destroy&amp;quot;, seremos redirecionados para a p&amp;aacute;gina index.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="http://asciicasts.com/system/photos/437/original/E224I05.png" width="801" height="337" alt="respond_with redirects to the index page after deleting a product."/&gt;
&lt;/div&gt;

&lt;p&gt;Se o comportamento padr&amp;atilde;o do &lt;code&gt;respond_with&lt;/code&gt; n&amp;atilde;o satisfizer certas necessidades da nossa aplica&amp;ccedil;&amp;atilde;o, podemos personaliz&amp;aacute;-lo para determinadas actions. Como um exemplo, digamos que quando atualizarmos um produto, n&amp;oacute;s queremos o redirecionamento para a action &lt;code&gt;index&lt;/code&gt; em vez do padr&amp;atilde;o que &amp;eacute; a action &lt;code&gt;show&lt;/code&gt;. Nesse caso, podemos passar a op&amp;ccedil;&amp;atilde;o de &lt;code&gt;location&lt;/code&gt; para o &lt;code&gt;respond_with&lt;/code&gt; para que ele redirecione para uma action diferente. Para redirecionar para a p&amp;aacute;gina index de produtos em vez de um produto espec&amp;iacute;fico da p&amp;aacute;gina, podemos alterar a action &lt;code&gt;update&lt;/code&gt; da seguinte forma:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controllers/products_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
def update
  @product = Product.find(params[:id])
  if @product.update_attributes(params[:product])
    flash[:notice] = &amp;quot;Successfully updated product.&amp;quot;
  end
  respond_with(@product, :location =&amp;gt; products_url)
end
&lt;/pre&gt;

&lt;p&gt;Tamb&amp;eacute;m podemos substituir formatos espec&amp;iacute;ficos passando um bloco para o &lt;code&gt;respond_with&lt;/code&gt;, como far&amp;iacute;amos com o &lt;code&gt;respond_to&lt;/code&gt;. Portanto, se queremos apenas rederizar algum texto para o formato XML da action edit, podemos faz&amp;ecirc;-lo.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controllers/products_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
def edit
  @product = Product.find(params[:id])
  respond_with(@product) do |format|
    format.xml { render :text =&amp;gt; &amp;quot;I&amp;#x27;m XML!&amp;quot; }
  end
end
&lt;/pre&gt;

&lt;p&gt;Quando visitarmos a vers&amp;atilde;o XML da p&amp;aacute;gina de edi&amp;ccedil;&amp;atilde;o, vamos ver essa string renderizada.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="http://asciicasts.com/system/photos/438/original/E224I06.png" width="799" height="140" alt="The edit page showing the custom XML."/&gt;
&lt;/div&gt;

&lt;p&gt;Finalmente, se precisamos de uma completa personaliza&amp;ccedil;&amp;atilde;o, podemos passar uma classe responder personalizada. Dessa forma, o controller ir&amp;aacute; entregar tudo para a classe e o comportamento da resposta ser&amp;aacute; como gostar&amp;iacute;amos.&lt;/p&gt;

&lt;pre class="ruby"&gt;
respond_with(@product, :responder =&amp;gt; MyResponder)
&lt;/pre&gt;

&lt;p&gt;Para um exemplo de cria&amp;ccedil;&amp;atilde;o de uma classe responder, d&amp;ecirc; uma olhada no &lt;a href="http://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/responder.rb"&gt;Responder class&lt;/a&gt; do Rails 3. O c&amp;oacute;digo &amp;eacute; bastante f&amp;aacute;cil de ler, est&amp;aacute; bem documentado e voc&amp;ecirc; ter&amp;aacute; uma ideia melhor de como funciona uma resposta.&lt;/p&gt;

&lt;p&gt;Por esse epis&amp;oacute;dio, &amp;eacute; isso. Como voc&amp;ecirc; pode ver o &lt;code&gt;respond_with&lt;/code&gt; &amp;eacute; uma maneira muito conveniente para lidar com v&amp;aacute;rios formatos. Mas se voc&amp;ecirc; estiver personalizando-o muito, poderia ser mais f&amp;aacute;cil deixar tudo como est&amp;aacute; e n&amp;atilde;o us&amp;aacute;-lo. Alternativamente, se voc&amp;ecirc; tem um monte de duplica&amp;ccedil;&amp;atilde;o, voc&amp;ecirc; pode criar sua classe de resposta personalizada.&lt;/p&gt;</description>
      <pubDate>Thu, 05 Aug 2010 21:08:55 +0000</pubDate>
      <guid>http://pt.asciicasts.com/episodes/224-controllers-no-rails-3</guid>
      <link>http://pt.asciicasts.com/episodes/224-controllers-no-rails-3</link>
    </item>
    <item>
      <title>MongoDB e MongoMapper</title>
      <description>&lt;p&gt;&lt;a href="http://www.mongodb.org/display/DOCS/Home"&gt;MongoDB&lt;/a&gt; &amp;eacute; um banco de dados baseado em documento, que funciona de forma diferente dos tradicionais bancos de dados relacionais como o MySQL, este tipo de banco n&amp;atilde;o possui schema (schema-free).  Este epis&amp;oacute;dio ir&amp;aacute; cobrir o b&amp;aacute;sico do MongoDb com a &lt;a href="http://mongomapper.com/"&gt;gem MongoMapper&lt;/a&gt; para criar uma aplica&amp;ccedil;&amp;atilde;o simples em Rails. Muitos desenvolvedores Rails ouviram falar pela primeira vez sobre MongoDB ap&amp;oacute;s uma postagem de John Nunemaker em seu excelente &lt;a href="http://railstips.org/2009/12/18/why-i-think-mongo-is-to-databases-what-rails-was-to-frameworks"&gt;Blog RailsTips&lt;/a&gt; mostrando sete caracter&amp;iacute;sticas do MongoMapper e MongoDB que contrastam com os tradicionais bancos de dados relacionais. Este post vale a pena ser lido se voc&amp;ecirc; pensa que pode estar interessado em usar o MongoDB.&lt;/p&gt;

&lt;p&gt;Uma caracter&amp;iacute;stica mencionada na postagem do blog e que faz o MangoDB interessante  &amp;eacute; que voc&amp;ecirc; n&amp;atilde;o precisa usar migra&amp;ccedil;&amp;otilde;es, como ele &amp;eacute; basicamente um mecanismo(engine) de banco de dados sem esquema, cada linha &amp;eacute; seu pr&amp;oacute;prio documento, que pode ter seu pr&amp;oacute;prio conjunto de atributos diferentes das outras colunas no banco de dados. Como n&amp;atilde;o existe um esquema fixo n&amp;oacute;s podemos definir um se quisermos.&lt;/p&gt;

&lt;h3&gt;Instalando o MongoMapper e MongoDB&lt;/h3&gt;
&lt;p&gt;Para criar sua aplica&amp;ccedil;&amp;atilde;o vamos precisar primeiro instalar o MongoDB. O download para v&amp;aacute;rias plataformas pode ser encontrado na &lt;a href="http://www.mongodb.org/display/DOCS/Downloads"&gt;p&amp;aacute;gina de download&lt;/a&gt; no site do MongoDB. Se voc&amp;ecirc; est&amp;aacute; usando OS X h&amp;aacute; um &lt;a href="http://www.shiftcommathree.com/articles/how-to-install-mongodb-on-os-x"&gt;grande artigo&lt;/a&gt; de como instalar e configurar MongoDB no site do Cris Kampmeir&amp;rsquo;s. Este artigo inclui um arquivo &lt;code&gt;plist&lt;/code&gt; que ir&amp;aacute; permitir que voc&amp;ecirc; crie um LauchDemon para iniciar o MongoDB automaticamente ao iniciar o sistema.  O artigo faz referencia a uma vers&amp;atilde;o antiga do MongoDB ent&amp;atilde;o tenha certeza que voc&amp;ecirc; instalou a &amp;uacute;ltima vers&amp;atilde;o (1.2.0 no momento que escrevo isso). Uma vez que o MOngoDB esta instalado e configurado voc&amp;ecirc; pode visitar &lt;a href="http://localhost:28017/"&gt;http://localhost:28017/&lt;/a&gt; para ver se ele esta funcionando.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="http://asciicasts.com/system/photos/275/original/E194I01.png" width="789" height="385" alt="" /&gt;
&lt;/div&gt;

&lt;h3&gt;Criando uma aplica&amp;ccedil;&amp;atilde;o Rails com MongoDB&lt;/h3&gt;

&lt;p&gt;Agora que n&amp;oacute;s temos o MongoDb instalado e rodando podemos come&amp;ccedil;ar a criar uma app Rails que ir&amp;aacute; trabalhar com ele. N&amp;oacute;s iremos criar uma nova app do zero para este epis&amp;oacute;dio chamada &lt;code&gt;todo&lt;/code&gt;.&lt;/p&gt;

&lt;pre class="terminal"&gt;
rails todo
&lt;/pre&gt;

&lt;p&gt;Iremos usar a gem MongoMapper para habilitar &amp;agrave; conversa de nossa app com o MongoDB. Para isto n&amp;oacute;s precisamos adicionar &amp;agrave; seguinte linha no bloco config de nosso &lt;code&gt;/config/environment.rb&lt;/code&gt;.&lt;/p&gt;
&lt;p class="codeFilePath"&gt;/config/environment.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
config.gem &amp;quot;mongo_mapper&amp;quot;
&lt;/pre&gt;
&lt;p&gt;N&amp;oacute;s tamb&amp;eacute;m precisamos alguma configura&amp;ccedil;&amp;atilde;o adicional que  fazeremos dentro do arquivo initializer. No diret&amp;oacute;rio &lt;code&gt;/config/initializers&lt;/code&gt; iremos criar um arquivo chamado &lt;code&gt;mongo_config.rb&lt;/code&gt;. Neste arquivo n&amp;oacute;s apenas precisamos adicionar uma linha para dizer ao MongoMapper qual banco de dados usar.&lt;/p&gt;
&lt;p class="codeFilePath"&gt;/config/initializers/mongo_config.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
MongoMapper.database = &amp;quot;todo-#{Rails.env}&amp;quot;  
&lt;/pre&gt;

&lt;p&gt;Ao passar o ambiente atual como parte do nome do banco de dados, vamos criar diferentes bancos de dados para nosso desenvolvimento, ambiente de teste e produ&amp;ccedil;&amp;atilde;o. Se fossemos mover esta aplica&amp;ccedil;&amp;atilde;o para produ&amp;ccedil;&amp;atilde;o n&amp;atilde;o haveria necessidade de fazer autentica&amp;ccedil;&amp;atilde;o e assim por diante, mas para prop&amp;oacute;sitos de demonstra&amp;ccedil;&amp;atilde;o esta &amp;oacute;tima.&lt;/p&gt;

&lt;p&gt;O passo final na configura&amp;ccedil;&amp;atilde;o de nossa aplica&amp;ccedil;&amp;atilde;o e rodar o seguinte comando para ter certeza que a gem MongoMapper esta instalada.&lt;/p&gt;

&lt;pre class="terminal"&gt;
sudo rake gems:install
&lt;/pre&gt;

&lt;h3&gt;Construindo nossa Aplica&amp;ccedil;&amp;atilde;o&lt;/h3&gt;


&lt;p&gt;Agora n&amp;oacute;s podemos come&amp;ccedil;ar a construir nossa aplica&amp;ccedil;&amp;atilde;o. Esta &amp;eacute; uma simples aplica&amp;ccedil;&amp;atilde;o todo list que ter&amp;aacute; um modelo &lt;code&gt;Project&lt;/code&gt; e cada &lt;code&gt;Project&lt;/code&gt; ir&amp;aacute; ter v&amp;aacute;rias tarefas(&lt;code&gt;Tasks&lt;/code&gt;). Para escrever mais facilmente nossa aplica&amp;ccedil;&amp;atilde;o iremos usar o &lt;a href="http://github.com/ryanb/nifty-generators"&gt;Nifty Gererators&lt;/a&gt; do Rayns Bates, mas essa aplica&amp;ccedil;&amp;atilde;o pode ser escrita sem ele.&lt;/p&gt;

&lt;p&gt;A primeira coisa que vamos fazer &amp;eacute; criar um layout para nossa aplica&amp;ccedil;&amp;atilde;o que podemos fazer rodando:&lt;/p&gt;

&lt;pre class="terminal"&gt;
script/generate nifty_layout
&lt;/pre&gt;

&lt;p&gt;A seguir vamos gerar um model e um scaffold para ele. &lt;code&gt;Project&lt;/code&gt; ir&amp;aacute; ter apenas um campo, nome, e como n&amp;atilde;o estamos gerando um model normal do ActiveRecord iremos passar a op&amp;ccedil;&amp;atilde;o &lt;code&gt;--skip-migraton&lt;/code&gt; para que nenhum arquivo de migra&amp;ccedil;&amp;atilde;o seja gerado.&lt;/p&gt;

&lt;pre class="terminal"&gt;
script/generate nifty_scaffold project name:string --skip-migration
&lt;/pre&gt;

&lt;p&gt;Isto ir&amp;aacute; gerar um arquivo de model, controller e view para n&amp;oacute;s. O modelo &lt;code&gt;Project&lt;/code&gt; gerado ir&amp;aacute; usar o ActiveRecord ent&amp;atilde;o termos que mudar para ele usar o MongoMapper.&lt;/p&gt;

&lt;pre class="ruby"&gt;
class Project &amp;lt; ActiveRecord::Base  
	attr_accessible :name  
end
&lt;/pre&gt;

&lt;p&gt;Tudo o que temos que fazer aqui &amp;eacute; fazer com que a classe pare de herdar de &lt;code&gt;ActiveRecord::Base&lt;/code&gt; e inclua o &lt;code&gt;MongoMapper::Document&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Para definir atributos do modelo n&amp;oacute;s usamos o m&amp;eacute;todo &lt;code&gt;key&lt;/code&gt;. Passamos o nome do atributo, neste caso, &lt;code&gt;:name&lt;/code&gt;. e tambem o tipo que deve ser uma classe Ruby. Para nosso atributo &lt;code&gt;:name&lt;/code&gt; sera uma &lt;code&gt;String&lt;/code&gt;. Nosso modelo agora se parece com isto.&lt;/p&gt;
&lt;p class="codeFilePath"&gt;/app/models/project.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
	class Project  
	  include MongoMapper::Document  

	  key :name, String  
	end
&lt;/pre&gt;

&lt;p&gt;Com essa mudan&amp;ccedil;a fizemos no model n&amp;oacute;s podemos agora rodar nossa aplica&amp;ccedil;&amp;atilde;o e usar isto para criar, atualizar e listar os projetos como seria com uma aplicacao baseada em um banco de dados relacional e ActiveRecord, apenas ao inv&amp;eacute;s usando MongoMapper e MongoDB.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
	&lt;img src="http://asciicasts.com/system/photos/276/original/E194I02.png" width="801" height="347" alt="" /&gt;
&lt;/div&gt;

&lt;p&gt;Em termos de interface o MongoMapper trabalha de maneira similar ao ActiveRecord. N&amp;oacute;s podemos realizar finds e creates, update e destroy nos registro como normalmente fazemos. Ele at&amp;eacute; suporta valida&amp;ccedil;&amp;otilde;es da mesma maneira como o ActiveRecord, ent&amp;atilde;o podemos adicionar:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/models/project.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
	validates_presence_of :name  
&lt;/pre&gt;

&lt;p&gt;ao nosso model Project e n&amp;atilde;o permitir mais criar um projeto com o name em branco. Com o MongoMapper h&amp;aacute; uma maneira melhor para adicionar valida&amp;ccedil;&amp;otilde;es movendo-as para a mesma linha. Para fazer com que o atributo name seja obrigat&amp;oacute;rio podemos adicionar &lt;code&gt;:required =&amp;gt;&lt;/code&gt; true para os param&amp;ecirc;tros do m&amp;eacute;todo key.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/models/project.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
	class Project  
	  include MongoMapper::Document  

	  key :name, String, :required =&amp;gt; true  
	end
&lt;/pre&gt;

&lt;h3&gt;Adicionando mais Atributos&lt;/h3&gt;

&lt;p&gt;Como o MongoDB &amp;eacute; um banco dados sem esquema podemos facilmente adicionar ou alterar atributos no model sem a necessidade de rodar qualquer migra&amp;ccedil;&amp;atilde;o. Se n&amp;oacute;s quisermos adicionar um atributo &lt;code&gt;priority&lt;/code&gt; em nosso &lt;code&gt;Project&lt;/code&gt; podemos simplesmente adicionar isto em nosso model.&lt;/p&gt;
&lt;p class="codeFilePath"&gt;/app/models/project.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
	class Project  
	  include MongoMapper::Document  

	  key :name, String, :required =&amp;gt; true  
	  key :priority, Integer  
	end
&lt;/pre&gt;

&lt;p&gt;N&amp;oacute;s podemos interar com este novo atribuito simplesmente como seria com o ActiveRecord. Ent&amp;atilde;o,na partial form de &lt;code&gt;Project&lt;/code&gt; podemos adicionar um menu select que ir&amp;aacute; permitir que n&amp;oacute;s selecionamos a prioridade quando formos criar ou atualizar um projeto.&lt;/p&gt;
&lt;p class="codeFilePath"&gt;/app/views/projects/_form.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;
&amp;lt;% form_for @project do |f| %&amp;gt;
  &amp;lt;%= f.error_messages %&amp;gt;
  &amp;lt;p&amp;gt;
    &amp;lt;%= f.label :name %&amp;gt;&amp;lt;br /&amp;gt;
    &amp;lt;%= f.text_field :name %&amp;gt;
  &amp;lt;/p&amp;gt;
  &amp;lt;p&amp;gt;
    &amp;lt;%= f.label :priority %&amp;gt;&amp;lt;br /&amp;gt;
    &amp;lt;%= f.select :priority, [1,2,3,4,5] %&amp;gt;
  &amp;lt;/p&amp;gt;
  &amp;lt;p&amp;gt;&amp;lt;%= f.submit &amp;quot;Submit&amp;quot; %&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/pre&gt;

&lt;p&gt;N&amp;oacute;s temos que modificar a view &lt;code&gt;show&lt;/code&gt; para que possamos mostrar a prioridade de um projeto.&lt;/p&gt;


&lt;p class="codeFilePath"&gt;/app/views/projects/show.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;
&amp;lt;% title &amp;quot;Project&amp;quot; %&amp;gt;
&amp;lt;p&amp;gt;
  &amp;lt;strong&amp;gt;Name:&amp;lt;/strong&amp;gt;
  &amp;lt;%=h @project.name %&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
  &amp;lt;strong&amp;gt;Priority:&amp;lt;/strong&amp;gt;
  &amp;lt;%=h @project.priority %&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;
  &amp;lt;%= link_to &amp;quot;Edit&amp;quot;, edit_project_path(@project) %&amp;gt; |
  &amp;lt;%= link_to &amp;quot;Destroy&amp;quot;, @project, :confirm =&amp;gt; &amp;#x27;Are you sure?&amp;#x27;, :method =&amp;gt; :delete %&amp;gt; |
  &amp;lt;%= link_to &amp;quot;View All&amp;quot;, projects_path %&amp;gt;
&amp;lt;/p&amp;gt;
&lt;/pre&gt;


&lt;p&gt;Quando n&amp;oacute;s visitamos a p&amp;aacute;gina New Project agora podemos ver um menu select para a prioridade e quando criamos um novo projeto esta prioridade ir&amp;aacute; ser mostrada.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
	&lt;img src="http://asciicasts.com/system/photos/277/original/E194I03.png" width="800" height="398" alt="" /&gt;
&lt;/div&gt;

&lt;p&gt;Como n&amp;oacute;s criamos um project antes de adicionarmos o atributo &lt;code&gt;priority&lt;/code&gt; voc&amp;ecirc; pode querer saber qual a prioridade que lhe foi atribu&amp;iacute;da. Se voc&amp;ecirc; olhar nesse projeto ver&amp;aacute; que a prioridade esta em branco. Como o valor de priority n&amp;atilde;o existe  para este documento o MongoDB ir&amp;aacute; dar valor nulo(&lt;code&gt;nil&lt;/code&gt;)&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
	&lt;img src="http://asciicasts.com/system/photos/278/original/E194I04.png" width="801" height="308" alt="" /&gt;
&lt;/div&gt;

&lt;h3&gt;Associa&amp;ccedil;&amp;otilde;es&lt;/h3&gt;

&lt;p&gt;Em nosso aplicativo Todo n&amp;oacute;s tamb&amp;eacute;m queremos ter um model &lt;code&gt;Task&lt;/code&gt;(Tarefas); cada &lt;code&gt;Project&lt;/code&gt; ir&amp;aacute; ter muitas &lt;code&gt;Tasks&lt;/code&gt;(Tarefas). Iremos gerar um scaffold para isto como fizemos antes para &lt;code&gt;Project&lt;/code&gt;. Note que &lt;code&gt;project_id&lt;/code&gt; &amp;eacute; uma string,  n&amp;oacute;s normalmente usamos um integer.&lt;/p&gt;

&lt;pre class="terminal"&gt;
script/generate nifty_scaffold task project_id:string name:string completed:boolean --skip-migration
&lt;/pre&gt;

&lt;p&gt;No model de &lt;code&gt;Project&lt;/code&gt; precisamos modificar o arquivo de modelo para trabalhar com o MongoMapper, substituindo o c&amp;oacute;digo especif&amp;iacute;co do ActiveRecord&lt;/p&gt;

&lt;pre class="ruby"&gt;
	class Task  
	  include MongoMapper::Document  

	  key :project_id, ObjectId  
	  key :name, String  
	  key :completed, Boolean  

	  belongs_to :project  
	end	
&lt;/pre&gt;


&lt;p&gt;Novamente teremos que incluir o &lt;code&gt;MongoMapper::Document&lt;/code&gt; e usar o m&amp;eacute;todo key para definir os atributos do modelo. Voc&amp;ecirc; pode ter esperado que o &lt;code&gt;project_id&lt;/code&gt; tivesse o tipo &lt;code&gt;Integer&lt;/code&gt;, mas o MongoDB usa &lt;code&gt;ObjectId&lt;/code&gt; para armazenar ids.&lt;/p&gt;

&lt;p&gt;Definimos o relacionamento de Taks&amp;#x27;s com Project como seria com o ActiveRecord usando o &lt;code&gt;belongs_to&lt;/code&gt;. Em &lt;code&gt;Project&lt;/code&gt; voc&amp;ecirc; pode esperar usar &lt;code&gt;has_many :tasks&lt;/code&gt;, mas para o MongoMapper usamos &lt;code&gt;many&lt;/code&gt;.&lt;/p&gt;
&lt;p class="codeFilePath"&gt;/app/models/project.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
	class Project  
	  include MongoMapper::Document  

	  key :name, String, :required =&amp;gt; true  
	  key :priority, Integer  

	  many :tasks  
	end
&lt;/pre&gt;

&lt;p&gt;N&amp;oacute;s podemos agora rodar o aplicativo e usar o controller e view gerados para criar novas tarefas. Entrar com o id do Project no formul&amp;aacute;rio de tasks ser&amp;aacute; complicado, embora o scaffold gerou um campo de texto para &lt;code&gt;project_id&lt;/code&gt;. Isto porque n&amp;oacute;s definimos ele como uma string quando  criamos o scaffold. Vamos modificar a view para que ela use um menu select permitindo &amp;agrave; escolha de qualquer Projeto existente. Da mesma forma que seria com um formul&amp;aacute;rio do ActiveRecord  podemos usar &lt;code&gt;collection_select&lt;/code&gt; para criar um menu select que vai listar todos os projetos.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/views/tasks/_form.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;
&amp;lt;% form_for @task do |f| %&amp;gt;
  &amp;lt;%= f.error_messages %&amp;gt;
  &amp;lt;p&amp;gt;
    &amp;lt;%= f.label :project_id %&amp;gt;&amp;lt;br /&amp;gt;
    &amp;lt;%= f.collection_select :project_id, Project.all, :id, :name %&amp;gt;
  &amp;lt;/p&amp;gt;

  &amp;lt;!-- Rest of form... --&amp;gt;
&lt;/pre&gt;  

&lt;p&gt;Agora tempos um jeito f&amp;aacute;cil de selecionar um projeto quando estamos criando uma nova tarefa.&lt;/p&gt;
&lt;div class="imageWrapper"&gt;	
	&lt;img src="http://asciicasts.com/system/photos/279/original/E194I05.png" width="801" height="433" alt="" /&gt; 
&lt;/div&gt;

&lt;p&gt;Depois que n&amp;oacute;s termos uma nova tarefa criada, seremos redirecionados para a p&amp;aacute;gina dessa tarefa que ir&amp;aacute; mostrar o id do projeto. Seria melhor se pud&amp;eacute;ssemos mostrar o nome do Project ao inv&amp;eacute;s do &lt;code&gt;id&lt;/code&gt;. Podemos fazer isto substituindo &lt;code&gt;@task.project_id&lt;/code&gt; na view show por &lt;code&gt;@task.project.name&lt;/code&gt;&lt;/p&gt;


&lt;p class="codeFilePath"&gt;/app/views/tasks/show.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;
	&amp;lt;% title &amp;quot;Task&amp;quot; %&amp;gt;

	&amp;lt;p&amp;gt;
	  &amp;lt;strong&amp;gt;Project:&amp;lt;/strong&amp;gt;
	  &amp;lt;%=h @task.project.name %&amp;gt;
	&amp;lt;/p&amp;gt;
	&amp;lt;!-- Rest of form --&amp;gt;
&lt;/pre&gt;


&lt;p&gt;O formul&amp;aacute;rio ir&amp;aacute; agora mostrar o nome do projeto associado, apenas como  seria com o ActiveRecord&lt;/p&gt;
&lt;div class="imageWrapper"&gt;	
	&lt;img src="http://asciicasts.com/system/photos/280/original/E194I06.png" width="801" height="350" alt="" /&gt;
&lt;/div&gt;

&lt;h3&gt;Finds no MongoDB&lt;/h3&gt;	


&lt;p&gt;N&amp;oacute;s vamos finalizar este epis&amp;oacute;dio mostrando algumas t&amp;eacute;cnicas para usar finds para models Mongo no console. Em alguns casos &amp;eacute; muito similar ao ActiveRecord. Por exemplo, podemos procurar todos( find all) projeto com &lt;code&gt;Project.all&lt;/code&gt;&lt;/p&gt;

&lt;pre class="terminal"&gt;
&amp;gt;&amp;gt; Project.all
=&amp;gt; [#&amp;lt;Project name: &amp;quot;Yardwork&amp;quot;, _id: 4b39d8c9a175750357000001, priority: nil&amp;gt;, #&amp;lt;Project name: &amp;quot;Housework&amp;quot;, _id: 4b39fbd1a175750357000002, priority: 3&amp;gt;]
&lt;/pre&gt;

&lt;p&gt;Podemos tamb&amp;eacute;m procurar um projeto por &lt;code&gt;id&lt;/code&gt;...&lt;/p&gt;

&lt;pre class="terminal"&gt;&amp;gt;&amp;gt; Project.find(&amp;#x27;4b39d8c9a175750357000001&amp;#x27;)
=&amp;gt; #&amp;lt;Project name: &amp;quot;Yardwork&amp;quot;, _id: 4b39d8c9a175750357000001, priority: nil&amp;gt;
&lt;/pre&gt;

&lt;p&gt;... ou fornecer op&amp;ccedil;&amp;otilde;es para procurar todos os registros em uma dada ordem.&lt;/p&gt;

&lt;pre class="terminal"&gt;&amp;gt;&amp;gt; Project.all(:order =&amp;gt; &amp;quot;name DESC&amp;quot;)
=&amp;gt; [#&amp;lt;Project name: &amp;quot;Yardwork&amp;quot;, _id: 4b39d8c9a175750357000001, priority: nil&amp;gt;, #&amp;lt;Project name: &amp;quot;Housework&amp;quot;, _id: 4b39fbd1a175750357000002, priority: 3&amp;gt;]
&lt;/pre&gt;

&lt;p&gt;Como o ActiveRecord n&amp;oacute;s podemos passar condi&amp;ccedil;&amp;otilde;es para o &lt;code&gt;find&lt;/code&gt;. Este difere do ActiveRecord em que as condi&amp;ccedil;&amp;otilde;es s&amp;atilde;o passadas inline ent&amp;atilde;o n&amp;oacute;s ir&amp;iacute;mos procurar todos os projetos com  prioridade 3:&lt;/p&gt;

&lt;pre class="terminal"&gt;&amp;gt;&amp;gt; Project.all(:priority =&amp;gt; 3)
=&amp;gt; [#&amp;lt;Project name: &amp;quot;Housework&amp;quot;, _id: 4b39fbd1a175750357000002, priority: 3&amp;gt;]
&lt;/pre&gt;

&lt;p&gt;E sobre as condi&amp;ccedil;&amp;otilde;es mais complexas? Como o Mongo n&amp;atilde;o &amp;eacute; baseado em SQL n&amp;atilde;o podemos simplesmente passar uma string SQL para a condi&amp;ccedil;&amp;atilde;o. Ao inv&amp;eacute;s ele tem sua pr&amp;oacute;pria linguagem para criar condi&amp;ccedil;&amp;otilde;es mais complexas. MongoMapper fornece um jeito conveniente para contornar isto passando um m&amp;eacute;todo para um s&amp;iacute;mbolo . Por exemplo, para pegar todos os projetos que tenham prioridade de dois ou mais, podemos fazer:&lt;/p&gt;


&lt;pre class="terminal"&gt;&amp;gt;&amp;gt; Project.all(:priority.gte =&amp;gt; 2)
=&amp;gt; [#&amp;lt;Project name: &amp;quot;Housework&amp;quot;, _id: 4b39fbd1a175750357000002, priority: 3&amp;gt;]
&lt;/pre&gt;

&lt;p&gt;N&amp;oacute;s podemos tamb&amp;eacute;m usar &lt;code&gt;in&lt;/code&gt;, passando um array de valores para o find, dizendo, projetos com a prioridade 2 ou 3.&lt;/p&gt;

&lt;pre class="terminal"&gt;&amp;gt;&amp;gt; Project.all(:priority.in =&amp;gt; [2,3])
=&amp;gt; [#&amp;lt;Project name: &amp;quot;Housework&amp;quot;, _id: 4b39fbd1a175750357000002, priority: 3&amp;gt;]
&lt;/pre&gt;
&lt;p&gt;A Documenta&amp;ccedil;&amp;atilde;o &amp;eacute; um pouco escassa sobre condi&amp;ccedil;&amp;otilde;es no momento, mas voc&amp;ecirc; pode descobrir mais sobre eles atrav&amp;eacute;s da leitura do &lt;a href="http://github.com/jnunemaker/mongomapper/blob/1831798fe3b8b2aea398435a4b1ea6f29f1a63c5/test/test_finder_options.rb"&gt;arquivo de test no github&lt;/a&gt;. Isto &amp;eacute; tudo por esse epis&amp;oacute;dio. N&amp;oacute;s apenas cobrimos o b&amp;aacute;sico do MongoDB e MongoMapper ent&amp;atilde;o voc&amp;ecirc; esta encorajado a fazer sua pr&amp;oacute;pria pesquisa se quiser continuar. A uma &lt;a href="http://groups.google.com/group/mongodb-user"&gt;maillgin list&lt;/a&gt; voc&amp;ecirc; pode se juntar a ela e voc&amp;ecirc; pode seguir o &lt;a href="http://twitter.com/mongodb"&gt;MongoDB no Twiiter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A grande quest&amp;atilde;o que voc&amp;ecirc; precisa fazer para si mesmo &amp;eacute;, devo usar MongoDb ao inv&amp;eacute;s de um tradicional bando de dados relacional? Isto realmente cabe a voc&amp;ecirc; pensar e decidir se o MongoDB &amp;eacute; apropriado para seu Projeto Rails. Mas voc&amp;ecirc; esta incentivado a dar uma chance para ver se ele se ajusta ao seu projeto. Em termos mais longos parece que os bancos de dados baseados em documentos ir&amp;atilde;o desempenhar um grande papel na constru&amp;ccedil;&amp;atilde;o de aplica&amp;ccedil;&amp;otilde;es Rails.&lt;/p&gt;</description>
      <pubDate>Sun, 10 Jan 2010 00:30:06 +0000</pubDate>
      <guid>http://pt.asciicasts.com/episodes/194-mongodb-e-mongomapper</guid>
      <link>http://pt.asciicasts.com/episodes/194-mongodb-e-mongomapper</link>
    </item>
  </channel>
</rss>

