A RSS Component for Rails
I was browsing around yesterday looking for some ruby or rails code to parse an RSS feed and return it to a partial so I could include it on the sidebar of our production pipeline product (Koji). I found a great article by Robby Russell with source code and everything and went to work implementing it. The code worked perfectly, rendered out properly, and did exactly what it needed to doÃƒÂ¢Ã¢â€šÂ¬Ã¢â‚¬Âthat is until I tried to render a partial.
I figured that since the partial was technically empty (the rendering in Robby’s code occurs on the controller level) that it wasn’t calling through to the controller for some reason. So picking up my handy dandy RailsAxe and started reading. Turns out this is more meant for components. Components are code blocks that are used when the application
needs to embed the processing of one action directly within another1
“Okay,” I say, having never used a component let alone made one.
So I start hacking away and work to split the view presentation from the controller itself. In order to do that I needed to
- Pull the xml feed
- Parse it
- Create an array
- Place the elements from the feed into the array
- Create a view to render out those elements
So first off I needed to set this up as a component instead of a regular controller. I created a folder called “rssfeed” in my components directory. Within that folder I made “feed_controller.rb” and a folder called “feed” to hold my view files (named by method).
I had to change the first line of Robby’s code to properly call the class and then added
uses_component_template_root in order to keep the view files within the component directory (as opposed to app/views).
require 'rss/2.0' require 'open-uri' class Rssfeed::FeedController < ActionController::Base uses_component_template_root
Then I needed to define the item structure (without creating a database model)
Rssitem = Struct.new(:title, :pubdate, :description, :link)
This says that the item has four containers and they are “title,” “pubdate,” “description” and “link.” And they are very sexy. Yes. I digress. You could create as many of these as you want depending on the complexity of the feed information you want to represent. One would simply echo out the various XML names as item.xmlname in the next function in the order they appear in the
Next, I split Robby’s method into two methods (based on the example in RailsAxe):
def self.find(*ignored) feed_url = 'http://plog.meticulous.com/xml/rss20/feed.xml' begin open(feed_url) do |http| response = http.read result = RSS::Parser.parse(response, false) result.items[0..2].each_with_index do |item, i| Rssitem.new(item.title, item.pubDate, item.description, item.link) end end rescue => e logger.error 'This RSS Component is broken baby. Check it out.' end end
This is where we define the feed, open it, read it, parse it, say “I only want the first three records” (in the
[0..2] declaration), and finally loop through and add it to the array.
Now to define the action for the view to access this array:
def plog_sidebar @rssitems = self.class.find(:all) render(:layout => false) end
Now, dismiss that class and move on with your life
And finally, let’s present this to the world in a view file:
<% for rssitem in @rssitems %> <p class="rssdate"><%=h rssitem.pubDate.strftime("%d %b %Y")%></p> <p class="rsstitle"><%=h rssitem.title %></p> <div class="rssbody"><%= rssitem.description %></div> <p class="rssaction"><a href="<%=h rssitem.link %>">[link]</a> <a href="<%=h rssitem.link %>#comment-form">[comment]</a></p> <% end -%>
After all this, however, I find that there’s a lovely little Ruby gem called FeedTools and that I could have saved a good four hours figuring this out. At the same time, these are the kinds of things where you actually start learning the language and what it can do.
UPDATE (25 Jun 06): Added a logger error in case the rss feed is inaccessible.
1 Dave Thomas and David Heinemeier Hansson, Agile Web Development with Rails, p375