What's New in Edge Rails: Get Your RSS & Atom Feeds for Free

Posted by ryan
at 4:48 AM on Thursday, September 14, 2006



Resource feeder is no more, but the atom feed helper is here to replace it

Rails is all about some open-ness and interopability and it has become incrementally easier to achieve this with the new Resource Feeder plugin. This plugin gives you an easy way to create RSS and Atom feeds in your controllers from a collection of model objects with the use of the rss_feed_for and atom_feed_for methods:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class PostsController < ApplicationController

  # Build an rss feed
  def rss
    render_rss_feed_for Post.find(:all, :order => 'created_at DESC',
                               :limit => 10)
  end

  # Build an atom feed
  def atom
    render_atom_feed_for Post.find(:all, :order => 'created_at DESC',
                                :limit => 10)
  end

end

So how do these feed methods know how to pull information from each individual resource of the collection? It uses a combination of options passed into the feed methods and specific properties of the resource. If you don’t pass any options into these feed methods your model objects should have title, description and created_at reader methods (and updated_at for atom).

Options

There are several options you can pass into these nice little feed methods to customize the title of the feed and most of the other feed elements. Here’s my attempt at enumerating all of them for RSS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Feed options (w/ defaults):
options[:feed][:title]            # Pluralization of the model class, i.e. "Posts"
options[:feed][:link]            # Url to this record
options[:feed][:description] # omitted if not specified
options[:feed][:language]    # "en-us"
options[:feed][:ttl]              # 40

# Individual item options (w/ defaults).  These are the method symbols used to
# retrieve the proper values from each individual object:
options[:item][:title]            # :title
options[:item][:description] # :description
options[:item][:pub_date]   # :created_at

# General options:
options[:url_writer]            # an instance of UrlWriter

Just pass in these options to your feed methods as needed:

1
2
3
4
5
6
7
8
9
10
11
12
class PostsController < ApplicationController

  # Build an rss feed
  def rss
    render_rss_feed_for(Post.find(:all, :order => 'created_at DESC',
                               :limit => 10),
                    { :feed => {:title => "All posts"},
                      :item => {:title => :name,
                                :pub_date => :updated_at} })
  end

end

Feelin’ sassy? Try taking advantage of this guy :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class PostsController < ActionController

  # View a collection of posts.  If "format" is specified
  # will return view of that type (of either rss or atom format)
  # /posts/list.rss => RSS
  # /posts/list.atom => Atom

  def list
    @posts = Post.find(:all, :order => 'created_at DESC',
                            :limit => 10)
    options = { :feed => {:title => "All posts"},
                    :item => {:title => :name,
                             :pub_date => :updated_at} }

    respond_to do |wants|
      wants.html
      wants.rss { render_rss_feed_for @posts, options }
      wants.atom { render_atom_feed_for @posts, options }
    end
  end
end

It just feels so right sometimes!

oh yeah, and to install this pup just do:

1
2
script/plugin install simply_helpful
script/plugin install resource_feeder

tags: rubyonrails, rails, rss, atom

Comments

Leave a response

  1. jonniiSeptember 14, 2006 @ 05:38 AM
    I saw this checked in to rails the other day and figured out how to integrate it. My first thought was to use the respond_to functionality and it was so simple! Luckily my posts already had title, description etc... =) Great write up btw.
  2. JeremySeptember 14, 2006 @ 06:23 AM
    Wow, that looks very, very useful. And slick.
  3. LeeSeptember 14, 2006 @ 06:24 AM
    That is quite spiffy.
  4. zerohaloSeptember 14, 2006 @ 06:57 AM
    Will this plugin work on Rails 1.1.x or only on Edge?
  5. jonniiSeptember 14, 2006 @ 07:04 AM
    zerohalo, it should work 1.1.x.
  6. Scott MatthewmanSeptember 14, 2006 @ 07:38 AM
    In the final example, the one that uses a respond_to block, you seem to need render_rss_feed_for and render_atom_feed_for, otherwise the script falls back to the default. Also, right now the RSS generator produces invalid dates (it specifies .to_s(:rfc82) instead of :rfc822). But this certainly looks like it's going to simplify a lot of coding in the near future. It certainly means that the project I'm currently working on has no excuse for not providing RSS feeds out of the box...
  7. Ryan DaigleSeptember 14, 2006 @ 08:58 AM
    Scott, do you mean it should look like this?:
    
    respond_to do |wants|
      ...
      wants.rss { render_rss_feed_for(@posts, options) }
      ...
    end
    
    
    If so, then I probably need to add @render@ to the earlier examples as well (since all XX_feed_for does is return an xml string) - yeah?
  8. Tony StubblebineSeptember 14, 2006 @ 08:58 AM
    So what do you put in the options if your objects have a name attribute instead of title?
  9. Ryan DaigleSeptember 14, 2006 @ 09:09 AM
    Tony, you can just pass in the @:name@ symbol for the @options[:item][:title]@ option. I updated my example to reflect this and to clarify my initial scenario:
    
    ...
    :item => {:title => :name,
              :pub_date => :updated_at} 
    ...
    
    
  10. Scott MatthewmanSeptember 14, 2006 @ 09:21 AM
    @Ryan: Technically, you also need to set the correct content type as well. The plugin has `render_rss_feed_for` and `render_atom_feed_for` methods that do this for you. Seems like a better habit to get into to avoid forgetting on the odd occasion And you're right, it applies to your other examples too!
  11. Ryan DaigleSeptember 14, 2006 @ 11:19 AM
    Scott - I was stuck on revision 5098 when I was taking a look at the source and missed out on the helpful @render_XX@ methods that were committed later. Thanks for the heads up!
  12. Jon MaddoxSeptember 14, 2006 @ 11:47 AM
    I"m confused. This is new in edge, but its not IN edge? I see that the plugin is in the core svn. Why is hosted there? Is it there to live and prove itself before it can walk down the red carpet to core?
  13. Tony StubblebineSeptember 14, 2006 @ 12:01 PM
    Ryan, thanks for the clarification!
  14. Deirdre Saoirse MoenSeptember 14, 2006 @ 12:09 PM
    :order => 'created_at' Wouldn't that be: :order => 'created_at DESC'
  15. Ryan DaigleSeptember 14, 2006 @ 12:24 PM
    Deirdre: that depends - do you want to see your newest posts first? :) Yeah, they need a @DESC@ - thank you!
  16. Ryan DaigleSeptember 14, 2006 @ 12:28 PM
    Jon: Apparently the core team isn't doing any branching or tagging with the plugins repository - so once it's in it's in. On a side note - a lot of the plugins rely on @alias_method_chain@ which is in Edge (well, I know that the Simply Helpful one does at least). Definitely seems like there should be some synchronization between the plugin branching and the rails branching, yeah?
  17. Jon MaddoxSeptember 14, 2006 @ 12:32 PM
    yah, I updated to 5110 and still didn't have the render_rss_feed_for, after adding the plugin, its complaining about not having simply_helpful installed either.... *uninitialized constant ResourceFeeder::Rss::SimplyHelpful*
  18. DHHSeptember 14, 2006 @ 03:17 PM
    You can't keep nothing secret in this community ;) This plugin depends on SimplyHelpful being installed as well. "gem install simply_helpful".
  19. Simon HarrisSeptember 14, 2006 @ 04:21 PM
    Looks very cool. Any chance of adding support for created_on as a fallback if no created_at is specified. Rails allows/promotes the use of both.
  20. Jon MaddoxSeptember 14, 2006 @ 04:34 PM
    Yeah, I just got shot down because of that too.
  21. timurvSeptember 15, 2006 @ 06:56 AM
    This plugin dows not working with 1.1.6, becouse there is no alias_method_chain method
  22. rickSeptember 19, 2006 @ 11:43 AM
    We put these in plugins as part of a testing ground for stuff in the next version of rails (post 1.2 I imagine). This way we can play around without actually committing anything to Rails Core. I'd love these to be fully compliant, so please do file patches, broken tests, or just tickets to fix any validation issues. And, one shortcoming I've come across is there's no way to access the view helpers (in case you want to textilize your post content, for example).
  23. anandDecember 01, 2006 @ 02:48 PM
    I think DHH meant script/plugin install simply_helpful.
  24. topfunkyDecember 22, 2006 @ 09:22 AM
    A nice feature is that any of the options can take a Proc as an argument: options[:item][:description] = Proc.new {|record| do_something_with(record) }
  25. David PalmFebruary 07, 2007 @ 07:27 AM
    tested this today (7/2/2007) using: script/plugin install resource_feeder script/plugin install simply_helpful I think I found a bug. Maybe the versions are misaligned? Line 25 in resource_feeder/rss.rb is: options[:feed][:link] ||= SimplyHelpful::RecordIdentifier.polymorphic_url(new_record, options[:url_writer]) But should be: options[:feed][:link] ||= SimplyHelpful::PolymorphicRoutes.polymorphic_url(new_record, options[:url_writer]) Maybe the "polymorphic_*()" methods got moved out of RecordIdentifier just recently? There are other places where you need to change too... Works great though! :-)
  26. Ryan DaigleFebruary 07, 2007 @ 09:41 AM

    David P. – I think you should submit a patch for this if that’s the case… :)

    http://dev.rubyonrails.org/

  27. KjellFebruary 10, 2007 @ 07:38 PM

    It’s already there -> http://dev.rubyonrails.org/ticket/7468.

    I’m having this problem as well and hoping it will get fixed up nice and quick.

  28. JosephFebruary 12, 2007 @ 06:11 PM

    Looks like Markdown has trashed your list of options in this post..

  29. jvpFebruary 16, 2007 @ 07:41 AM

    Great write-up and apparently the authoritative source according to Google. So very little has been written about this. All signs point to this article. Two suggestions:

    1) As Joseph indicated, it looks like Markdown busted your options markup. Hovering over the URL indicates what you were trying to illustrate, but the text shown is broke.

    2) To make the article more complete and self-contained, at the end where you mention script/install, you should also mention installing script/plugin install simply_helpful, as DHH pointed out.

  30. RyanFebruary 16, 2007 @ 09:41 AM

    jvp – excellent points. I’ve updated the post with some much needed formatting love. Thanks for the motivation!

  31. RyanFebruary 16, 2007 @ 09:44 AM

    David P. & Kjell – Looks like your issue has been patched: http://dev.rubyonrails.org/changeset/6150

  32. jvxMarch 05, 2007 @ 09:54 AM

    I just tried out this plug-in, but it doesn’t seem to work for me….

    first, I got a collection of the items (of type “page”) that I want to create an rss feed for, and in the controller, I added:

    def rss

    render_rss_feed_for(@collection_of_pages,
    { :feed => {:title => "Recently Revised"},
    :item => {:title    => :name,
    :pub_date => :updated_at} })

    end

    But, when I try to run this, I get an exception that it says I don’t have a “pages_url” method. After some preliminary investigation, I added a :link => “http://test” to the :feed variable, and then I got another exception of no “page_url” method….. So to fix this, I had to create a method called page_url in my controller. Rails passes one variable to this method from which I will need to figure out which page it is referring to return a url that points to this page. However, this seems like more work than just creating the rss feed manually… (although I am posting because I might be missing something simple

  33. PhilMarch 07, 2007 @ 05:10 PM

    how can you explicitly declare the link for the items? rss.rb is automagically creating it to point back to the actual post page; suppose i wanted to go somewhere else (use in a non-blog app)? any ideas?

  34. PhilMarch 07, 2007 @ 05:34 PM

    Okay figured that out… you add this line above the resource_link = lambda… code: options:item ||= lambda { |r| SimplyHelpful::RecordIdentifier.polymorphic_url(r, options[:url_writer]) }

    from there, you can add :item :link => :link in your controller and that will access the link method in your model…

  35. Bala ParanjMarch 16, 2007 @ 09:25 PM

    How do I test the RSS and Atom feeds?

  36. StanApril 10, 2007 @ 10:21 PM

    sounds interesting, can put Feed generator and Anothr IM-based delivery. It is pretty cool!

  37. GeoffApril 15, 2007 @ 11:37 AM

    Phil: You should only need to set options:item with a Proc object, no need to hack the plugin.

  38. Micah WedemeyerMay 14, 2007 @ 11:20 PM

    If anyone is having problems with polymorphic_url, I wrote up a small howto detailing how to get around this issue.

    http://blog.aisleten.com/2007/05/14/demystifying-resource_feeder-for-rss-feeds-polymorphic-urls/

  39. hudlercMay 27, 2007 @ 10:32 AM

    Resource_feeder is gone now :-( http://dev.rubyonrails.org/changeset/6835