My most recent Pathfinder project calls for a pretty typical Ruby on Rails web application with two interesting additional components: a Facebook application and an iGoogle gadget. Though a Rails Facebook plugin was easy to find, Rails development tools for iGoogle weren’t as thick on the ground.
First, a bit of background: iGoogle, Google’s personalized-homepage service, offers developers two methods of application development:
- build a native gadget by wrapping custom HTML, CSS and JavaScript in an XML wrapper.
- build a sandboxed gadget by wrapping an externally hosted web application in an iframe.
Because of cross-domain security issues, gadgets that require authentication must be built using the iframe sandbox method. As it turns out, this method’s a lot easier. Instead of building a whole new interface, you can just tart up your existing app with an iGoogle-optimized user interface. Why replicate your existing view logic with a bunch of iGoogle-specific JavaScript when you can just reskin and call it a day?
As it turns out, though, reskinning a Rails app for iGoogle isn’t as simple as it might seem at first glance. I can think of three options. All have drawbacks:
- Serve up your existing application using all the same controllers and actions. Just build a new iGoogle layout that works well within the small viewport of an iframed gadget. Of course, you’ll need a mechanism to distinguish between iGoogle requests and normal requests. Your gadget could initially call up a one-off iGoogle controller that sets a session flag (
session[:igoogle] => true) so that all subsequent requests get the iGoogle layout. The only problem is that visits to your normal application in the same browser will get polluted by the iGoogle flag. The iGoogle interface that works so well in a tiny iframe renders your main application almost unusable in a full browser window. - Use the same approach as above, but use a URL flag or a URL rewriting scheme to differentiate between iGoogle and normal requests. This keeps your normal application from having its layout accidentally toggled to the iGoogle one. But it’s a lot of work. Accepting requests with an iGoogle flag is easy, but it’s much harder to make sure that every link or form submittal within your application propagates that flag.
- Build out a complete iGoogle controller that replicates every action from your normal application that you wish to expose to the iGoogle gadget. Depending on the number of actions and the complexity of each, this could require a lot of duplicated controller code. Of course, smart use of partials would reduce the amount of view-layer effort. Still, you’ve now got a ton of essentially identical controller actions that have to be maintained in two places.
None of these solutions is ideal, so let’s hear from you, readers. How do you build Rails apps that lend themselves to efficient re-use within iGoogle or other sandboxed “gadget” contexts? Let us know in the comments.

If I were doing this I would go with #2 and use a custom igoogle format in my url. I know this got backported to rails from merb, but I’m not sure on the details. In Merb, I would add a custom format to my controllers (provides xml, json, igoogle), create a custom layout (application.igoogle.erb), and ensure that all my url’s were generated and not hard coded strings (hard coding your url scheme is brittle). There may even be some templates that would benefit from being customized for small layouts (foo/index.igoogle.erb)
Does anyone know how this currently works in Rails? I’m dreading the transition back for Rails 3.
I’d look into a combination approach of a JavaScript link rewriter and session-based handling. I’m thinking along the lines of checking to see if your app is iframed (anti-clickjacking method) and then rewrite/set session vars accordingly.
A combination approach with CSRF-type protection (hidden secret in window.name) will give you more control if you actually need to use iframes in your application.
I’d define a custom MIME type in the Rails initializers:
Mime::Type.register_alias “text/html”, :igoogle
then in your respond_to block have a format.igoogle that renders the appropriate layout.
Store an igoogle flag in the session.
See http://www.locomotivation.com/blog/2008/06/29/redesign-your-site-in-place-using-rails-custom-mime-types.html for a similar setup.