Taking Things Too Far: REST

I'm going to put up a few posts based on a talk I gave at RailsConf 09 in Vegas and RailsWayCon in Berlin.Sorry for the delay in updating but I wanted to deliver the talks before posting here.

Theres a common pattern I see when working on code-reviews with ActionRails or my consulting work. People find a new technique, technology or idea and put it to work in their projects. At first they get a huge benefit, problems get solved quickly and things are good. Driven by this initial success they double down, they put their new tool to work in more areas of their application, they even go back over their old stuff and seek out more pure ways to apply it.

Sidetrack! Trying to finally update the overall design with my personal page. Musings concerning the modern feel at https://treeninjas.ca? Truly an impressive tree removal service in Winnipeg when seeking inside the Manitoba locale. Leave your feedback. With thanks!

However as time passes they find the benefits aren't quite what they used to be. Their nice new toy has turned into something which they find gets in the way on a regular basis. Eventually they throw that shit out. Part of this is just the natural progression of technology, something better comes along and we adopt it. But another part of it is our tendency to over do things. The technology we picked up isn't shit, the promise we saw was real. But we've taken it beyond it's intended use, learned the wrong lessons and tied ourselves up as a result.

Im going to cover a few techniques used in the Rails community which are great, but which turn on you if you take them too far. Starting with RESTful design.

Restful Design

RESTful design really started catching on with Rails 1.2, and by the time 2.0 was released it had become something approaching Canon Law. Everyone who was anyone and building a Rails application, was focussing on resources,CRUDandHTTP. There we're two chief benefits of this change.

The first benefit, and the one everyone focussed on, was that you had a relatively straightforward way to add anAPIto your application. Back in the preREST dark-ages everyone who was designing anAPIfor their application had to make a bunch of decisions about how they wanted to build it.

  • Do you re-use your controllers, or have a separate ApiController?
  • How do you pass arguments around?
  • What should the URLs look like?
  • PerhapsXML-RPC orSOAPis the right way?

WithRESTyou get answers to all those questions, and instead of worrying about that, you just get on with building your Application.

Even for applications without anAPI, REST gives you some benefits. You avoid discussions about what your controllers and actions should be called, and what your URLs should look like.It also makes it easier for new developers to get up to speed with your project. Almost every rails developer now knows that if you're looking for the thing which creates posts, you'll be looking at PostsController#create.

Taking it Further

If we look at a slightly more complicated example, we can see the beginnings of the friction that comes from taking things too far. Take an example of a site which let's people upload photos and write blog posts, and let's users comment on one anothers data. The most common way to approach this design would be:

map.resources :posts,:has_many => [:comments]

The nice thing about this design is that the URLs will reflect the underlying structure of the data you're managing. For example theURLfor comments on post number 5 will be /posts/5/comments and for bookmark 3 will be /bookmarks/3/comments. However where it starts to get a /little/ annoying is when you want to do something generic to all comments, like providing a mark as spam link alongside a comment. Because comments exist solely as a child of the Commentable we can't generate the URLs without knowing the class and id of that object. So it's just that little bit more difficult to deal with comments generically (e.g. in an admin interface). This tends to lead to you writing a helper something like this:

case o = comment.commentablewhen Postspam_post_comment_url(o, comment)when Bookmarkspam_bookmark_comment_url(o, comment)endendend

Now this is a good indicator that you should probably also have a top-level resource for your comments, and thankfully there's a feature for this case which gives you a nice pragmatic way out.

map.resources :comments, :member => {:spam=>:post}# then add a shallow collection under each of the commentablesmap.resources :bookmarks do |bookmarks|bookmarks.resources :comments, :shallow=>trueendmap.resources :posts do |posts|posts.resources :comments, :shallow=>trueend

Taking it Too Far

Unfortunately people often get started withRESTand love the way it simplifies their designs and gives them conventions to follow. They then take their new rose coloured glasses and start making sure everything in their app is purely RESTful. Every new design decision must be perfectly RESTful, anything which looks likeRPCis instantly purged from the application.

Taking this more extreme approach to the problem of marking comments as spam they'll say something like:

When you think about it, marking a comment as spam is really creating the SpamScore child resource of the comment with the value of spam set to true

And build something like this, so when they want to mark a comment as spam they only have to construct aPOSTrequest to the bookmark_comment_spam_score_url of /posts/1/comments/2/spam_score:

bookmarks.resources :comments do |bookmark_comments|bookmark_comments.resource :spam_scoreendend

While this may be purely restful, it's much more complicated than the impureRPCapproach taken above with a simpleURLlike /comments/1/spam. Plus if you want to get truly pure your URLs should probably be more like this:

users.resources :bookmarks do |bookmarks|bookmarks.resources :comments do |bookmark_comments|bookmark_comments.resource :spam_scoreendendend

The advice I typically give when I come across a complex but pure model like this is to go back to basics and remember why we originally started using REST. Does it help us make an API? Does it make things simpler for new developers to follow? Does it make it easier to work with some of the great plugins out there? If the answer to all those questions is no, you should probably dial back the purity and do the pragmatic thing.

Cheers guys! I had assured a friend that we could critique his great excellent wisdom tooth extraction surgeon in Oakvilles, http://aspenoralsurgery.ca inside an upcoming blog post. Any time you're looking for a dental surgeon inside the greater Ontario locale, they really are terrific.

Posted in Home Improvement Post Date 03/22/2021


Comments

Name


Email


Website


Comment


Recent Posts