Rough RESTing on Rails

When I started using Ruby on Rails professionally a few months ago I hoped that Rails was first of a new breed of web application frameworks. After working with it for several months I have reached conclusion that it is not the paradigm shifting framework I had hoped for. Rather, it is just an incremental, though significant, improvement to the existing paradigm of web application frameworks. It is significantlyI think the 5-10 time productivity improvements people claim are probably not far off. less effort to implement a web application in Rails than in any other framework in which I have worked but it is not better than those other frameworks, just easier.

I am an unabashed RESTafarian. I believe that the RESTful nature of the web is what has made it successful. I think that every entity (read: resource) of any consequence in any system should have at least one URI. I believe that RESTful architectures are the best way to produce scalable, flexible and powerful applications. And, sadly, I believe that it is, generally, inappropriate to build RESTful applications in Rails.

The Problem

Rails is fundamentally a procedural framework. You can see the in the default form of the URI it uses, for example,, in the names of the methods that get called on the controllers, for example, show, create, destroy, etc, and even what those methods are called, actions. The web is fundamentally not a procedural environment, it is a RESTful environment. However, much like how you can write procedural code in an object oriented environment you can also write procedural code for a RESTful environment, but by doing so you miss many of the advantages of the RESTful environment, which is quite unfortunate.

I am not disappointed by the fact that Rails is, by default, procedural. In fact, for any web application framework to succeed, at this point in time, it must support a procedural approach to web applications. This is because, basically, every mainstream web application framework in existence is procedural in nature. That fact combined with the fact that people will not, usually, adopt a new technology unless the new technology allows them to use their existing idioms more effectivelyI picked this meme up from someone’s blog but I cannot remember whose. If you recognize it please let me know where I saw it so I and link to it. means the any web application framework must support tunneling RPC over the web. Rather, the disappointing thing is that I now believe it is impractical to make Rails behave in a RESTful manner, in the general caseThough, you can reasonably create RESTful interfaces for small parts of an applications..

Initially I thought that RestController
might be a solution. RestController provides a mechanism for easily defining the actions of a controller in terms of the HTTP method used in the request. For example, you might have the following code using the RestControllerAll error handling has been left out for clarity.

class BooksController < RestControllerIn reality you would want to  modify ApplicationController inherit from RestController, rather than ActionController::Base, and to inherit from ApplicationController so that ApplicationHelper would be included.
  verbs_for :show do
    def get
      @book = Book.find(params['id'])
    def put
      @book = Book.find(params['id'])

This works reasonably well, as far as it goes. Unfortunately, merely respecting the action specified at the protocol level is not sufficient for RESTful behavior. Further, the astute reader will have noticed that the abstraction is starting to leak a little already. If you want to create or update a Book entity you need call the show action. Hardly what you would call obvious.

You can hide this inconsistency from the client with a clever set of routes but you are forced to deal with it inside the application code, and that clever set of routes will cost you. You end up needing a lot of routes and most of them have to be hand constructed. Routes in Rails are pretty easy to create but each custom route increases the cognitive load when trying to understanding the entire system. Worse yet, routes are physically separated from controllers (a sub-optimal design decision in my book) so it can often be non-obvious how a particular controller is called from the outside world. Even given a clever set of routes the URI production mechanisms in Rails force you to acknowledge that the system is procedural by requiring a controller and action be specifiedIf you do not specify them it assumes the current controller and/or action. every time a link is produced.

The problem is an absolutely fundamental one. Namely, Rails equates each URI with as single action and in a RESTful architecture a URI equates to a resource with, up to, four actions. While you can write code in Rails that will do the correct thing the names will never be quite right and you end up maintaining a lot of custom, and non-obvious, code to protect the illusion that your frameworks abstractions match those fundamental to the Web.

A RESTful Future?

There is a lot to like about Rails. It would be nice if we could retrofit RESTfulness onto Rails, but I cannot see an approach that I think would work. However, I am not a Rails expert so I am going to sketch out what I think a RESTful Rails would look like and hope that someone smarter than I will see a way where I do not.

The following code is approximately what I think a really RESTful controller should look like

class BooksController < RestController
  uri_base "/books/"

  resource "." do
    get "application/atom+xml" do
      # return XML representation of collection containing all known books.

    get "text/html" do
      # return HTML representation of collection containing all known books.

    post do
      # create new book and add it to the collection

  resource "./:id", :requirements => {:id => /^[[:digit:]]+$/}  do
    get  do
      # yield html representation of a individual book
    put do
      # update and individual book resource

  resource "./:id/editor", :requirements => {:id => /^[[:digit:]]+$/}  do
    get do
      # yield a representation of the book editor (a page with a 
      #   form that puts to "./:id" on submit)

  resource "./creator" do
    get do
      # yield a representation of the book creator (a page with a 
      #   form that posts to "." on submit)

In some was this looks a bit like what the RestController provides but it is vitally different is several ways. First, resources are specified by explicit URI patterns. URIs are a fundamental part of the web and are beautiful and elegant in their own right. There is no reason to hide them. There are some practical concerns with explicit URI patterns but this example avoids those by having all the URI patterns be relative to a base URI pattern specified in the controller. If the controller is moved to another URI it need only be tweaked in one place. Second, action implementation is allowed to vary on URI, HTTP method and requested content type. Varying on content type is basically required for any non-trivial REST application so it should be baked into the framework from the beginning.

Having actions specified by URI patterns means that we would need new URI production mechanisms in Rails. These new URI production mechanisms would take the target controller because, in this world view, URIs are usually relative to a controller. The should also, optionally, take a MIME type.

  <%= link_to "I Know A Rhino",  :controller => 'books', :resource => './:id', :id => a_good_childs_book -%>

In principle the above is doable, I think. For example, a RestfulController could write new routes based on the resources calls. The code would probably be a bit hairy but the interface could be made pretty clean. And URI production functions would be cake by comparison to the non-RESTful ones. The problems are mostly practical. For example, controllers are currently loaded lazily. They are not loaded until the first time a route to that controller is exercised. This means that you cannot have the controllers add the appropriate routes for the resources they declare. It might be possible to change Rails to load the controllers eagerly but that raises the question of if two controllers URI spaces overlap who should take precedence. I think you would just do last loaded wins but that means that you would need a way to explicitly tweak the load order. And how do generated routes relate to explicitly routes, precedence-wise. I haven’t even really thought about how backwards compatibility with RPC style controllers would be maintained, and that would be absolutely required, or how template lookup would work.

Our Last Best Hope?

I fear that we RESTafarians might have to embrace (and extend) Rails, even though it is not the optimal platform for a RESTful web application framework. The reason is that Rails is really good at, human facing, web applications. I doubt that we will get this sort of productivity compatibility in developing RPC style web applications again anytime soon, if ever. That means that it will be hard to convince the world to embrace a truly RESTful web applicationframework because, even it is great, it will provide only marginal improvements for the RPC web application idiom that people know.

Hopefully someone with more skills and free time than I will take up the challenge of making Rails RESTful framework. Until then I suppose I will continue to write ugly, but functional, RPC style web applications. At least with Rails I do not feel like I am wasting most of my time with administrivia. On the other hand, the lack of administrivia leaves me with more time to feel dirty about the interface I am creating.

12 thoughts on “Rough RESTing on Rails

  1. I have seen that. I am not sure exactly how I feel about that but I know that it is not enough. My examples asside, I do not really like using application internal identifiers in URIs if there is any other choice. It makes the URI too opaque and obscure for my tastes. And I think that in most cases there are other choices. That fact alone makes me think that the routes in the restifarian plugin are not a huge inprovement. I basically think that since controllers are all about interacting with the user that the URIs should be specified explicitly in the controller because they are intrinsic in the user interaction.

  2. I wrote the initial RestController proof of concept and have begun using it in a real software project. Its evolved quite a bit from the one in my post on the microformats list, but the same basic syntax remains as you describe it.

    I really like your idea of putting a way of specifying the URI a controller observes inside the controller itself. Keeps everything together in one place nice and neat. For this to work I think it should work side by side with the
    current routing system rather than replacing it. I think I might take a stab at this in the next week.

    I also like the way you define handlers for each of the methods. I’ll probably borrow that in my next iteration of RestController.

    The one thing I disagree with is that I don’t think its a good idea to specify the content-type of the response in the action. The same base instance variables should be made available for all supported views, so the same code should be used to gather together the data. There may be slighly different presentational logic based on the type of view, but I think that logic should be pushed to the view and its helpers rather than existing inside the controller.

  3. Dan, I look forward to seeing what you end up with.

    I agree that it would work along side of the current routing system. I think it is vital that RPC style controllers continue to function as they currently do.

    As for content-type… I think you are right. It is important to provide a way to easily support multiple content types but it should not be handled at the action definition level. That code should be able to be shared by all the representations of that resource. However, I am not sure exactly how it shoule be handled instead.

  4. I think the problem about separating presentational code from controller code has already been solved to some extent with Rails’ Helper system.

    The .rhtml template can contain simpler logic, like if statements and variable interpolation, but complex logic can be placed into Helper classes and invoked with a simple method call.

    If you were going to design a view module for some other representation you could decide to either include all the presentational logic inside the templates themselves, or invoke a method from an outside class. After seeing Rails’ approach work successfully in practice I’d probably design any views modules in a similar way.

  5. I think that the helper system is not well suited for this. We are really talking about completely independent views of the same date. I do not think that you want either helper methods which render the entire html page or templates which are, in effect, giant if blocks (with one part being the HTML template and the next part being an Atom template and a third part being a RSS template).

    Perhaps some convenient for template naming could work, like “++”. But when I write that down it looks overly complicated. On the other hand shared behavior is well understood at the controller/action level, you just have a private method that does the shared work. Handling different content types at the controller/action definition level is not quite correct conceptually but it might be workable, pragmatic choice. Of course I think you would just be pushing the complexity to the app developer (because they would probably end up need to explicity specify what template to use) which is probably a Bad Thing.

    Anyway, it is not clear to me what the best answer is but if something occurs to me I will post it here or microformats-rest.

  6. Sorry I wasn’t more clear, but I wasn’t suggesting using the actual ActionView Helper system for alternate representation views. ActionView Helper methods are too tightly bound to the representation type, which I think is a good thing.

    What I was suggesting was that I like the concept of Helper system on a per-representation basis. All it is is a class where you define methods that your view/representation code can access, allowing you to extract complex logic from a view into a reusable component. Helper systems should not be shared between different representations.

  7. Hi Peter,

    I wanted to let you know that I released a new version of my RESTful Rails plugin on RubyForge yesterday. I took your suggestions, remixed them with my own ideas and I’m pretty happy with the results.

    Here’s the announcement on the Microformats list:

    You may also be interested to note that Rails 1.1 will have something similar to your idea of sending different variants depending on what the client asks for. This process is called Content Negotiation, and it looks pretty cool:

  8. I saw that on uf-rest. Glad to see you are still working on this problem. Maybe I will get a chance to take a look at it in the near future. Thanks for letting me know, though.

  9. I’m glad to see that you do some more work on uf-rest problems with it. Thanks for letting us know about it and also that there’s a lot of REST-based changes going on in Rails.

Comments are closed.