Functional Widgets with Rails, JavaScript and JSONP
January
21st,
2011
h3. What's a widget?
I have no idea. I'm sure the cool kids have a better name for it these days, but we'll just call 'em widgets for now. When we draw a wireframe of a web app with a box around some bit of functionality, we tend to refer to that thing as a 'widget'.
Taking this a step further, while a widget is often thought of as a discreet piece of functionality, we also tend to think of it as being portable. That lovely little widget is just so great, let's share it with the world! Can't we just "drop that in" to another website? Yes we can!
h3. JavaScript widgets
Rendering the HTML content of our widget on a separate "consuming" web application is typically done with JavaScript. If our widget includes only static content, it's very simple to render that content remotely. Ilya Grigorik's post on Creating JavaScript Widgets in Rails demonstrates this technique, essentially wrapping each line of HTML output in a call to widgets services. However, as soon as we want to interact with a RESTful service using AJAX, we have to come up with our own pattern for our views. We often want to send back content to be rendered as HTML. We'll also need a way to communicate success or failure along with specific error messages we may want to render in the widget. Additionally, we often need to redirect our users to new pages after they complete a certain step.
Peter Bui wrote js_message that solves this pattern nicely. Her's a quick example:

document.write
.
h3. Functional Javascript widgets
What if our widgets actually do stuff? How can we build fully-functional widgets with Rails that can be consumed by other websites? Here's one way to do it...
1. Create the feature that you want to 'widgetize' with Rails
Let's say you'd like to support CRUD actions on content for your awesome home-grown blog app. Create your model, controller, view(s) and routes as usual. Don't forget your tests. Set up some nice model validation and build your forms The Rails Way. Don't forget to use theroute_url
route name instead of the route_path
name in the form actions, since we'll be interacting with this form from a different host eventually.