The resource_feeder
plugin, along with simply_helpful
, recently snuck into edge Rails, courtesy of DHH. They’re nice. resource_feeder
lets a controller return a well-formed RSS or Atom feed for any array of ActiveRecord instances. I don’t really know what simply_helpful
does, but resource_feeder
requires it, so whatever.
install the plugins
First, check out the plugins as svn:externals
so you can keep up to date easily.
Go to whatever folder you keep Camping plugins in, or make a folder, and run:
svn propedit svn:externals .
Add these lines to the file:
resource_feeder http://dev.rubyonrails.org/svn/rails/plugins/resource_feeder
simply_helpful http://dev.rubyonrails.org/svn/rails/plugins/simply_helpful
Now, svn up
. You will have the plugins.
require them
Now your Camping application needs to load them. One way to do that is this:
%w[simply_helpful resource_feeder].each do |plugin|
$LOAD_PATH.unshift("plugins/#{plugin}/lib")
require plugin
$LOAD_PATH.shift
end
You also need to add a few support methods somewhere in your application (or in an external require
), since this is not Rails.
require 'rubygems'
require_gem 'actionpack'
require_gem 'activesupport'
module ResourceFeeder::Atom
#emulate Rail's request object with a singleton method on @env
def request
class << @env
def host_with_port
self['HTTP_HOST']
end
end
@env
end
end
class String
def pluralize
Inflector.pluralize(self)
end
end
That it. It’s all Ruby in the end, so we can make resource_feeder think it’s operating in a Rails environment even though that’s totally a lie.
usage example
Now we can make a feed controller. Assume our Camping app is named Awesome, and that we want to use Atom and not RSS:
module Awesome::Controllers
class FeedMe
include ResourceFeeder::Atom
def get
@things_to_eat = ThingsToEat.find(:all, :limit => 15, :order => "created_at DESC")
@things_to_eat = [ThingsToEat.new(:title=>"No results", :id => 0)] if @things_to_eat.blank?
@headers['Content-Type'] = "application/xml"
atom_feed_for @things_to_eat,
{:feed => {:title => "Things to eat 4 u", # feed title
:ttl => 40}, # time-to-live in minutes
:items => {:title => :title,
:pub_date => :created_at}}
end
That would be it, except we also need some specially named methods to return the canonical url of the feed itself and also of the individual records.
def awesome_models_thing_to_eats_url
"http://www.aweso.me/" + R(ViewThingToEat)
end
def awesome_models_thing_to_eat_url(obj)
"http://www.aweso.me/" + R(ViewThingToEat, obj.id)
end
end
end
One last thing: your models have to respond to .title
and .description
methods, which provide the title and body of the feed entry, respectively. Sometimes you can just point this at another field, but sometimes you will want to mess around with formatting and aggregating multiple fields into one, specially for the RSS output.
this bug juice won’t come out of my shirt
In order to be able to feed resource_feeder
an empty array, you need to fix two small bugs so that we can make it work with new()
records. Currently resource_feeder
bombs out if there are no records, which we clearly don’t want if we are making a feed for a dynamic search or something like that, in which case an empty result set is perfectly valid.
Also, we will fix it externally so that we don’t run into merge conflicts in the future when the plugin gets updated.
First, the new record must have an id
, even if it’s completely bogus, or resource_feeder
complains. So we assign it 0
, as above.
Second, resource_feeder
likes to retrieve the xmlschema
of things even if they are nil
. So we will give nil
its own special xmlschema
:
class NilClass
def xmlschema; ""; end
end
Of course you knew to do that already :) .
postcript
I’d like to use Remember the Milk as my scheduler now that I don’t have a corporate job anymore. But I want events to find their way wirelessly onto my Treo’s calendar and there isn’t a way to do that. I never use that Palm Desktop thing.
I realize I am probably like one of three people in the universe who would want this.
I created a plugins folder beneath my now beloved camping folder filled with camping .rb apps.
I go into said plugins folder.
I type: svn propedit svn:externals .
I get:
svn: ’.’ is not a working copy
I cry and thusforth ask you for help.
That will only work if your code is under version control with svn already, and you have added your plugins folder with
svn add
.If you’re just messing around and have no intention of keeping anything, use
svn export PATH TARGET
from the command line;PATH
being the url for the plugin andTARGET
being the plugin name.Nic, you gotta learn svn! Unless you use Git or something already in which case you’re way beyond me.
Tortoise for Win32 protects me from such shinanigans.
I shall put down the fancy tools and pick up the command line from now on :)