Hacker News new | ask | show | jobs
by mjw 5857 days ago
I think they should get rid of controllers and instead model RESTful / resource-oriented concepts like Resource and Entity directly!

A Resource is an object which responds to some subset of GET, PUT, POST and DELETE. It has a unique URL which identifies it.

(OK it's a bit more complicated than that, but you get the gist).

At present Controllers in Rails are a flat grab-bag of procedural code loosely associated with some group of resources, with meta-programming used to sweep some of the mess under the carpet. They're not an elegant way to model RESTful concepts.

(I actually have a framework in development for doing resource-oriented APIs on top of Rack, however it's currently very pre-1.0)

5 comments

One particular thing which bothers me about controllers is the way they lump together obviously class- or collection-level methods (index, create, ...) with instance-level methods (show, update, delete, ...).

IMO requests should be routed to an instance representing a particular resource; the methods on that resource should correspond directly to the HTTP request methods. The collection (or the class) is a separate resource.

Agreed. I always thought that Rails controllers violated the Single Responsibility Principle (http://en.wikipedia.org/wiki/Single_responsibility_principle) by mixing collection and member concerns into a single class.
I've been thinking about this very thing for awhile, too. I wrote some code to demonstrate how I think resource/routes/controllers should work: https://gist.github.com/d64847016687e82d104b

Started on an implementation based on Rails 3 ActionPack, but never got very far. To make the case statements work, you have to override #=== on Symbol.

Sounds like an interesting idea, but raises a few questions. What are the responsibilities of a resource? What actions does it know how to perform? You mentioned responding to the HTTP verbs, so clearly it knows about HTTP. Does it know how to interact with a persistence layer? If so, I think it's seriously overburdened. If not, and this perhaps is what your Entity is responsible for, then you can have an Account resource and an Account entity. Or, in other words, an Account controller, and an Account model, essentially changing little but class and method names. Another thing that bothers me is that (assuming Resource + Entity) a resource is supposed to "be" that abstract thing you're viewing / manipulating in a RESTful architecture. But this nomenclature demotes it to a proxy to that concept. I suppose one could criticize Rails similarly, except that Rails intentionally keeps the notion of a resource abstract.
Good questions.

> What are the responsibilities of a resource? What actions does it know how to perform? You mentioned responding to the HTTP verbs, so clearly it knows about HTTP.

Yep, it's entirely a HTTP-level concept. It is aiming to model exactly the concept of a resource which is referred to in the relevant RFCs

> Does it know how to interact with a persistence layer? If so, I think it's seriously overburdened.

Nope, and I agree. (Although it is available as mixins, so you could mix it into your model classes if you wish. However I'm tending towards discouraging this)

> If not, and this perhaps is what your Entity is responsible for

Nope - at present an entity is, as per the RESTful jargon, quite a simple object which represents an instance of some media type. You can declare a lazy entity with a block though, to avoid generating the response bytes for an entity which was refused by content negotiation.

> Another thing that bothers me is that (assuming Resource + Entity) a resource is supposed to "be" that abstract thing you're viewing / manipulating in a RESTful architecture. But this nomenclature demotes it to a proxy to that concept. I suppose one could criticize Rails similarly, except that Rails intentionally keeps the notion of a resource abstract.

Think I sort of get what you mean here, but that it's not really as much of a concern when you think about it.

Really my goal first and foremost is to formalise the interfaces which one ought to expose in order for an object to be served up as a resource by a restful HTTP server.

So in that sense, the framework is to be considered more a plugin API for RESTful HTTP servers, along the lines of Restlet for Java

There is inevitably still some boilerplate in wrapping persistence layer objects in such interfaces, but the plan is to develop standard wrappers for ActiveModel classes and instances to help with that.

And of course, not every resource is backed by an ORM.

I've found the process of trying to pin down the right interface for a Resource quite interesting though, in that it's lead me to read the HTTP RFCs a lot deeper than I otherwise would have.

There's still some way to go, though.

One other big thing to point out is that this approach has the biggest pay-off when you're doing API-focused development (eg writing RESTful web services for thick client applications to use, which was where the framework originated from).

While you could do more traditional web apps this way too, I haven't really tried to optimise for that use case at present. It would need more rails-style glue code and help for HTML templating etc to get there, although that's certainly doable.

I've also been waiting to see if the new more flexible Rails makes it possible to switch in the resource-based routing and controller approach that I want. Sadly I suspect there wouldn't be much of Rails left by that point (we're not using ActiveRecord either), but bears investigation.

I was working on a framework like this, too -- I spoke about it at RubyConf in 2008, and the last version of the code (from 2009) is at http://github.com/bscofield/athena

I put it on hold a while back, though I'm thinking about bringing it back on top of Rails 3's more flexible substructure.

This is really interesting, care to share more info?
Sorry just noticed this, here's the link to the project: http://github.com/mjwillson/doze

Warning: rough edges, etc :)