<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="pt-BR">
  <id>tag:www.levyonrails.com,2005:/feed</id>
  <link type="text/html" rel="alternate" href="http://www.levyonrails.com" />
  
  <title>Levy on Rails</title>
  <updated>2009-05-30T13:39:54Z</updated>
  <link rel="self" href="http://feeds.feedburner.com/LevyOnRails" type="application/atom+xml" /><feedburner:emailServiceId>LevyOnRails</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry>
    <id>tag:www.levyonrails.com,2005:Post/24</id>
    <published>2009-05-30T13:39:54Z</published>
    <updated>2009-05-30T13:46:31Z</updated>
    <link type="text/html" rel="alternate" href="http://feedproxy.google.com/~r/LevyOnRails/~3/mwHqFqKkbCI/24-changed-domain" />
    <title>Changed domain</title>
    <content type="html">&lt;p&gt;Following on the steps of &lt;a href="http://drnicwilliams.com/"&gt;Dr.Nic&lt;/a&gt;, the guy from the Ruby on Rails fame and the one that recommends everyone to have a domain name with their own name, I decided to move this blog from LevyOnRails.com to the domain &lt;a href="http://levycarneiro.com/"&gt;LevyCarneiro.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I found having "Rails" in the name was a little restrictive, being I wanted to cover a wider spectrum of Web technology knowledge. And why not, sometimes post things about my hobbies and other stuff I find interesting.&lt;/p&gt;

&lt;p&gt;I also changed from a Rails custom blog, to using Wordpress, which I find is much more suited for the task, since I didn't have much time to add everything I wanted, and Wordpress is ready with so many plugins, widgets and themes already to use. &lt;a href="http://www.pragprog.com/the-pragmatic-programmer"&gt;Being pragmatic is good!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's it.&lt;/p&gt;

&lt;p&gt;So please add the new feed to your reader:&lt;br&gt;&lt;a href="http://feeds2.feedburner.com/LevyCarneiro"&gt;http://feeds2.feedburner.com/LevyCarneiro&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Please visit the &lt;a href="http://levycarneiro.com/"&gt;new site&lt;/a&gt; from now on.&lt;/p&gt;

&lt;p&gt;Thanks for watching!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/LevyOnRails/~4/mwHqFqKkbCI" height="1" width="1"/&gt;</content>
    <author>
      <name>Levy Carneiro Jr.</name>
    </author>
  <feedburner:origLink>http://www.levyonrails.com/posts/24-changed-domain</feedburner:origLink></entry>
  <entry>
    <id>tag:www.levyonrails.com,2005:Post/23</id>
    <published>2009-04-26T21:39:42Z</published>
    <updated>2009-04-26T21:39:42Z</updated>
    <link type="text/html" rel="alternate" href="http://feedproxy.google.com/~r/LevyOnRails/~3/XZoFw49yiM8/23-tr-nsito-n-o-um-experimento-com-twitter-tr-nsito-e-ruby-on-rails" />
    <title>Trânsito Não! Um experimento com Twitter, Trânsito e Ruby on Rails</title>
    <content type="html">&lt;p&gt;O &lt;a href="http://twitter.com"&gt;Twitter&lt;/a&gt; se tornou uma grande ferramenta para interação social, já até ameaçando o conteúdo oferecido em &lt;a href="http://www.techcrunch.com/2009/03/10/are-blogs-losing-their-authority-to-the-statusphere/"&gt;blogs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Indo ainda mais longe, alguns já falam que não importa mais quantos seguidores você tenha no Twitter, mas que a pessoa com maior autoridade é aquela com o &lt;a href="http://danzarrella.com/introducing-the-retweetability-metric.html"&gt;maior número de mensagens "retweetadas"&lt;/a&gt;, mostrando então que o que esta pessoa escreve é conteúdo bom e merece ser repassado a todos.&lt;/p&gt;

&lt;p&gt;O projeto &lt;a href="http://transitonao.com.br"&gt;Trânsito Não!&lt;/a&gt; é um experimento social com Twitter e um assunto que deixa todo mundo fora de si: o trânsito. Este website conta tweets enviados como idéias e/ou votos, gerando um espaço público de discussão sobre um dos problemas mais urgentes destes dias.&lt;/p&gt;

&lt;p&gt;Este projeto é direcionado a todo o Brasil, só que mais especialmente aquelas pessoas que vivem na Grande São Paulo, uma região com cerca de 17 milhões de habitantes que experimentam um dos maiores volumes de tráfego de veículos do mundo.&lt;/p&gt;

&lt;p&gt;Usei &lt;a href="http://rubyonrails.org/"&gt;Ruby on Rails&lt;/a&gt; para construir este site. Este framework web oferece grande produtividade ao desenvolvedor. Se você ainda não assistiu, não deixe de ver este &lt;a href="http://media.rubyonrails.org/video/rails_blog_2.mov"&gt;vídeo que mostra a criação de um blog em apenas 15 minutos usando Ruby on Rails&lt;/a&gt;.

&lt;p&gt;O sistema de votação funciona assim: você envia um tweet (no Twitter) com uma idéia ou solução para resolver o problema do trânsito. Esta idéia vira então uma "idéia" dentro do Trânsito Não! Cada retweet da sua idéia, vira um voto. Então quanto mais a sua idéia se espalhar no Twitter, mais votos ela recebe no site. Os tweets são obtidos do Twitter através de uma API que é lida a cada minuto. As idéias ou votos são adicionados ao banco de dados, e as páginas são geradas novamente.&lt;/p&gt;

&lt;p&gt;Você pode me encontrar em meu &lt;a href="http://www.levyonrails.com"&gt;blog&lt;/a&gt;, 
&lt;a href="http://twitter.com/levycarneiro"&gt;Twitter&lt;/a&gt;, 
ou por &lt;a href="mailto:levy@levycarneiro.com"&gt;e-mail&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/LevyOnRails/~4/XZoFw49yiM8" height="1" width="1"/&gt;</content>
    <author>
      <name>Levy Carneiro Jr.</name>
    </author>
  <feedburner:origLink>http://www.levyonrails.com/posts/23-tr-nsito-n-o-um-experimento-com-twitter-tr-nsito-e-ruby-on-rails</feedburner:origLink></entry>
  <entry>
    <id>tag:www.levyonrails.com,2005:Post/22</id>
    <published>2009-04-26T21:27:07Z</published>
    <updated>2009-04-26T21:29:20Z</updated>
    <link type="text/html" rel="alternate" href="http://feedproxy.google.com/~r/LevyOnRails/~3/2LEIoKWKACk/22-transito-n-o-an-experiment-with-twitter-traffic-jams-and-ruby-on-rails" />
    <title>Transito Não! An experiment with Twitter, Traffic Jams and Ruby on Rails</title>
    <content type="html">&lt;p&gt;&lt;a href="http://twitter.com/"&gt;Twitter&lt;/a&gt; has become a great tool for social interaction, and it's also gaining &lt;a href="http://www.techcrunch.com/2009/03/10/are-blogs-losing-their-authority-to-the-statusphere/"&gt;more authority than content in blogs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Going even further, some people say it doesn't matter how many followers you have on Twitter, but instead &lt;a href="http://danzarrella.com/introducing-the-retweetability-metric.html"&gt;what matters is how many times your tweets get forwarded by those following you&lt;/a&gt;, showing that this person writes more valuable content, which deserves to be sent over to other people.&lt;/p&gt;

&lt;p&gt;The project &lt;a href="http://transitonao.com.br"&gt;Trânsito Não!&lt;/a&gt; (which stands for "No To Traffic!") is a social experiment with Twitter and a subject that gets everyone mad: the traffic jams. This web app cast tweets as ideas and/or votes, generating a public web space to debate on one of the most urgent problems of these days.&lt;/p&gt;

&lt;p&gt;This project is aimed at the Brazilian people, specially those people living in the greater area of Sao Paulo, a region with about 17 million people experiencing one of the biggest car traffics in the world.&lt;/p&gt;

&lt;p&gt;I developed this website with &lt;a href=""http://rubyonrails.org/&gt;Ruby on Rails&lt;/a&gt;. This web framework offers great productivity to the developer. If you haven't the chance yet, don't miss this &lt;a href="http://media.rubyonrails.org/video/rails_blog_2.mov"&gt;video showing a complete web blog written in only 15 minutes using Ruby on Rails&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The voting works like this: you tweet some idea or solution for the traffic problems, followed by the hashtag #transitonao. This tweet becomes a "idea" on TransitoNao website. If your tweet gets retweeded X times, these X times become votes for your idea. So the longer your idea spreads, the more votes you get. New tweets are read from the Twitter API every minute, being added to the database, and the pages being also refreshed (using page caching).&lt;/p&gt;

&lt;p&gt;You can find me on my &lt;a href="http://www.levyonrails.com/"&gt;blog&lt;/a&gt;, &lt;a href="http://twitter.com/levycarneiro"&gt;Twitter&lt;/a&gt;, or at my &lt;a href="levy@levycarneiro.com"&gt;personal email&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/LevyOnRails/~4/2LEIoKWKACk" height="1" width="1"/&gt;</content>
    <author>
      <name>Levy Carneiro Jr.</name>
    </author>
  <feedburner:origLink>http://www.levyonrails.com/posts/22-transito-n-o-an-experiment-with-twitter-traffic-jams-and-ruby-on-rails</feedburner:origLink></entry>
  <entry>
    <id>tag:www.levyonrails.com,2005:Post/21</id>
    <published>2009-02-12T10:46:04Z</published>
    <updated>2009-02-12T10:46:04Z</updated>
    <link type="text/html" rel="alternate" href="http://feedproxy.google.com/~r/LevyOnRails/~3/JbTZarDvhgA/21-what-is-scrum-learn-it-in-less-than-1-minutes" />
    <title>What is SCRUM? Learn it in less than 10 minutes</title>
    <content type="html">&lt;p&gt;This guy put together a presentation on &lt;b&gt;what is SCRUM&lt;/b&gt;. It's very informative and to the point. "By the end of this fast-paced video, you'll know about burn-down charts, team roles, product backlogs, sprints, daily scrums and more."&lt;/p&gt;

&lt;p&gt;I'm so glad I'm able to breathe, because this guy wasn't :)&lt;/p&gt;

&lt;object width="480" height="295"&gt;&lt;param name="movie" value="http://www.youtube.com/v/Q5k7a9YEoUI&amp;hl=en&amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/Q5k7a9YEoUI&amp;hl=en&amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="295"&gt;&lt;/embed&gt;&lt;/object&gt;
&lt;img src="http://feeds.feedburner.com/~r/LevyOnRails/~4/JbTZarDvhgA" height="1" width="1"/&gt;</content>
    <author>
      <name>Levy Carneiro Jr.</name>
    </author>
  <feedburner:origLink>http://www.levyonrails.com/posts/21-what-is-scrum-learn-it-in-less-than-1-minutes</feedburner:origLink></entry>
  <entry>
    <id>tag:www.levyonrails.com,2005:Post/20</id>
    <published>2009-02-07T18:19:39Z</published>
    <updated>2009-02-07T18:19:39Z</updated>
    <link type="text/html" rel="alternate" href="http://feedproxy.google.com/~r/LevyOnRails/~3/DyITFVjsjyc/20-testing-route-helper-methods-and-formatted-routes" />
    <title>Testing route helper methods and formatted routes</title>
    <content type="html">&lt;p&gt;Here's a quick tip on how to test those helpers such as 'new_post_path' and 'home_path'. Also those formatted routes such as 'formatted_posts_path'. And why is important to test those.&lt;/p&gt;

&lt;p&gt;Here's how I test route helper methods.&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# spec/controllers/ideas_controller_spec.rb

describe IdeasController do
  describe "GET /ideas/new" do
    it "should have helper method new_idea_path" do
      get :new
      new_idea_path.should_not be_nil
      new_idea_path.should == '/ideas/new'
    end

    it "should have helper method formatted_new_idea_path" do
      get :new, :format =&gt; :json
      formatted_new_idea_path.should_not be_nil
      formatted_new_idea_path.should == '/ideas/new.json'
    end

    (...)
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And why it's important to test those methods, since they're already tested by Rails tests?&lt;/p&gt;

&lt;p&gt;Rails 2.3 has removed all those formatted_xxx named routes. Turns out these routes ate up a lot of memory and served minimal purpose. Read article &lt;a href="http://ryandaigle.com/articles/2008/11/27/what-s-new-in-edge-rails-no-more-formatted-routes
"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So if you use something like formatted_new_user, and you need to upgrade the application to Rails 2.3, it would be broken without test coverage.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/LevyOnRails/~4/DyITFVjsjyc" height="1" width="1"/&gt;</content>
    <author>
      <name>Levy Carneiro Jr.</name>
    </author>
  <feedburner:origLink>http://www.levyonrails.com/posts/20-testing-route-helper-methods-and-formatted-routes</feedburner:origLink></entry>
  <entry>
    <id>tag:www.levyonrails.com,2005:Post/19</id>
    <published>2009-02-07T17:34:10Z</published>
    <updated>2009-02-07T17:35:58Z</updated>
    <link type="text/html" rel="alternate" href="http://feedproxy.google.com/~r/LevyOnRails/~3/hg1db3EUj3o/19-cucumber-generic-method-for-handling-webrat-visit-method" />
    <title>Cucumber generic method for handling Webrat visit method</title>
    <content type="html">&lt;p&gt;Here's a tip for creating a generic Cucumber step, handling the Webrat visit method.&lt;/p&gt;

&lt;p&gt;Imagine you have many Cucumber scenarios, and you have many steps like these:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
  Given I am on the new task page
  Given I am on the new project page
  Given I am on the home page
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This way you'd have to create mapping between these strings above, to real paths inside the application. You could use the method 'path_to', which is already provided with Cucumber, inside features/support/paths.rb. That could lead to something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# features/support/paths.rb

def path_to(page_name)
  case page_name

  when /new task/i
    new_task_path
  when /tasks/i
    tasks_path

  when /new user/i
    new_user_path
  when /users/i
    users_path

  when /home/i
    root_path

  # and so forth...

  else
    raise "Can't find mapping from \"#{page_name}\" to a path."
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or you could use something more generic and more maintanable.&lt;/p&gt;

&lt;p&gt;So, let's take advantage of the path helpers already provided by Rails such as new_task_page, tasks_path, home_path, and do this instead:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
  Given I am on the new_task page
  Given I am on the new_project page
  Given I am on the home page
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And add this to your create_task_steps.rb:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# features/step_definitions/create_task_steps.rb

Given /^I am on the (.+) page$/ do |page_name|
  eval("visit #{page_name}_path")
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This way Webrat will visit the path: new_page_path, and you won't have to maintain the paths.rb file.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/LevyOnRails/~4/hg1db3EUj3o" height="1" width="1"/&gt;</content>
    <author>
      <name>Levy Carneiro Jr.</name>
    </author>
  <feedburner:origLink>http://www.levyonrails.com/posts/19-cucumber-generic-method-for-handling-webrat-visit-method</feedburner:origLink></entry>
  <entry>
    <id>tag:www.levyonrails.com,2005:Post/18</id>
    <published>2009-02-06T18:47:52Z</published>
    <updated>2009-02-12T10:47:27Z</updated>
    <link type="text/html" rel="alternate" href="http://feedproxy.google.com/~r/LevyOnRails/~3/rJ8kekqn_GE/18-scaling-rails" />
    <title>Scaling Rails</title>
    <content type="html">&lt;p&gt;Gregg Pollack and New Relic just launched a Screencast series on &lt;b&gt;Scaling Rails&lt;/b&gt;. And, it's free! :)&lt;/p&gt;

&lt;a href="http://railslab.newrelic.com/scaling-rails"&gt;"Scaling Rails Screencast Series"&lt;/a&gt; produced by Gregg Pollack and supported by New Relic.&lt;/p&gt;

&lt;p&gt;"Learn everything you need to know about Scaling your Rails app through 13 informative Screencasts produced by Gregg Pollack with the support of New Relic. In the next few weeks we’re going to bring you 13 educational videos, teaching you just about everything you need to know to create a Rails application that can scale."&lt;/p&gt;

&lt;p&gt;Topics covered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://railslab.newrelic.com/2009/01/22/introduction"&gt;Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://railslab.newrelic.com/2009/01/22/page-responsiveness"&gt;Episode #1 - Page Responsiveness&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://railslab.newrelic.com/2009/01/22/page-caching"&gt;Episode #2 - Page Caching&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://railslab.newrelic.com/2009/01/22/cache-expiration"&gt;Episode #3 - Cache Expiration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://railslab.newrelic.com/2009/01/22/new-relic-rpm"&gt;Episode #4 - New Relic RPM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://railslab.newrelic.com/2009/02/05/episode-5-advanced-page-caching"&gt;Episode #5 - Advanced Page Caching&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://railslab.newrelic.com/2009/02/09/episode-6-action-caching"&gt;Episode #6 - Action Caching&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://railslab.newrelic.com/2009/02/09/episode-7-fragment-caching"&gt;Episode #7 - Fragment Caching&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Episode #8 - Memcached&lt;/li&gt;
&lt;li&gt;Episode #9 - Client Side Caching&lt;/li&gt;
&lt;li&gt;Episode #10 - Advanced HTTP Caching&lt;/li&gt;
&lt;li&gt;Episode #11 - Database Speed, by Taylor Weibly from EngineYard&lt;/li&gt;
&lt;li&gt;Episode #12 - Deployment Strategies, by Jesse Newland from RailsMachine&lt;/li&gt;
&lt;li&gt;Episode #13 - New Relic Advanced Features, by Jim Gochee from New Relic&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/LevyOnRails/~4/rJ8kekqn_GE" height="1" width="1"/&gt;</content>
    <author>
      <name>Levy Carneiro Jr.</name>
    </author>
  <feedburner:origLink>http://www.levyonrails.com/posts/18-scaling-rails</feedburner:origLink></entry>
  <entry>
    <id>tag:www.levyonrails.com,2005:Post/17</id>
    <published>2009-02-02T10:32:49Z</published>
    <updated>2009-02-02T10:33:13Z</updated>
    <link type="text/html" rel="alternate" href="http://feedproxy.google.com/~r/LevyOnRails/~3/wNiPPDKWH9o/17-no-need-for-touching-restart-txt-a-tip-for-passenger-users" />
    <title>No need for touching restart.txt. A tip for Passenger users</title>
    <content type="html">&lt;p&gt;Natham writes about this tip I found today. This one helps to speed up the deployment with Passenger a little bit. In your Capistrano, Vlad, etc, you probably have a step that runs:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
touch tmp/restart.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is needed, so Passenger (mod_rails) is able to know when it should restart itself. Now, think about this:&lt;/p&gt;

&lt;b&gt;Commit "tmp/restart.txt" to your Git repository.&lt;/b&gt;

&lt;p&gt;This way you'll never have to touch tmp/restart.txt again. This will be deleted when Passenger notices it. And on the next deployment, it'll be rewritten again, with your deploy script (Capistrano/etc), that probably runs something like "git reset; git pull", and Passenger will notices again, restart. And so forth.&lt;/p&gt;

&lt;p&gt;Clever, isn't? :)&lt;/p&gt;

&lt;p&gt;Source: &lt;a href="http://codedlite.com/blog/?p=57"&gt;A tip for Passenger(mod_rails) users&lt;/a&gt; by Nathan.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/LevyOnRails/~4/wNiPPDKWH9o" height="1" width="1"/&gt;</content>
    <author>
      <name>Levy Carneiro Jr.</name>
    </author>
  <feedburner:origLink>http://www.levyonrails.com/posts/17-no-need-for-touching-restart-txt-a-tip-for-passenger-users</feedburner:origLink></entry>
  <entry>
    <id>tag:www.levyonrails.com,2005:Post/16</id>
    <published>2009-02-01T21:52:59Z</published>
    <updated>2009-02-02T10:56:22Z</updated>
    <link type="text/html" rel="alternate" href="http://feedproxy.google.com/~r/LevyOnRails/~3/xZpckVGNl-8/16-which-methods-in-ruby-should-contain-a-bang-sign-" />
    <title>Which methods in Ruby should contain a bang sign?</title>
    <content type="html">&lt;p&gt;I always thought the bang sign (!) in Ruby methods were meant to say: "I'm destructive, I'll change your object". Like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
def do_something
end

def do_something!
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now I know better. Actually the bang sign (!) is only meant to give you and other developers a warning, like "I'm more dangerous than the other version, the non-bang one."&lt;/p&gt;

&lt;h2&gt;Which methods should have a bang sign?&lt;/h2&gt;

&lt;p&gt;Matz says, on January 28, 2009 (EST):&lt;/p&gt;

&lt;p&gt;The bang (!) does not mean "destructive" nor lack of it mean non destructive either.  The bang sign means "the bang version is more dangerous than its non bang counterpart; handle with care".  Since Ruby has a lot of "destructive" methods, if bang signs follow your opinion, every Ruby program would be full of bangs, thus ugly.&lt;/p&gt;

&lt;p&gt;And I (David A. Black) say:&lt;/p&gt;

&lt;p&gt;So please stop writing bang methods that have no non-bang equivalent! The bang in isolation literally means nothing. It's purely ornamental, and dilutes the conventional usage (see above) to the point where it's
unrecognizable and pointless.&lt;/p&gt;

&lt;p&gt;(Exception: things like Builder, where the bang/non-bang distinction is completely redefined, and documented as having been redefined, for the sake of domain-specific semantics.)&lt;/p&gt;

&lt;p&gt;Source: &lt;a href="http://www.wobblini.net/bang.txt"&gt;this comment&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/LevyOnRails/~4/xZpckVGNl-8" height="1" width="1"/&gt;</content>
    <author>
      <name>Levy Carneiro Jr.</name>
    </author>
  <feedburner:origLink>http://www.levyonrails.com/posts/16-which-methods-in-ruby-should-contain-a-bang-sign-</feedburner:origLink></entry>
  <entry>
    <id>tag:www.levyonrails.com,2005:Post/15</id>
    <published>2009-01-29T15:52:42Z</published>
    <updated>2009-01-29T15:56:49Z</updated>
    <link type="text/html" rel="alternate" href="http://feedproxy.google.com/~r/LevyOnRails/~3/yTNr2BVb6D4/15-the-rspec-book-is-in-beta-" />
    <title>The RSpec Book is in beta!</title>
    <content type="html">&lt;p&gt;A whole lot of Ruby developers are waiting for this book. It's finally in Beta state, which means you can buy the PDF version and download new versions as the book is being written. For only US$ 24 it's a bargain!&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;Title:&lt;/b&gt; &lt;a href="http://www.pragprog.com/titles/achbd/the-rspec-book"&gt;The RSpec Book: Behaviour Driven Development with RSpec, Cucumber and Friends&lt;/a&gt;&lt;br/&gt;
350 pages, Apr 2009&lt;br/&gt;
&lt;b&gt;Authors&lt;/b&gt;: by David Chelimsky, Dave Astels, Zach Dennis, Aslak Hellesoy, Bryan Helmkamp, Dan North.&lt;br/&gt;
&lt;b&gt;ISBN&lt;/b&gt;: 9781934356371
&lt;/p&gt;

&lt;p&gt;Is your team trying to do TDD and failing? Are you finding your test suites bloated and difficult to read, understand, or maintain? Business applications today are plagued with features that are never used, highly coupled code that is hard to change, and expensive test suites that aren’t run any more because they are brittle and unreadable.&lt;/p&gt;

&lt;p&gt;RSpec, Ruby’s leading Behaviour Driven Development tool, helps you do TDD right by embracing the design and documentation aspects of TDD. It encourages readable, maintainable suites of code examples that not only test your code, they document it as well. The RSpec Book will teach you how to use RSpec, Cucumber, and other Ruby tools to develop truly agile software that gets you to market quickly and maintains its value as evolving market trends drive new requirements.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/LevyOnRails/~4/yTNr2BVb6D4" height="1" width="1"/&gt;</content>
    <author>
      <name>Levy Carneiro Jr.</name>
    </author>
  <feedburner:origLink>http://www.levyonrails.com/posts/15-the-rspec-book-is-in-beta-</feedburner:origLink></entry>
  <entry>
    <id>tag:www.levyonrails.com,2005:Post/14</id>
    <published>2009-01-13T17:18:42Z</published>
    <updated>2009-01-13T17:18:42Z</updated>
    <link type="text/html" rel="alternate" href="http://feedproxy.google.com/~r/LevyOnRails/~3/mFdGSnuEqnE/14-tratando-m-ltiplos-models-em-um-nico-form" />
    <title>Tratando Múltiplos Models em Um Único Form</title>
    <content type="html">&lt;p&gt;O livro &lt;a href="http://pragprog.com/titles/fr_arr/advanced-rails-recipes"&gt;Advanced Rails Recipes&lt;/a&gt; é um livro muito interessante para quem quer aprender algumas dicas mais avançadas de Rails. Especialmente aquele tipo de dicas que você não encontra em tutoriais ou blogs por aí. Da descrição do site:&lt;/p&gt;

&lt;p&gt;"Você irá aprender como os profissionais resolveram problemas complicados usando as técnicas mais atualizadas de Rails 2, para que você possa entregar a sua impressionante aplicação Web de forma mais fácil e mais rápida."&lt;/p&gt;

&lt;p&gt;Esta é uma tradução para o português, com autorização de &lt;a href="http://pragprog.com/about"&gt;Dave Thomas&lt;/a&gt; de &lt;a href="http://pragprog.com/"&gt;Pragmatic Programers&lt;/a&gt;. Aproveite! :)&lt;/p&gt;&lt;br&gt;

&lt;h2&gt;Tratando Múltiplos Models em Um Único Form&lt;/h2&gt;

&lt;p&gt;Por Ryan Bates (http://railscasts.com/). Ryan trabalha com desenvolvimento Web desde 1998. Começou a trabalhar profissionalmente com Ruby on Rails em 2005 e é mais conhecido pelo seu trabalho com os Railscasts, uma série gratuita de screencasts sobre Ruby on Rails.&lt;/p&gt;

&lt;h2&gt;Problema&lt;/h2&gt;

&lt;p&gt;A maioria do código Rails que você encontra geralmente trata um model de cada vez. Isso nem sempre é prático. Algumas vezes você precisa criar e/ou editar dois (ou mais) models em um único form, nas situações onde você tem uma associação one-to-many entre os models.&lt;/p&gt;

&lt;h2&gt;Solução&lt;/h2&gt;

&lt;p&gt;Digamos que nós precisamos salvar todas as tarefas pendentes para vários projetos. Quando nós criarmos ou atualizarmos um projeto, nós gostaríamos de adicionar, remover e atualizar suas tarefas, em um único form. O que estamos imaginando é:&lt;/p&gt;

&lt;img src="/images/posts/Multiple_models_one_form_NewProject.jpg"&gt;

&lt;p&gt;Vamos começar criando um relacionamento &lt;i&gt;has_many&lt;/i&gt; entre &lt;i&gt;Project&lt;/i&gt; e &lt;i&gt;Task&lt;/i&gt;. Para simplificar, vamos dar para cada model um atributo obrigatório chamado &lt;i&gt;name&lt;/i&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# Arquivo: app/models/project.rb
class Project &lt; ActiveRecord::Base
  has_many :tasks, :dependent =&gt; :destroy
  validates_presence_of :name
end

# Arquivo: app/models/task.rb
class Task &lt; ActiveRecord::Base
  belongs_to :project
  validates_presence_of :name
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Nós vamos usar a biblioteca de Javascript Prototype, então antes de qualquer coisa vamos garantir que ela está carregada em nosso arquivo de layout:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# Arquivo: app/views/layouts/application.html.erb
&lt;%= javascript_include_tag :defaults %&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Vamos voltar a nossa atenção para o form, para criar um projeto com suas múltiplas tarefas, e associadas ao projeto. Quando precisamos tratar múltiplos models em um form, é muito útil eleger um model como sendo o foco primário ou principal, e a partir daí construir os models adicionais através da associação entre eles.&lt;/p&gt;

&lt;p&gt;Neste caso, vamos fazer de &lt;i&gt;Project&lt;/i&gt; o nosso model primário e construir suas tarefas através da associação &lt;i&gt;has_many&lt;/i&gt;. Então para a action new de nosso &lt;i&gt;ProjectsController&lt;/i&gt;, nós criamos um objeto &lt;i&gt;Project&lt;/i&gt; da forma usual. No entanto, nós também inicializamos uma nova &lt;i&gt;Task&lt;/i&gt; (em memória) que é associada com o &lt;i&gt;Project&lt;/i&gt; de forma que nosso form tem alguma coisa para começar a trabalhar:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# Arquivo: app/controllers/projects_controller.rb
def new
  @project = Project.new
  @project.tasks.build
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;O template para o form precisa de algumas “manhas” já que nós precisamos tratar os campos para o model &lt;i&gt;Project&lt;/i&gt; e também os campos de cada um dos models &lt;i&gt;Task&lt;/i&gt;. Então, vamos quebrar o problema em partes menores e usar um partial para renderizar os campos da &lt;i&gt;Task&lt;/i&gt; e adicionar um helper &lt;i&gt;add_task_link&lt;/i&gt; para criar o link que adiciona uma nova tarefa:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# Arquivo: app/views/projects/_form.html.erb
&amp;lt;%= error_messages_for :project %&amp;gt;

&amp;lt;% form_for @project do |f| -%&amp;gt;
  &amp;lt;p&amp;gt;
  Name: &amp;lt;%= f.text_field :name %&amp;gt;
  &amp;lt;/p&amp;gt;
  &amp;lt;div id="tasks"&amp;gt;
    &amp;lt;%= render :partial =&amp;gt; 'task', :collection =&amp;gt; @project.tasks %&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;p&amp;gt;
    &amp;lt;%= add_task_link "Add a task" %&amp;gt;
  &amp;lt;/p&amp;gt;
  &amp;lt;p&amp;gt;
    &amp;lt;%= f.submit "Submit" %&amp;gt;
  &amp;lt;/p&amp;gt;
&amp;lt;% end -%&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Os templates &lt;i&gt;new&lt;/i&gt; e &lt;i&gt;edit&lt;/i&gt; simplesmente renderizam este partial de formulário, de forma que nós temos uma forma consistente para criar e atualizar um projeto. A partial do form vai e renderiza uma partial de tarefa para cada uma das tarefas do projeto. Antes de entrarmos no conteúdo da partial de tarefa, vamos dar uma olhada naquele helper &lt;i&gt;add_task_link&lt;/i&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# Arquivo: app/helpers/projects_helper.rb
def add_task_link(name)
  link_to_function name do |page|
    page.insert_html :bottom, :tasks, :partial =&gt; 'task' , :object =&gt; Task.new
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Quando nós clicamos no link “Add a Task”, nós queremos um novo conjunto de campos de tarefas aparecendo abaixo dos campos de tarefa que já existem no formulário. Ao invés de ocupar o servidor com isto, nós podemos usar JavaScript para adicionar os campos dinamicamente. O método &lt;i&gt;link_to_function&lt;/i&gt; aceita um bloco de código RJS. Geralmente nós associamos código RJS com chamadas assíncronas indo para o servidor. Mas neste caso o código RJS gera JavaScript que é executado no browser imediatamente quando o usuário clica no link. O resultado é que renderizar os campos para adicionar uma nova tarefa não requer uma requisição enviada ao servidor, o que leva a um tempo de resposta mais rápido no uso da aplicação.&lt;/p&gt;

&lt;p&gt;Voltando ao partial do form, nós estamos usando &lt;i&gt;form_for&lt;/i&gt; para dedicar o form para o model &lt;i&gt;@project&lt;/i&gt;. Como então nós vamos adicionar campos para cada uma das tarefas do projeto? A resposta está dentro da partial de tarefa:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# Arquivo: app/views/projects/_task.html.erb
&amp;lt;div class="task"&amp;gt;
&amp;lt;% new_or_existing = task.new_record? ? 'new' : 'existing' %&amp;gt;
&amp;lt;% prefix = "project[#{new_or_existing}_task_attributes][]" %&amp;gt;

&amp;lt;% fields_for prefix, task do |task_form| -%&amp;gt;
  &amp;lt;p&amp;gt;
    Task: &amp;lt;%= task_form.text_field :name %&amp;gt;
    &amp;lt;%= link_to_function "remove" , "$(this).up('.task').remove()" %&amp;gt;
  &amp;lt;/p&amp;gt;
&amp;lt;% end -%&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;O ingrediente chave aqui é o método &lt;i&gt;fields_for&lt;/i&gt;. Ele se comporta de forma muito parecida com form_for mas ele não renderiza a tag HTML &lt;i&gt;form&lt;/i&gt;. Isto nos permite mudar o contexto para um model diferente, no meio do form principal – como se nós estivéssemos embutindo um form dentro de outro.&lt;/p&gt;

&lt;p&gt;O primeiro parâmetro para &lt;i&gt;fields_for&lt;/i&gt; é muito importante. Esta string será usada como um prefixo para cada campo de tarefa. Como vamos usar esta partial também para renderizar tarefas existentes – e nós queremos mantê-las separadas quando o form é enviado – no prefixo nós incluímos uma indicação dizendo se a tarefa é nova ou existente. (O ideal seria criar esta string de prefixo em um helper, mas vamos simplificar um pouco as coisas aqui.)&lt;/p&gt;

&lt;p&gt;O HTML gerado para uma nova tarefa se parece com isto:&lt;/p&gt;

&lt;pre&gt;&lt;code class="html"&gt;
&amp;lt;input name="project[new_task_attributes][][name]" size="30" type="text" /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Se esta fosse uma tarefa existente, o Rails iria colocar automaticamente o ID da tarefa entre as chaves, assim:&lt;/p&gt;

&lt;pre&gt;&lt;code class="html"&gt;
&amp;lt;input name="project[existing_task_attributes][7][name]" size="30" type="text" /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Agora, quando o form é enviado, o Rails irá decodificar o nome do campo de entrada, para forçar uma estrutura no hash &lt;i&gt;params&lt;/i&gt;. As chaves ([]) que estão preenchidas se tornam keys em um hash aninhado. As chaves que estão vazias se tornam um array. Por exemplo, se nós enviarmos o form com duas novas tarefas, o hash &lt;i&gt;params&lt;/i&gt; vai ficar assim:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
"project" =&gt; {
  "name" =&gt; "Yard Work" ,
  "new_task_attributes" =&gt; [
    { "name" =&gt; "rake the leaves" },
    { "name" =&gt; "paint the fence" }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note que os atributos para o projeto e cada tarefa estão aninhados dentro do hash project. Isto é conveniente porque significa que a action &lt;i&gt;create&lt;/i&gt; em nosso controller pode simplesmente passar todos os atributos de projeto ao model &lt;i&gt;Project&lt;/i&gt; sem se preocupar sobre o que está dentro do hash project:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# Arquivo: app/controllers/projects_controller.rb
def create
  @project = Project.new(params[:project])
  if @project.save
    flash[:notice] = "Successfully created project and tasks."
    redirect_to projects_path
  else
    render :action =&gt; 'new'
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Este código se parece com uma action &lt;i&gt;create&lt;/i&gt; padrão, para um form de um único model. Mas existe algo sútil acontecendo aqui. Quando chamamos &lt;i&gt;Project.new(params[:project])&lt;/i&gt;, o Active Record assume que nosso model &lt;i&gt;Project&lt;/i&gt; tem um atributo correspondente chamado &lt;i&gt;new_task_attributes&lt;/i&gt; porque ele procura uma key chamada &lt;i&gt;new_task_attributes&lt;/i&gt; dentro do hash &lt;i&gt;params[:project]&lt;/i&gt;. Isto é, o Active Record tentará fazer uma atribuição em massa (mass assign) de todos os dados contidos neste hash, para os atributos correspondentes no model &lt;i&gt;Project&lt;/i&gt;. Mas nós não temos um atributo &lt;i&gt;new_task_attributes&lt;/i&gt; em nosso model &lt;i&gt;Project&lt;/i&gt;.&lt;/p&gt;

&lt;p&gt;Um jeito conveniente de manter tudo isto transparente, da ponto de vista do controller, é usar um atributo virtual. Para fazer isso, nós simplesmente criamos um método &lt;i&gt;setter&lt;/i&gt; em nosso model &lt;i&gt;Project&lt;/i&gt;, chamado &lt;i&gt;new_task_attributes=&lt;/i&gt;, que recebe um array e constrói a tarefa para cada elemento:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# Arquivo: app/models/project.rb
def new_task_attributes=(task_attributes)
  task_attributes.each do |attributes|
    tasks.build(attributes)
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Pode parecer que estas tarefas não estão sendo salvas em lugar nenhum. De fato, o Rails vai fazer isso automaticamente quando o projeto é salvo, porque ambos o projeto e suas tarefas associadas, são novos registros.&lt;/p&gt;

&lt;p&gt;E isso é tudo que precisamos para criar um projeto. Vamos ver agora como atualizá-lo.&lt;/p&gt;

&lt;p&gt;Assim como antes, nós precisamos de uma forma de adicionar e remover tarefas dinamicamente, mas desta vez se uma tarefa já existe, ela deve ser atualizada. As actions do controller só precisam se preocupar sobre o projeto, então elas são bem convencionais. Como antes, a atualização de tarefas será tratada no model &lt;i&gt;Project&lt;/i&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# Arquivo: app/controllers/projects_controller.rb
def edit
  @project = Project.find(params[:id])
end

def update
  params[:project][:existing_task_attributes] ||= {}

  @project = Project.find(params[:id])
  if @project.update_attributes(params[:project])
    flash[:notice] = "Successfully updated project and tasks."
    redirect_to project_path(@project)
  else
    render :action =&gt; 'edit'
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Um detalhe importante: a primera linha da action update seta o parâmetro &lt;i&gt;existing_task_attributes&lt;/i&gt; para um hash vazio, se ele já não está setado. Sem esta linha, não teria como deletar a última tarefa de um projeto. Se não existem campos de tarefa no form (porque nós removemos todos eles com JavaScript), então &lt;i&gt;existing_task_attributes()&lt;/i&gt; não será setado pelo form, o que significa que o nosso método &lt;i&gt;Project#existing_task_attributes=&lt;/i&gt; não será invocado. Setando um hash vazio aqui, se &lt;i&gt;existing_task_attributes()&lt;/i&gt; está vazio, garante que o método &lt;i&gt;Project#existing_task_attributes=&lt;/i&gt; é chamado ao deletar a última tarefa.&lt;/p&gt;

&lt;p&gt;A partial de form não precisa de alterações. No entanto, quando nós submetemos o form com tarefas existentes, o hash &lt;i&gt;params[:project]&lt;/i&gt; irá incluir uma key chamada &lt;i&gt;existing_task_attributes&lt;/i&gt;. Isto é, quando nós atualizamos o projeto, os parâmetros do POST irão se parecer com isto:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
"project" =&gt; {
  "name" =&gt; "Yard Work" ,
  "existing_task_attributes" =&gt; [
    {
      "1" =&gt; {"name" =&gt; "rake the leaves" },
      "2" =&gt; {"name" =&gt; "paint the fence" },
    }
  ]
  "new_task_attributes" =&gt; [
    { "name" =&gt; "clean the gutters" }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Para tratar isto, nós precisamos adicionar um método &lt;i&gt;existing_task_attributes=&lt;/i&gt; ao nosso model &lt;i&gt;Project&lt;/i&gt;, que irá receber cada tarefa existente e aí vai: ou atualizar a tarefa ou deletá-la, dependendo se os atributos são passados:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# Arquivo: app/models/project.rb
after_update :save_tasks

def existing_task_attributes=(task_attributes)
  tasks.reject(&amp;:new_record?).each do |task|
    attributes = task_attributes[task.id.to_s]
    if attributes
      task.attributes = attributes
    else
      tasks.delete(task)
    end
  end
end

def save_tasks
  tasks.each do |task|
    task.save(false)
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note que nós estamos salvando as tarefas em um callback chamado &lt;i&gt;after_update&lt;/i&gt;. Isto é importante porque, diferente de antes, as tarefas existentes não serão automaticamente salvas quando o projeto for atualizado. E já que os callbacks são encapsulados em uma transação, se algum problema inesperado acontecer será feito um roll back.&lt;/p&gt;

&lt;p&gt;Ao passar &lt;i&gt;false&lt;/i&gt; para o método &lt;i&gt;task.save&lt;/i&gt;, os dados são salvos sem passar pela validação. Ao invés disso, para garantir que todas as tarefas sejam validadas quando o projeto é validado, nós simplesmente adicionamos esta linha ao model &lt;i&gt;Project&lt;/i&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
validates_associated :tasks
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Isto vai garantir que tudo é valido antes de salvar. E se a validação falha, então o uso de &lt;i&gt;error_messages_for :project&lt;/i&gt; no template de formulário inclui os erros de validação para o projeto e qualquer uma de suas tarefas.&lt;/p&gt;

&lt;p&gt;Então agora nós podemos criar e editar projetos e suas tarefas em uma tacada só. E ao usar atributos virtuais, nós mantemos o código do controller felizmente ignorante que nós estamos tratando vários models a partir de um único formulário.&lt;/p&gt;

&lt;h2&gt;Discussão&lt;/h2&gt;

&lt;p&gt;Uma vez que você começa a colocar mais de um model em um único formulário, você provavelmente vai querer criar um helper customizado para mensagens de erro, para fazer coisas como ignorar certos erros e detalhar outros. Veja a receita 17 "Customize as Mensagens de Erro", na página 91 para saber como escrever um método &lt;i&gt;error_messages_for&lt;/i&gt; customizado. (Nota do tradutor: capítulo disponível no livro &lt;a href="http://pragprog.com/titles/fr_arr/advanced-rails-recipes"&gt;Advanced Rails Recipes&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Campos de data causam alguns problemas porque, por algum motivo, o Rails remove as chaves [] do nome do campo. Isto pode ser arrumado especificando manualmente a opção &lt;i&gt;:index&lt;/i&gt; e setá-lo para uma string vazia se a tarefa é nova:

&lt;pre&gt;&lt;code class="ruby"&gt;
&amp;lt;%= task_form.date_select :completed_at,
:index =&amp;gt; (task.new_record? ? '' : nil) %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Infelizmente, campos do tipo checkbox não vão funcionar com esta receita porque o valor destes campos não é passado pelo browser quando o checkbox é desmarcado. Portanto, você não tem como saber a qual tarefa um checkbox pertence quando estiver criando um novo projeto. Para resolver este problema, você pode usar um menu select para campos booleanos:

&lt;pre&gt;&lt;code class="ruby"&gt;
&amp;lt;%= task_form.select :completed, [['No' , false], ['Yes' , true]] %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Copyright (c) 2008 The Pragmatic Programmers, LLC&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/LevyOnRails/~4/mFdGSnuEqnE" height="1" width="1"/&gt;</content>
    <author>
      <name>Levy Carneiro Jr.</name>
    </author>
  <feedburner:origLink>http://www.levyonrails.com/posts/14-tratando-m-ltiplos-models-em-um-nico-form</feedburner:origLink></entry>
  <entry>
    <id>tag:www.levyonrails.com,2005:Post/13</id>
    <published>2009-01-06T19:04:01Z</published>
    <updated>2009-01-06T19:04:15Z</updated>
    <link type="text/html" rel="alternate" href="http://feedproxy.google.com/~r/LevyOnRails/~3/Ew3Y_7f1jGQ/13-asciicasts-or-railscasts-made-text" />
    <title>ASCIIcasts or RailsCasts made text</title>
    <content type="html">&lt;p&gt;Imagine you are doing something in Rails, and you need to remember or even learn how to it.&lt;/p&gt;

&lt;p&gt;Maybe you, like me, will try to look at the Railscasts videos. But... searching something that Ryan Bates talked about during the video is not so easy to find. Or maybe you can't watch a video at all, right now.&lt;/p&gt;

&lt;p&gt;Here's a solution. Eifion Bedford is creating text versions of the well-know screencasts at &lt;a href="http://railscasts.com/"&gt;RailsCasts&lt;/a&gt; and posting at this new site called &lt;a href="http://asciicasts.com/"&gt;ASCIIcasts&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Great find.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/LevyOnRails/~4/Ew3Y_7f1jGQ" height="1" width="1"/&gt;</content>
    <author>
      <name>Levy Carneiro Jr.</name>
    </author>
  <feedburner:origLink>http://www.levyonrails.com/posts/13-asciicasts-or-railscasts-made-text</feedburner:origLink></entry>
  <entry>
    <id>tag:www.levyonrails.com,2005:Post/12</id>
    <published>2008-12-19T11:34:36Z</published>
    <updated>2009-05-03T21:58:08Z</updated>
    <link type="text/html" rel="alternate" href="http://feedproxy.google.com/~r/LevyOnRails/~3/TLdnGmtGp4w/12-scaling-microblogging-services-such-as-twitter" />
    <title>Scaling microblogging services such as Twitter</title>
    <content type="html">&lt;p&gt;There's a joke in the Ruby and Rails world that says 'Rails doesn't scale', which it's just a joke to really say: what is scallable is the way you create your app, and that does not depend whether is written in Rails, Perl or even &lt;a href="http://www.yolinux.com/TUTORIALS/LinuxTutorialCgiShellScript.html"&gt;Bash&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So it's important to know what matters in terms of building a scallable web app. As you know:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Scalability&lt;/b&gt;: ability to either handle growing amounts of work in a graceful manner, or to be readily enlarged.&lt;/p&gt;

&lt;p&gt;And how do you accomplish that in Ruby/Rails/whatever app you're writing?&lt;/p&gt;

&lt;p&gt;Well, one way to gain further knowledge on the subject is by reading this article. The author explains what is envolved when you need to scale a microblogging service such as Twitter. The author created Nouncer (a developer platform for building microblogs and similar services) and ended up learning quite a lot about the inner-workings and challenges of such an application.&lt;/p&gt;

&lt;p&gt;Please do read it, it's a series of 3 articles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.hueniverse.com/hueniverse/2008/03/on-scaling-a-mi.html"&gt;Scaling a Microblogging Service - Part I&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.hueniverse.com/hueniverse/2008/03/scaling-a-micro.html"&gt;Scaling a Microblogging Service - Part II&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.hueniverse.com/hueniverse/2008/04/scaling-a-micro.html"&gt;Scaling a Microblogging Service - Part III&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My thoughts? Scalling is not a solved subject, and it depends on the expertise of the developer/architect on finding ways to identify the fine grained causes for bottlenecks and to deal with them in a rather creative way, cycling between endless monitoring and improvements down the road.&lt;/p&gt;

&lt;p&gt;Fun, isn't? :)&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/LevyOnRails/~4/TLdnGmtGp4w" height="1" width="1"/&gt;</content>
    <author>
      <name>Levy Carneiro Jr.</name>
    </author>
  <feedburner:origLink>http://www.levyonrails.com/posts/12-scaling-microblogging-services-such-as-twitter</feedburner:origLink></entry>
  <entry>
    <id>tag:www.levyonrails.com,2005:Post/11</id>
    <published>2008-12-06T14:11:30Z</published>
    <updated>2009-01-08T12:07:45Z</updated>
    <link type="text/html" rel="alternate" href="http://feedproxy.google.com/~r/LevyOnRails/~3/hAE_hi1J3is/11-new-merb-course-on-rubylearning-com" />
    <title>New Merb course on RubyLearning.com</title>
    <content type="html">&lt;p&gt;RubyLearning.com, the online Ruby programming courses, now offers a introductory course on Merb! The fee is only US$ 6.00 for the first 25 participants, US$ 8 till December 31st, and US$ 10 from January 1st on.&lt;/p&gt;

&lt;p&gt;The course starts on 10th Jan. 2009 and runs for 2 weeks. You first need to register on the site and then enroll into the course. On registration, you can download the “Introduction to Merb” eBook.&lt;/p&gt;

&lt;h2&gt;What Will I Learn?&lt;/h2&gt;

&lt;p&gt;The course topics, as suggested by &lt;span style="background-color: #FFFFCC;"&gt;&lt;a href="http://www.linkedin.com/in/mattaimonetti"&gt;Matt Aimonetti&lt;/a&gt;&lt;/span&gt; are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Installation: Merb Installation, SQLite Installation, 
Installing database driver allowing DataMapper to connect to SQLite, Mongrel Installation&lt;/li&gt;
  &lt;li&gt;Interactive Merb&lt;/li&gt;
  &lt;li&gt;Router&lt;/li&gt;
  &lt;li&gt;Using Erubis&lt;/li&gt;
  &lt;li&gt;Developing a simple app: Callable tasks, Generating a Controller, Generating a Model, Setting Relationships, Helpers, CRUD, Partials, Exercises&lt;/li&gt;
  &lt;li&gt;merb-auth&lt;/li&gt;
  &lt;li&gt;A Mini-project&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read the full &lt;a href="http://rubylearning.com/blog/2008/12/06/introduction-to-merb-a-new-course/"&gt;post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For other courses on RubyLearning, check the &lt;a href="http://rubylearning.org/class/index.php"&gt;full list&lt;/a&gt;.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/LevyOnRails/~4/hAE_hi1J3is" height="1" width="1"/&gt;</content>
    <author>
      <name>Levy Carneiro Jr.</name>
    </author>
  <feedburner:origLink>http://www.levyonrails.com/posts/11-new-merb-course-on-rubylearning-com</feedburner:origLink></entry>
  <entry>
    <id>tag:www.levyonrails.com,2005:Post/10</id>
    <published>2008-12-04T12:52:45Z</published>
    <updated>2008-12-04T13:00:41Z</updated>
    <link type="text/html" rel="alternate" href="http://feedproxy.google.com/~r/LevyOnRails/~3/R-9344xrlnI/10-rails-templates" />
    <title>Rails Templates</title>
    <content type="html">&lt;p&gt;Let's say you want to create a new Rails app. Every time you run "rails my_app" you usually also do some other steps such as:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
# You need to remove the index.html for your app to work:
rm public/index.html

# Maybe you also create some basic Models everytime:
./script/generate scaffold person name:string

# Adding a route to the homepage
# route "map.root :controller =&gt; :person"

# Migrating the database
rake db:migrate

# The first commit in Git
git init
git add .
git commit -a -m 'Initial commit'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This problem's gone. Edge Rails now supports a solution  using "Templates". Running a command like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
rails blog -m ~/template.rb
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You're passing parameters to the 'rails' command, telling everything it needs to be done after the creation of the app directory. Things like installing plugins, removing files, putting some default css and image files in /public, the works! So, inside the template.rb file you'd put something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# template.rb
run "rm public/index.html"
generate(:scaffold, "person name:string")
route "map.root :controller =&gt; :person"
rake("db:migrate")

git :init
git :add =&gt; "."
git :commit =&gt; "-a -m 'Initial commit'"
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Cool, isn't? :)&lt;/p&gt;

&lt;p&gt;Better yet, you can use an URL to the rails command, so from any machine you're using you'll always have the initialization commands at your disposal. How great is that? :)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
rails blog -m http://gist.github.com/31208.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For more information on Rails Templates check &lt;a href="http://m.onkey.org/2008/12/4/rails-templates"&gt;here&lt;/a&gt; and &lt;a href="http://omgbloglol.com/rejoice-rg-is-now-part-of-rail"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/LevyOnRails/~4/R-9344xrlnI" height="1" width="1"/&gt;</content>
    <author>
      <name>Levy Carneiro Jr.</name>
    </author>
  <feedburner:origLink>http://www.levyonrails.com/posts/10-rails-templates</feedburner:origLink></entry>
  <entry>
    <id>tag:www.levyonrails.com,2005:Post/9</id>
    <published>2008-11-29T21:22:03Z</published>
    <updated>2008-12-01T10:30:13Z</updated>
    <link type="text/html" rel="alternate" href="http://feedproxy.google.com/~r/LevyOnRails/~3/HU4va7TiH8I/9-automatic-file-type-detection-for-rspec-and-rails-in-textmate" />
    <title>Automatic file type detection for Rspec and Rails in Textmate</title>
    <content type="html">&lt;p&gt;If your TextMate is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;using the Ruby Bundle for files that are Ruby on Rails;&lt;/li&gt;
&lt;li&gt;using the Ruby on Rails Bundle for files that are Rspec;&lt;/li&gt;
&lt;li&gt;any other wrong association.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are some ways to fix. I followed these steps to fix it:&lt;/p&gt;

&lt;p&gt;1. Remove the manual associations. When you use the popup bar at the status bar, in Textmate, you may not know but you are associating files to Bundles, manually, which is bad. To fix it, let's first read what's already in there. Run this command in the Terminal:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
defaults read com.macromates.textmate OakLanguageFileBindings
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Check the manual associations you've made so far. And remove them all with:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
defaults delete com.macromates.textmate OakLanguageFileBindings
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;2. Specify inside a Bundle, which files it should be used for. Open Bundles → Bundle Editor → Edit Languages… and locate the &lt;b&gt;Ruby&lt;/b&gt; Grammar. Inside this text area, locate a line that looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
fileTypes = ( 'rb', 'rbx', 'rjs', 'Rakefile', 'rake',
  'cgi', 'fcgi', 'gemspec', 'irbrc', 'capfile' );
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Remove the rb extension. And add it to the Ruby on Rails grammar instead. At the end my lines became like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# my Ruby Language grammar
fileTypes = ( 'rbx', 'rjs', 'Rakefile', 'rake', 
  'cgi', 'fcgi', 'gemspec', 'irbrc', 'capfile' );

# my Ruby on Rails Language grammar
fileTypes = ( 'rb', 'rxml', 'builder' );
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As you see, the rb extension now belongs to the Rails Language Grammar.&lt;/p&gt;

&lt;p&gt;Now whenever I open a *.rb file, the Bundle is Ruby on Rails. Whenever I open a *_spec.rb file, the Bundle is RSpec. You can always improve on that idea, and do what you think it's best for you. For example, you can edit Ruby on Rails grammar for .erb files, .rjs, and the like.&lt;/p&gt;

&lt;p&gt;Further information in the TextMate Blog's post &lt;a href="http://blog.macromates.com/2007/file-type-detection-rspec-rails/"&gt;File Type Detection (RSpec &amp; Rails)&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/LevyOnRails/~4/HU4va7TiH8I" height="1" width="1"/&gt;</content>
    <author>
      <name>Levy Carneiro Jr.</name>
    </author>
  <feedburner:origLink>http://www.levyonrails.com/posts/9-automatic-file-type-detection-for-rspec-and-rails-in-textmate</feedburner:origLink></entry>
  <entry>
    <id>tag:www.levyonrails.com,2005:Post/8</id>
    <published>2008-11-28T10:41:08Z</published>
    <updated>2008-11-28T10:41:08Z</updated>
    <link type="text/html" rel="alternate" href="http://feedproxy.google.com/~r/LevyOnRails/~3/81OPGvTpmk8/8-what-to-do-when-github-goes-down" />
    <title>What to do when GitHub goes down</title>
    <content type="html">&lt;p&gt;What if my GitHub repository is corrupted or deleted?&lt;/p&gt;

&lt;p&gt;Don’t Panic! Because of the distributed nature of git, everyone always has a local full copy of the repository, complete with history. Any of your repositories, assuming they have been kept up to date, can be uploaded to the GitHub repository with no loss of data.&lt;/p&gt;

&lt;p&gt;Read the &lt;a href="http://ozmm.org/posts/when_github_goes_down.html"&gt;full article&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/LevyOnRails/~4/81OPGvTpmk8" height="1" width="1"/&gt;</content>
    <author>
      <name>Levy Carneiro Jr.</name>
    </author>
  <feedburner:origLink>http://www.levyonrails.com/posts/8-what-to-do-when-github-goes-down</feedburner:origLink></entry>
  <entry>
    <id>tag:www.levyonrails.com,2005:Post/7</id>
    <published>2008-11-27T11:20:17Z</published>
    <updated>2008-11-27T11:20:17Z</updated>
    <link type="text/html" rel="alternate" href="http://feedproxy.google.com/~r/LevyOnRails/~3/Lj6zgs4PCWc/7-new-official-15-minute-video-for-rails-2-2" />
    <title>New official 15-minute video for Rails 2.2</title>
    <content type="html">&lt;p&gt;Finally, an update to the famous video on creating a blog with Rails in 15 minutes. The old version was made back in 2005!&lt;/p&gt;

&lt;p&gt;New official 15-minute blog &lt;a href="http://rubyonrails.org/screencasts"&gt;video for Rails 2.2&lt;/a&gt; by Ryan Bates.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/LevyOnRails/~4/Lj6zgs4PCWc" height="1" width="1"/&gt;</content>
    <author>
      <name>Levy Carneiro Jr.</name>
    </author>
  <feedburner:origLink>http://www.levyonrails.com/posts/7-new-official-15-minute-video-for-rails-2-2</feedburner:origLink></entry>
  <entry>
    <id>tag:www.levyonrails.com,2005:Post/6</id>
    <published>2008-11-26T16:16:36Z</published>
    <updated>2008-11-27T10:14:07Z</updated>
    <link type="text/html" rel="alternate" href="http://feedproxy.google.com/~r/LevyOnRails/~3/Ugfc5kU1hzE/6-the-do-to-read-ratio" />
    <title>The Do-to-Read Ratio</title>
    <content type="html">&lt;p&gt;How much time do you spend reading about Ruby and Rails, instead of actually doing something? Wich is coding, by the way :)&lt;/p&gt;

&lt;p&gt;If I read/watch/listen_to material on Rails during three hours, and I only code for one hour, I think I'm not being productive in my path to be a great Web developer. Anyway, 1/3 of my learning time is being spent on non-coding things.&lt;/p&gt;

&lt;p&gt;I realized my time is much more productive if I follow some basic rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reading RSS once a week: it's very easy to become so fascinated about the new stuff coming every day on the Ruby on Rails world. Not reading RSS everyday gives me 2 benefits: I don't get overwhelmed and frustrated about what I don't know yet (what is not a great motivator), and I save time to actually code;&lt;/li&gt;
&lt;li&gt;Sticking to a subject: I'm now studying RSpec and BDD. I'm studying the necessary to be comfortable at the subject;&lt;/li&gt;
&lt;li&gt;Studying in layers: after some rounds of subjecs I studied, I may get back to subjects I need to gain a deeper understanding. Like, at first I may study a little on BDD/RSpec and sometime later I'll catch up on more advanced topics.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And also, while reading or watching a screencast you can always code along with the material pausing and resuming all the time (which is good, because for me it counts as coding).&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/LevyOnRails/~4/Ugfc5kU1hzE" height="1" width="1"/&gt;</content>
    <author>
      <name>Levy Carneiro Jr.</name>
    </author>
  <feedburner:origLink>http://www.levyonrails.com/posts/6-the-do-to-read-ratio</feedburner:origLink></entry>
  <entry>
    <id>tag:www.levyonrails.com,2005:Post/5</id>
    <published>2008-11-21T22:37:24Z</published>
    <updated>2008-11-23T22:26:59Z</updated>
    <link type="text/html" rel="alternate" href="http://feedproxy.google.com/~r/LevyOnRails/~3/XxZVBsDOwmU/5-how-to-love-tests" />
    <title>How To Love Tests</title>
    <content type="html">&lt;p&gt;On this presentation "How I Learned to Love Testing", Gregg Polack talks about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why would you test your code?&lt;/li&gt;
&lt;li&gt;When do you test your code?&lt;/li&gt;
&lt;li&gt;The path to developer enlightenment&lt;/li&gt;
&lt;li&gt;Test Driven Development (TDD)&lt;/li&gt;
&lt;li&gt;Behavior Driven Development (BDD)&lt;/li&gt;
&lt;li&gt;Where'd RSpec come from?&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;

&lt;object width="500" height="333"&gt;&lt;param name="allowfullscreen" value="true" /&gt;&lt;param name="allowscriptaccess" value="always" /&gt;&lt;param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=2305392&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=ff9933&amp;amp;fullscreen=1" /&gt;&lt;embed src="http://vimeo.com/moogaloop.swf?clip_id=2305392&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=ff9933&amp;amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="500" height="333"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;

&lt;p&gt;The original post &lt;a href="http://www.railsenvy.com/2007/10/4/how-i-learned-to-love-testing-presentation"&gt;here&lt;/a&gt;, and the link to download the &lt;a href="http://www.patchedsoftware.com/RailsEnvy-LoveTests.mov"&gt;entire presentation with better quality than Vimeo's&lt;/a&gt;.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/LevyOnRails/~4/XxZVBsDOwmU" height="1" width="1"/&gt;</content>
    <author>
      <name>Levy Carneiro Jr.</name>
    </author>
  <feedburner:origLink>http://www.levyonrails.com/posts/5-how-to-love-tests</feedburner:origLink></entry>
  <entry>
    <id>tag:www.levyonrails.com,2005:Post/4</id>
    <published>2008-11-14T18:24:24Z</published>
    <updated>2008-11-14T18:24:24Z</updated>
    <link type="text/html" rel="alternate" href="http://feedproxy.google.com/~r/LevyOnRails/~3/5DkzWTD-hc4/4-the-number-one-secret-of-the-great-blogs" />
    <title>The number one secret of the great blogs</title>
    <content type="html">&lt;p&gt;Being a Web Developer myself, I keep finding myself thinking of new ideas of web 2.0 sites to build. And now being a Railer, it seems it gives much more power to actually build a killer web app :)&lt;/p&gt;

&lt;p&gt;This guy, Seth Godin, is a well-known Marketing professional and speaker. He really captures the essence in what the costumer wants in a product or service.&lt;/p&gt;

&lt;p&gt;The things you learn when you have a blog, or at least when you try to build a great blog on a certain subject, are probably the same things you'll use when creating a web 2.0 application. That leads to this very interesting article I found on Seth's blog, which I re-post here.&lt;/p&gt;

&lt;p&gt;That makes a lot of sense. After you read that book you love, where can you go to get more of that insight? The author's blog. Like, once when I read "Freakonomics" I went straight to the author's blog. I knew I could go there to keep update on the stuff he mentions in the actual book.&lt;/p&gt;

&lt;p&gt;37signals is leading a tribe through their &lt;a href="http://www.37signals.com/svn/"&gt;blog&lt;/a&gt;. In Brazi &lt;a href="http://www.akitaonrails.com"&gt;Fabio Akita&lt;/a&gt; and &lt;a href="http://www.nomedojogo.com"&gt;Carlos Brando&lt;/a&gt; for instance, are leading a tribe of passionate Rails developers.&lt;/p&gt;

&lt;p&gt;What tribe are you willing to lead? :)&lt;/p&gt;

&lt;p&gt;Without further ado, here's the article.&lt;/p&gt;

&lt;h2&gt;The number one secret of the great blogs&lt;/h2&gt;
&lt;quote&gt;&lt;a href="http://sethgodin.typepad.com/seths_blog/2008/11/the-number-one.html"&gt;by Seth Godin&lt;/a&gt;&lt;/quote&gt;

&lt;p&gt;Every one of them leads a &lt;a href="http://www.squidoo.com/tribesbook"&gt;tribe.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.boingboing.net"&gt;Boingboing&lt;/a&gt; readers recognize each other at conferences. We use the same shorthand, we recognize the same memes. &lt;a href="http://www.huffingtonpost.com"&gt;Huffingtonpost&lt;/a&gt; editors don't try to reach everyone. Instead, they are hosting a digital cocktail party for invited guests that have something in common. &lt;a href="http://www.presentationzen.com"&gt;Garr Reynolds&lt;/a&gt; doesn't try to teach everyone about Powerpoint... instead, he leads a tribe of people committed to changing the way the world communicates in meetings.&lt;/p&gt;

&lt;p&gt;Go down the list. &lt;a href="http://www.gapingvoid.com"&gt;Hugh&lt;/a&gt; leads a tribe.&lt;a href="http://www.talkingpointsmemo.com/"&gt; &lt;span style="text-decoration: underline;"&gt;Josh&lt;/span&gt;&lt;/a&gt;&lt;a href="http://www.jaffejuice.com"&gt;&amp;nbsp;&lt;/a&gt; leads a tribe. So does &lt;a href="http://www.twistimage.com/blog/"&gt;Mitch.&lt;/a&gt; And &lt;a href="http://www.amazon.com/Reality-Check-Outsmarting-Outmanaging-Outmarketing/dp/1591842239/ref=sr_1_2?ie=UTF8&amp;amp;s=books&amp;amp;qid=1226579258&amp;amp;sr=1-2"&gt;Guy,&lt;/a&gt; who just wrote a book for his tribe too. It's not hard to &lt;a href="http://www.flowerdust.net/"&gt;find&lt;/a&gt; other &lt;a href="http://www.startupnation.com/"&gt;examples&lt;/a&gt; for my thesis.&lt;/p&gt;

&lt;p&gt;In each case, the function of the blog is to be a standard bearer, the north star that tribe members can point to as a place to meet or for ideas to circle around. The blog isn't about the writer, it's about the readers.&lt;/p&gt;

&lt;p&gt;The key takeaway is this: once you realize that your job is to find and connect and lead a tribe, to give them something to talk about and a place to go, it's a lot easier to write a blog that works.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/LevyOnRails/~4/5DkzWTD-hc4" height="1" width="1"/&gt;</content>
    <author>
      <name>Levy Carneiro Jr.</name>
    </author>
  <feedburner:origLink>http://www.levyonrails.com/posts/4-the-number-one-secret-of-the-great-blogs</feedburner:origLink></entry>
  <entry>
    <id>tag:www.levyonrails.com,2005:Post/3</id>
    <published>2008-11-05T14:11:02Z</published>
    <updated>2008-11-05T14:12:46Z</updated>
    <link type="text/html" rel="alternate" href="http://feedproxy.google.com/~r/LevyOnRails/~3/SRHIog4Lepo/3-como-adicionar-suporte-a-feeds" />
    <title>Como adicionar suporte a feeds</title>
    <content type="html">&lt;p&gt;Imaginei que adicionar suporte a feeds em uma aplicação Rails fosse complicado. Mas uma vez "tomei na cabeça" vendo que o Rails realmente é produtivo de se trabalhar :)&lt;/p&gt;

&lt;p&gt;&lt;b&gt;1. Método de consulta que retorna todos os posts&lt;/b&gt;. Para criar uma URL de feed para o seu blog, antes de tudo você precisa criar um método que faça uma query que liste todos os posts do blog. Seguindo a filosofia "fat model / skinny controller" este método deve ficar dentro do próprio model "Post". Vamos criar um método chamado "all_posts".&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# app/models/post.rb
class Post &lt; ActiveRecord::Base
  has_many :comments

  def self.all_posts
    find(:all, :order =&gt; "created_at DESC")
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;2. Criando uma action para feeds&lt;/b&gt;. Agora vamos adicionar uma action chamada "feed" dentro do controller "posts'. Repare que aqui já estamos usando o método "all_posts" criado no passo anterior.&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# app/controllers/posts_controller.rb
class PostsController &lt; ApplicationController
  def feed
    @posts = Post.all_posts

    respond_to do |format|
      format.atom
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;3. Adicionando uma rota&lt;/b&gt;. Do jeito que está, não existe como acessar a URL http//www.myblog.com.br/feed, porque ainda não temos uma rota para esta URL. Precisamos adicionar esta rota no arquivo config/routes.rb. Note a última linha do arquivo.&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# config/routes.rb
  map.root :controller =&gt; 'posts'
  map.resources :posts, :has_many =&gt; :comments
  map.resources :sessions
  map.feed 'feed', :controller =&gt; 'posts', :action =&gt; 'feed'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;4. Adicionando um template para o feed.&lt;/b&gt;. Ok, agora o Rails já sabe que existe uma URL /feed em nosso blog. Mas ele não sabe o que renderizar ali, na action "feed". Ele só sabe que possui um objeto @posts disponível. Vamos dizer ao Rails como ele deve formatar esse retorno. O exemplo abaixo foi retirado da própria documentação do Rails, do Helper &lt;a href="http://api.rubyonrails.com/classes/ActionView/Helpers/AtomFeedHelper.html#M001208"&gt;AtomFeedHelper&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# app/views/posts/feed.atom.builder
atom_feed(:language =&gt; "pt-BR") do |feed|
  feed.title(h "My blog")
  feed.updated((@posts.first.created_at))

  for post in @posts
    feed.entry(post) do |entry|
      entry.title(post.title)
      entry.content(post.body, :type =&gt; 'html')

      entry.author do |author|
        author.name(h "João da Esquina")
      end
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Você pode testar essa URL em seu browser. Mas provavelmente é melhor testar com o comando curl e ver o resultado completo:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
curl --get http://www.myblog.com.br/feed
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;5. Feed no &amp;lt;HEAD&amp;gt; do site&lt;/b&gt;. Pronto, já temos um feed funcionando. Agora precisamos colocar isto em nosso HTML, para dizer ao mundo que nosso blog já tem suporte a feeds :) A melhor forma é usar o helper auto_discovery_link_tag do Rails:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# app/views/layouts/application.html.erb
&amp;lt;head&amp;gt;
  &lt;%= auto_discovery_link_tag(:atom, :controller =&gt; 'posts', :action =&gt; 'feed') %&gt;
&amp;lt;/head&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Agora nosso blog informa aos leitores de feeds, que nossa URL oficial é o /feed que criamos até agora. Mas se você como eu, prefere usar o FeedBurner para isso, ao invés disso faça assim:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# app/views/layouts/application.html.erb
&amp;lt;head&amp;gt;
 &lt;%= auto_discovery_link_tag(:atom, 'http://feeds.feedburner.com/LevyOnRails', :title =&gt; "My blog's feed") %&gt;
&amp;lt;/head&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ok. Agora se você informar a url de seu blog, por exemplo, http://www.myblog.com.br/ (sem o /feed) no Google Reader ou outro leitor de feeds experto, ele vai usar o feed do FeedBurner, no meu caso a URL http://feeds.feedburner.com/LevyOnRails. Perfeito!&lt;/p&gt;

&lt;p&gt;Mas e se alguém usar a url http://www.myblog.com.br/feed, desconsiderando o que está na tag auto_discovery_link_tag acima? Para isso precisamos adicionar um redirect para o feed.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;6. Redirect para o feed&lt;/b&gt;. Vamos criar um redirect, de forma que somente o FeedBurner consiga ler a nossa URL /feed. O restante do mundo será redirecionada para a URL do http://feeds.feedburner.com/LevyOnRails. Qual a vantagem disso? Você não terá metade de seus leitores usando o FeedBurner e outra metade usando o feed direto de teu site. Assim você consegue medir 100% a leitura/visitação de seu feed, usando as facilidades disponíveis no site do FeedBurner. Vamos precisar alterar o nosso controller:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# app/controllers/posts_controller.rb
class PostsController &lt; ApplicationController
  def feed
    redirect_to 'http://feeds.feedburner.com/LevyOnRails', :status=&gt;307 and return unless request.env['HTTP_USER_AGENT'].match(/feedburner|feedvalidator/i)

    @posts = Post.all_posts

    respond_to do |format|
      format.atom
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Com isso verificamos a variável do servidor HTTP_USER_AGENT, se esta contém a string "feedburner" ou "feedvalidator". Se tiver, nós acreditamos que trata-se do FeedBurner, e somente este agent pode acessar nossa URL feed real.&lt;/p&gt;

&lt;p&gt;E isso é tudo. Simples, não? :)&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/LevyOnRails/~4/SRHIog4Lepo" height="1" width="1"/&gt;</content>
    <author>
      <name>Levy Carneiro Jr.</name>
    </author>
  <feedburner:origLink>http://www.levyonrails.com/posts/3-como-adicionar-suporte-a-feeds</feedburner:origLink></entry>
  <entry>
    <id>tag:www.levyonrails.com,2005:Post/2</id>
    <published>2008-11-01T14:52:51Z</published>
    <updated>2008-11-02T23:30:08Z</updated>
    <link type="text/html" rel="alternate" href="http://feedproxy.google.com/~r/LevyOnRails/~3/-aI2JrL-WHI/2-processo-de-cria-o-de-um-blog-em-rails-parte-1" />
    <title>Processo de criação de um blog em Rails - Parte 1</title>
    <content type="html">&lt;p&gt;Esse título poderia ser: "por que não dá para fazer um blog em 15 minutos". Tudo bem, David Hanson consegue, afinal ele é o cara :)&lt;/p&gt;

&lt;p&gt;Estou falando do famoso vídeo de uma &lt;a href="http://media.rubyonrails.org/video/rails_take2_with_sound.mov"&gt;criação de um blog em 15 minutos&lt;/a&gt;, feito pelo próprio criador do framework Ruby on Rails, David H. Hanson. Se você não viu ainda, veja agora! É interessante ver o quanto um vídeo pode fazer para propagar um produto ou idéia, e para empolgar as pessoas. Muitas pessoas que começam a mexer com Rails dizem “eu vi aquele vídeo de 15 minutos, e fiquei impressionado” (myself included!). Desde a criação deste vídeo em 2005, o Rails já evoluiu muito e hoje o próprio DHH diz que já é possível fazer a mesma coisa em 3 minutos. Para um vídeo mais atualizado veja o screencast do Akita, sobre &lt;a href="http://www.akitaonrails.com/2007/12/10/the-first-rails-2-0-screencast-english"&gt;criação de um blog em Rails 2.x (disponível em inglês e português)&lt;/a&gt;.&lt;/p&gt;
 
&lt;p&gt;Voltando ao assunto, criar um blog em 15 minutos é fácil. Agora para quem quer aprender Rails no processo de criação de um blog, a história é outra. Você precisa de um blog funcional com: autenticação de administrador, um layout mínimo, controle de versão, algum esquema de deployment automatizado, etc.&lt;/p&gt;

&lt;p&gt;Pretendo descrever aqui não um processo de um blog, mas sim o processo que fiz para criar o meu blog. Vamos lá:&lt;/p&gt;
 
&lt;p&gt;&lt;b&gt;Layout&lt;/b&gt;: aqui é onde muitos programadores (principalmente eu!) empacam. Criar um layout do zero não é fácil, especialmente se você tem bom gosto e especialmente se já viu muitos sites bons por aí. O layout deste blog ficou bem diferente do que eu havia imaginado, mas até que quebra o galho. Levei 2 semanas para criar uma imagem no Photoshop deste layout. Muito tempo, né? Um designer faz isso em 1 hora, se já tiver uma boa direção sobre o que ele precisa criar. Outra coisa que consumiu um certo tempo foi procurar ícones na web. Você geralmente precisa de ícones para realçar o seu layout, e achar um icon set que te agrade, também pode demorar. No meio desse processo, encontrei um blog de um designer chamado &lt;a href="http://singularityconcepts.com/blog.cfm?postID=4"&gt;Joel Watson&lt;/a&gt; que fala muito sobre o processo de criação de um layout de sites, e o que te faz ser um designer melhor. Está em inglês. Vale a pena ler.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Criar o CSS&lt;/b&gt;: essa parte é mais tranquila. Em 1 ou 2 horas você cria o CSS básico, e depois vai aperfeiçoando. Se você precisa aprender CSS nos padrões Web, alguns sites que recomendo são: o blog &lt;a href="http://www.tableless.com.br/"&gt;Tableless&lt;/a&gt;, o campus online de vídeos da &lt;a href="http://visie.com.br/campus"&gt;Visie&lt;/a&gt;, o blog &lt;a href="http://www.pinceladasdaweb.com.br/blog/"&gt;Pinceladas da Web&lt;/a&gt; e o &lt;a href="http://revolucao.etc.br/"&gt;Revolução Etc&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Hospedagem Rails&lt;/b&gt;: deployment de Rails não é simplesmente fazer upload dos arquivos e pronto, site funcionando (a menos que você use Mod_Rails e já tenha o Apache configurado). Com Rails você pode fazer o deployment de uma aplicação usando várias combinações de software: Apache + FastCGI, Mongrel, Mod_Rails (Phusion Passenger), Nginx, Thin, Lighttpd. A maioria dos provedores de hospedagem nem sabe como fazer funcionar um site em Rails. Alguns oferecem o Apache + FastCGI, que não funciona muito bem, e só aguenta um uso bem moderado da aplicação. Ao ver algumas opções no mercado, acabei escolhendo o Rails Playground (plano Developer, a US$ 5 / mês, com opções maiores de plano, para quando o site crescer), mas existem outros como Linode, SliceHost, e outros bem mais caros como Engine Yard, Joyent, e por aí vai. Na Rails Playground uso atualmente Apache + FastCGI (eu sei, totalmente básico sendo que temos Passenger, Mongrel, e outros), mas com a opção de mudar para Mongrel quando precisar. E é até interessante começar algo com a versão simples, e ir sentindo a necessidade de escalar a aplicação. E nesse processo todo, você aprende muito sobre deployment de Rails. Você primeiro escala o teu código, fazendo o melhor com o que você tem, e só aí parte pra mudanças no servidor. O investimento de ter uma conta de hospedagem em um provedor que entende de Rails vale muito a pena, altamente recomendado para quem quer aprender Rails.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Controle de versão (Git, é claro!)&lt;/b&gt;: o Akita fala muito disso no &lt;a href="http://podcast.rubyonrails.pro.br/"&gt;Rails Brasil Podcast&lt;/a&gt;. E não é pra menos. É impossível você criar uma aplicação sem ter um controle de versão das alterações. E aqui entra o Git, um software opensource de controle de versão criado pelo Linus Torvalds, sim ele mesmo, o criador do Linux. Em 1 semana esse cara criou um controlador de versão, descontente com as opções existentes no momento (em 2006).&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Repositório do código (GitHub, é claro!)&lt;/b&gt;: depois de criar um código inicial da tua aplicação, ou pelo menos o arquivo README que seja, você precisa colocar isto em um repositório de onde você possa acessar remotamente e trabalhar no código sempre que quiser. Funciona assim: você cria uma conta no &lt;a href="http://github.com"&gt;GitHub&lt;/a&gt;, e envia a tua aplicação para o site. Depois sempre que você quiser trabalhar em cima da aplicação, você "baixa" o código para tua máquina local, trabalha nas alterações, faz teus commits, e depois envia as atualizações para o repositório. Você pode usar o plano free, onde teus projetos são considerados open-source, e assim todos podem abrir e ver teu código. Ou você pode usar um plano pago, a partir de U$ 7/mês, e criar projetos privados, que só você pode ver.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Deployment da aplicação&lt;/b&gt;: Capistrano é uma solução em Ruby, que funciona na tua própria máquina. Funciona como um script que faz em sequência, todas as tarefas que você faria para colocar um site em produção:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;entra por SSH no servidor de produção;&lt;/li&gt;
&lt;li&gt;gera um tar.gz do conteúdo atual do site;&lt;/li&gt;
&lt;li&gt;envia o conteúdo novo do site;&lt;/li&gt;
&lt;li&gt;corrige permissões em arquivos;&lt;/li&gt;
&lt;li&gt;roda Migrations, no servidor de banco de dados;&lt;/li&gt;
&lt;li&gt;restarta o servidor Web;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;É altamente recomendado, e depois de configurado você só precisa rodar “cap deploy” para subir uma nova versão para produção.&lt;/p&gt;

&lt;p&gt;Em breve, teremos a próxima parte da série de posts sobre como foi criar este blog, usando Ruby on Rails. Stay tuned! :)&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/LevyOnRails/~4/-aI2JrL-WHI" height="1" width="1"/&gt;</content>
    <author>
      <name>Levy Carneiro Jr.</name>
    </author>
  <feedburner:origLink>http://www.levyonrails.com/posts/2-processo-de-cria-o-de-um-blog-em-rails-parte-1</feedburner:origLink></entry>
  <entry>
    <id>tag:www.levyonrails.com,2005:Post/1</id>
    <published>2008-10-29T00:14:01Z</published>
    <updated>2008-10-29T00:19:05Z</updated>
    <link type="text/html" rel="alternate" href="http://feedproxy.google.com/~r/LevyOnRails/~3/4lb4w_bGtsQ/1-blog-sobre-ruby-on-rails" />
    <title>Blog sobre Ruby on Rails</title>
    <content type="html">&lt;p&gt;Já conhecia o Ruby on Rails de nome, mas comecei a estudar faz 2 meses. Desde então, não parei mais. Vindo do mundo ASP.NET e PHP, achei no Rails um framework muito bem resolvido.&lt;/p&gt;

&lt;p&gt;O que acho que faz do Rails um grande framework? Existem muitos pontos a considerar, mas os que me chamam mais atenção são:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;A beleza do código&lt;/b&gt;: a linguagem Ruby permite construções de código mais próximas de uma linguagem humana:&lt;/p&gt;

&lt;div class="code"&gt;&lt;pre&gt;
@soccer.score.should be_big
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;b&gt;Separação de camadas&lt;/b&gt;: Rails segue o modelo MVC (model/view/controller) onde por definição as camadas de sua aplicação já ficam separadas. Isto também facilita o que é conhecido como DRY: don't repeat yourself. O Rails permite que você compartilhe trechos de código de forma inteligente, sem repetição, o que permite uma melhor manutenção e evolução de aplicações escritas em Rails.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Tudo está em arquivo-texto&lt;/b&gt;: quer fazer um hack dentro do Rails? Quer ver como funciona uma parte interna do framework? Está tudo lá, aberto, para você ver e alterar conforme quiser. Isso dá muito poder ao desenvolvedor, que pode otimizar ao máximo sua aplicação Web.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Convenções:&lt;/b&gt; ao criar uma aplicação Web, você geralmente precisa definir várias coisas, como: onde ficarão arquivos de configuração, onde ficam as classes de acesso ao banco/lógica de negócio/apresentação, onde ficam os testes da aplicação, e por aí vai. O Rails já tem várias definições "de fábrica", permitindo que qualquer programador Rails tenha um ponto de partida muito bom para desenvolver em cima de código de outras pessoas.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;80/20&lt;/b&gt;: o Rails tenta resolver 80% das necessidades de uma aplicação Web. Os 20% restantes você pode implementar usando plugins ou gems disponíveis na web, ou escrevendo um código do zero, e claro, disponibilizando em forma de plugin para a comunidade :) Desta forma, o Rails tem uma "garantia" de não se tornar algo grande e lento, como um Godzilla dos frameworks.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Agilidade&lt;/b&gt;: em 5 minutos você já consegue criar uma aplicação em Rails. A partir daí é customizar as views (ou telas) de sua aplicação, aperfeiçoar os modelos (ou classes), e a lógica de negócios (os controllers). Isto realmente faz diferença no dia-a-dia, e este é um dos pontos que tem feito o Ruby on Rails o framework mais procurado por startups que precisam de agilidade no desenvolvimento de aplicações Web.&lt;/p&gt;

&lt;p&gt;Em resumo, Ruby on Rails é muito bom, vale a pena aprender e usar.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/LevyOnRails/~4/4lb4w_bGtsQ" height="1" width="1"/&gt;</content>
    <author>
      <name>Levy Carneiro Jr.</name>
    </author>
  <feedburner:origLink>http://www.levyonrails.com/posts/1-blog-sobre-ruby-on-rails</feedburner:origLink></entry>
</feed>
