Como adicionar suporte a feeds
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
1. Método de consulta que retorna todos os posts. 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”.
# app/models/post.rb
class Post < ActiveRecord::Base
has_many :comments
def self.all_posts
find(:all, :order => "created_at DESC")
end
end
2. Criando uma action para feeds. 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.
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
def feed
@posts = Post.all_posts
respond_to do |format|
format.atom
end
end
end
3. Adicionando uma rota. 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.
# config/routes.rb
map.root :controller => 'posts'
map.resources :posts, :has_many => :comments
map.resources :sessions
map.feed 'feed', :controller => 'posts', :action => 'feed'
4. Adicionando um template para o feed.. 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 AtomFeedHelper.
# app/views/posts/feed.atom.builder
atom_feed(:language => "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 => 'html')
entry.author do |author|
author.name(h "João da Esquina")
end
end
end
end
Você pode testar essa URL em seu browser. Mas provavelmente é melhor testar com o comando curl e ver o resultado completo:
curl --get http://www.myblog.com.br/feed
5. Feed no <HEAD> do site. 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:
# app/views/layouts/application.html.erb
<head>
<%= auto_discovery_link_tag(:atom, :controller => 'posts', :action => 'feed') %>
</head>
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:
# app/views/layouts/application.html.erb
<head>
<%= auto_discovery_link_tag(:atom, 'http://feeds.feedburner.com/LevyOnRails', :title => "My blog's feed") %>
</head>
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!
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.
6. Redirect para o feed. 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:
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
def feed
redirect_to 'http://feeds.feedburner.com/LevyOnRails', :status=>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
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.
E isso é tudo. Simples, não?





