Saturday, January 16, 2010

Rails: The REST Religion

I like Rails. I like Web services. I even like making a strong distinction between GET and POST for all the standard reasons. However, I do not like the REST religion.

It's a simple fact of life that Web browsers don't currently support DELETE and PUT. Rails compensates for this by passing a parameter _method=DELETE. The REST religion contends that REST is simple because it cooperates with how the Web is supposed to work. However, the Web as most people use it is browser-based, and my current browser doesn't support DELETE and PUT. In fact, I'm going to have to deal with browsers that don't support DELETE and PUT for many years to come. Hence, Rails' use of _method=DELETE is a HACK in order to try to force the Web to be something it isn't, all the while claiming that RESTful routing is the way the Web is meant to work.

Nowhere is this more evident than in this code:
<%= link_to "Delete", project_path(@project), :method => :delete %>
That little helper generates a link that when clicked on, creates a form on the fly (using DOM methods) and then submits the form. The form has a hidden field with _method=DELETE. If you have JavaScript turned off, it'll end up loading the wrong action--show instead of destroy.

This is a well-known problem which they're hoping to address in the future. By the way, did I mention that this is used whenever you generate scaffolding? Here's my point: in an effort to make the Web behave in a way that we all wish it did, they overlooked the way in which the Web actually works. In the real world, you can't count on the user having JavaScript. In fact, my boss submitted a bug against me because he had JavaScript turned off, and clicking a link lead to some mysterious behavior because it executed the wrong action.

As I mentioned Rails has a thing called RESTful routing. It's a routing system in which the URL as well as the HTTP method determine which action gets called. I don't know why, but for some reason I have a standards body that lives inside my head, and they won't tolerate me using anything other than RESTful routing. Even though I've read "RESTful Web Services" cover-to-cover, and I've read the section on RESTful routing in the Rails book, I must admit that RESTful routing actually causes me far more pain than any other feature of Rails. I use things like nested routing, special :member actions, special :collection actions, etc. However, unless I'm doing an admin GUI, I always feel like I'm trying to shove a round peg in a square hole.

I wish I could just stick with GET and POST. I wish I could abandon the idea of Resource Oriented Architectures which insist that you may use any noun you want, as long as you only use the verbs GET, POST, PUT, DELETE, HEAD, and OPTIONS. I wish I could use any beautiful verb I wanted to and shove it in the URL all willy-nilly. I wish I could just go back to the old days of :controller, :action, and :id without people thinking I'm stuck in the stone age. I wish I could group my controllers and actions based on how the user interacts with the page instead of trying to separate everything neatly with one resource per controller.

Last of all, I wish I were more pragmatic, and that I didn't have a standards body living in my head telling me what to do all the time ;)

14 comments:

Mr Darrin Eden said...

I'm simply tickled pink you've arrived at this conclusion. You've practically decided to go down the rabbit hole. :-)

Shannon -jj Behrens said...

I don't understand. Please explain ;)

Vortex said...

Rails supports but doesn't enforce RESTful design, resources are optional, you can always use ordinary routes and create custom actions.

grimen said...

For me REST also makes more sense, I'm not enforced because of a religion (I'm atheist ;)). So if I generalize what you sate: We should have sticked with java-applets and flash forever just because the web/HTML-spec didn't support such? I - and I hope more ppl - see the web as a creature that evolves like all things done in the evolution - driven by innovation. In case of HTTP: Even though it's used today it might not be used in 100 years from now, (e.g. Google wants to replace it, and in such case I'm sure RESTfulness - or something more sci-fi that makes even more sense - would be a requirement). I think it's more important to do what makes more sense among the crowd in the long run, not get contrained by some technical constraints that exists as of today. ...and as @Vortex said: It's optional to use REST in Rails.

Shannon -jj Behrens said...

> Rails supports but doesn't enforce RESTful design, resources are optional, you can always use ordinary routes and create custom actions.

I know. It's just that I feel guilty, for some reason, if I don't try to use REST all over the place.

Shannon -jj Behrens said...

I'm feeling a little less frustrated today.

* I decided to not sweat it if I fall back to non-RESTful routing when there's not an actual resource. The about page is like that.

* I decided to use RESTful routing features such as :collection and :member even more so I can have more actions.

* I moved further away from the actions that scaffolding creates. I decided to use :collection => {:admin => :get} to administrate a list of resources so that I can use the normal index action for the list of resources the normal user sees. The admin view of the resources vs. the normal user's view of the resources was really bugging me since they're so entirely different.

I wonder how other people cope with RESTful routing vs. non-RESTful routing. When I talked to Kelly at Pivotal, I got the sense that he didn't care at all about trying to stick to RESTful routing.

Alex Conrad said...

"Web browsers don't currently support DELETE and PUT" because HTML 4.01 doesn't implement PUT and DELETE.

HTML5 does support these methods, browsers implementing HTML5 are likely to support them in the future.

I just wanted to point out that the lack of support for PUT and DELETE isn't a browser problem but an HTML problem.

Shannon -jj Behrens said...

> I just wanted to point out that the lack of support for PUT and DELETE isn't a browser problem but an HTML problem.

Thanks for clarifying that.

> HTML5 does support these methods, browsers implementing HTML5 are likely to support them in the future.

I just don't feel it's likely that I'll be able to count on having HTML5 anytime soon. I know some people have disagreed with me, but it's amazing how many older browsers there are.

Since HTML doesn't support PUT and DELETE anyway, why not stick to GET and POST and make up any verb you want to in the URL?

Andriy Drozdyuk said...

If you use Rails I don't think it implies that you know what Rest is.
Also the book you are referring to is pretty much an "opinionated" survey on what the author thinks rest should be. I've read part of it before putting it down.
My first read on REST was Roy Fielding's dissertation: http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm

Currently there is NO standard for REST routing or "noun-only" usage. The ROA introduced by Richardson is a bunch of humbug IMHO.
So far the best book on REST I found (I read it in rough cuts edition through O'Rielly online) is RESTful Web services cookbook: http://www.amazon.com/RESTful-Web-Services-Cookbook-Scalability/dp/0596801688/ref=sr_1_3?ie=UTF8&s=books&qid=1263940939&sr=1-3

Regarding non-existence of DELETE or PUT and such, I would argue that those methods are more of a requirement for the web-services and API's. Using a POST for these situations in a browser is not only a requirement but the only possibility today.

Shannon -jj Behrens said...

> If you use Rails I don't think it implies that you know what Rest is.

There are a lot of people who don't know what REST is. It's an architectural style for distributed hypermedia (or something like that). However, just as people use the term REST to mean many things, I have to use the term REST to complain about those things ;)

> Also the book you are referring to is pretty much an "opinionated" survey on what the author thinks rest should be. I've read part of it before putting it down.

I'll agree with you on that one. I found it to be a pretty frustrating read, although I read it cover-to-cover so that I could say I knew what REST was about. He does do a good job explaining what the dissertation was about, and he does clarify that what he is proposing is a twist on REST called Resource Oriented Architecture.

> Currently there is NO standard for REST routing or "noun-only" usage.

Of course not. REST is an architectural style, not a particular way of laying out your URLs.

> The ROA introduced by Richardson is a bunch of humbug IMHO.

It's nice to hear someone else tell me that the king is naked.

> Regarding non-existence of DELETE or PUT and such, I would argue that those methods are more of a requirement for the web-services and API's. Using a POST for these situations in a browser is not only a requirement but the only possibility today.

Of course.

I think what I'm inferring from your comments is that because REST is a "style" and not a RFC standard, lots of people are free to use the term to mean whatever they want, and as long as it matches the style, they feel that they have the weight of the dissertation backing them up.

Shannon -jj Behrens said...

Concerning REST and Rails, I was reading the chapter on routing in "Agile Web Development with Rails", and it said, "The comprehensive way [of defining routes] lets you define a direct mapping of URLs to actions based on pattern matching, requirements, and conditions. The convenient way lets you define routes based on resources, such as the models that you define. And because the convenient way is built on the comprehensive way, you can freely mix and match the two approaches." (p. 422)

In fact, the store application that they show through the book uses a mix of both routing styles.

Shannon -jj Behrens said...

Here's another good quote from the Rails book on p. 454:

Rails makes it simple to develop an application that is based on Resource-based routing. Many claim it greatly simplifies the coding of their applications. However, it isn't always appropriate. Don't feel compelled to use it if you can't find a way of making it work. And you can always mix and match. Some controllers can be resourced [sic] based, and others can be based on actions. Some controllers can even be resource based with a few extra actions.

Alex Rohde said...

What a breath of fresh air.

Not to take a side on REST myself, but it sounds like you're asking the interesting questions that aren't asked often (Such as what's the big difference between VERB http://url and http://url?_=VERB )

Shannon -jj Behrens said...

> What a breath of fresh air.

Thanks.

> Not to take a side on REST myself, but it sounds like you're asking the interesting questions that aren't asked often (Such as what's the big difference between VERB http://url and http://url?_=VERB )

Well, the one benefit with "VERB /url" is that proxies understand what it means and can behave differently.

Thanks!