<?xml version="1.0" encoding="UTF-8"?>
<post>
  <body>&lt;p&gt;Imaginei que adicionar suporte a feeds em uma aplica&#231;&#227;o Rails fosse complicado. Mas uma vez &quot;tomei na cabe&#231;a&quot; vendo que o Rails realmente &#233; produtivo de se trabalhar :)&lt;/p&gt;

&lt;p&gt;&lt;b&gt;1. M&#233;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&#234; precisa criar um m&#233;todo que fa&#231;a uma query que liste todos os posts do blog. Seguindo a filosofia &quot;fat model / skinny controller&quot; este m&#233;todo deve ficar dentro do pr&#243;prio model &quot;Post&quot;. Vamos criar um m&#233;todo chamado &quot;all_posts&quot;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;
# app/models/post.rb
class Post &lt; ActiveRecord::Base
  has_many :comments

  def self.all_posts
    find(:all, :order =&gt; &quot;created_at DESC&quot;)
  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 &quot;feed&quot; dentro do controller &quot;posts'. Repare que aqui j&#225; estamos usando o m&#233;todo &quot;all_posts&quot; criado no passo anterior.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&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&#225;, n&#227;o existe como acessar a URL http//www.myblog.com.br/feed, porque ainda n&#227;o temos uma rota para esta URL. Precisamos adicionar esta rota no arquivo config/routes.rb. Note a &#250;ltima linha do arquivo.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&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&#225; sabe que existe uma URL /feed em nosso blog. Mas ele n&#227;o sabe o que renderizar ali, na action &quot;feed&quot;. Ele s&#243; sabe que possui um objeto @posts dispon&#237;vel. Vamos dizer ao Rails como ele deve formatar esse retorno. O exemplo abaixo foi retirado da pr&#243;pria documenta&#231;&#227;o do Rails, do Helper &lt;a href=&quot;http://api.rubyonrails.com/classes/ActionView/Helpers/AtomFeedHelper.html#M001208&quot;&gt;AtomFeedHelper&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;
# app/views/posts/feed.atom.builder
atom_feed(:language =&gt; &quot;pt-BR&quot;) do |feed|
  feed.title(h &quot;My blog&quot;)
  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 &quot;Jo&#227;o da Esquina&quot;)
      end
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Voc&#234; pode testar essa URL em seu browser. Mas provavelmente &#233; melhor testar com o comando curl e ver o resultado completo:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&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&#225; temos um feed funcionando. Agora precisamos colocar isto em nosso HTML, para dizer ao mundo que nosso blog j&#225; tem suporte a feeds :) A melhor forma &#233; usar o helper auto_discovery_link_tag do Rails:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&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 &#233; o /feed que criamos at&#233; agora. Mas se voc&#234; como eu, prefere usar o FeedBurner para isso, ao inv&#233;s disso fa&#231;a assim:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&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; &quot;My blog's feed&quot;) %&gt;
&amp;lt;/head&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ok. Agora se voc&#234; 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&#233;m usar a url http://www.myblog.com.br/feed, desconsiderando o que est&#225; 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&#225; redirecionada para a URL do http://feeds.feedburner.com/LevyOnRails. Qual a vantagem disso? Voc&#234; n&#227;o ter&#225; metade de seus leitores usando o FeedBurner e outra metade usando o feed direto de teu site. Assim voc&#234; consegue medir 100% a leitura/visita&#231;&#227;o de seu feed, usando as facilidades dispon&#237;veis no site do FeedBurner. Vamos precisar alterar o nosso controller:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&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&#225;vel do servidor HTTP_USER_AGENT, se esta cont&#233;m a string &quot;feedburner&quot; ou &quot;feedvalidator&quot;. Se tiver, n&#243;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 &#233; tudo. Simples, n&#227;o? :)&lt;/p&gt;
</body>
  <comments-count type="integer">22</comments-count>
  <created-at type="datetime">2008-11-05T14:11:02Z</created-at>
  <id type="integer">3</id>
  <permalink nil="true"></permalink>
  <slug>como-adicionar-suporte-a-feeds</slug>
  <title>Como adicionar suporte a feeds</title>
  <updated-at type="datetime">2008-11-05T14:12:46Z</updated-at>
  <user-id type="integer" nil="true"></user-id>
</post>
