« SYWTWAB 7: Reviewers, And How Not to Kill Them | Main | The RADAR Architecture: RESTful Application, Dumb-Ass Recipient »

March 28, 2007

Change to REST URLs for Rails 2.0

Mike Clark pointed out a Rails change in Edge. No longer will we have to use RESTful URLs such as article/1;edit. We're going back to the more normal-looking article/1/edit And a great huzzah! was heard throughout the land.

This only applies in Edge, so folks on 1.2.3 won't be affected. However, as Mike pointed out, you probably want to stop publishing permalinks containing semicolons (of you have any), because Rails 2.0 map.resources won't recognize them.

TrackBack

TrackBack URL for this entry:
http://www.typepad.com/t/trackback/2226312/17290970

Listed below are links to weblogs that reference Change to REST URLs for Rails 2.0:

Comments

One of the ways I understood REST was that it attempted to separate the nouns from the verbs. Ideally, all the verbs would go into the protocol, and the URLs would be the nouns. However, as the protocol only currently supports a few verbs, then I quite liked how Rails made extra verbs not look like part of the URL using the semi-colon.

Maybe I just haven't yet grokked the whole REST thing yet (most probably the situation), but the seeming re-marriage of verb and noun (or at least the loss of ability to easily distinguish them) disturbs me slightly. So (just out of interest) my question is: why was a great Huzzah! heard throughout the lands?

I know it sounds a bit stupid, but this is one reason I've been put off the whole REST thing. I didn't want to lose my lovely clean URLs :) Good news.

"RESTful URLs such as article/1;edit. We're going back to the more normal-looking article/1/edit "

RESTful doesn't make the distinction here.

1: the reason you expose URLs like /edit are many, but one is important; and it's to do with html forms processing. In theory you can GET to read, PUT to write, POST to create. In practice when dealing with browsers (and with some frameworks that are controller/stage driven), it can be easier to map the verbs into URL space. It is a mildly lunatic way of doing things tho'. In OO this is exactly like having an object for each CRUD action, with the 'R' object being the 'real' one, instead of one object that can accept all messages. I'm pretty sure if one propsed an object design like that, it would be shot down. So - whether you use ';' or path segments isn't the issue - it's mapping verbs to nouns, arguably not a convention consistent with DHH's "world of resources", but something you have to do to deal with deployed web infrastructure.

2: "stop publishing permalinks containing semicolons". To be honest the real gotcha is Rails putting primary keys into permalinks. That's not a good default; one database reset or dump/load and those URLs are hosed. The URLs you have on this site for example, are likely to be more stable (assuming the date and slug are one-shot don't change when you update). An exception would be a management/admin interface (eg if you had blog software it's reasonable to use PKs in the UI). The problem programmers will have is carrying a non-db key with the object that can be be used to inject into a URL. When developing apps these days I find myself giving objects some kind of one-shot fixed non-db field, like an md5 hash, whether or not the object is going to be web exposed or alternatively a fucntion that can compute it. Take a look at flickr for an example of URL space that doesn't use pks. Not neccessarily pretty, but very stable wrt to change.

Oh thank goodness. Although in the long run it really made little difference to me, it never really felt right tossing those ;s in there.

The really ugly part with the 1.2 scheme was not ;edit, but /new, which should have been ;new. So the new scheme is actually more consistent.

I'm pretty sure we'll ship something with 2.0 to allow recognition of semi-colon based urls, even if it's just a plugin. I'm definitely not a fan of busting people's applications unless truly necessary.

As for pks in the URL, Given that a primary key is just the 'main identity' of an object within your application, I'd question the wisdom in having a 'primary key' and a 'primary key that I stick in urls'. The argument about 'instability with dumps and reloads' can apply equally to any field in your system. If you left out the slugs from your database dumps then regenerated them from the titles you'd probably get broken links too from people editing the title after publishing. When dumping your database, be sure to include whatever your identifying column is and you're fine.

Finally, flickr's urls appear to have some kinda nine digit number in them (http://www.flickr.com/photos/koz/277914311/ ), not sure what it is, but just as with 'id' and 'slug' it obviously has the same limitation that it will need to be preserved during any migration, dumps or reloads.

"The argument about 'instability with dumps and reloads' can apply equally to any field in your system."

In theory. In practice autoincrementing database pks lack stability. There are a lot of movable type users out there, for example, that have been bitten by its default choice of serving a pk instead of a slug (myself included). Partitioned dbs would tend to stray away from autoincrements in favout of guids.

"I'd question the wisdom in having a 'primary key' and a 'primary key that I stick in urls'."

I wouldn't; I have URLs that i expect to last for many many years. URLs are just another vector for distributing data. But if you can make autoincrements permanent and stable, more power to you.

The thing that bugs me about the semicolon in the URL is that browsers and controls that recognize URLs don't understand the semicolon.

For example, if I paste a link that has a semicolon into my Backpack (in a note), it will only recognize the URL up to the semicolon. Therefore, the feature is rendered useless.

http://www.somedomain.com/test/1;edit

But it works fine here. Can that be a Backpack issue?

Sure, perhaps I was unclear. Leaving the merits or otherwise of autoincrementing integers aside. Your application has many internal references which rely on whatever your 'primary key' is, be it a guid, a slug or an autoincrement key. If for whatever reason autoincrements aren't suitable for your URL requirements, I'd suggest using your slugs as your primary keys. You lose the simplicity of the autoincrementing integers, but presumably for a good reason.

As for the MT case, I was also bit by that. However the problem wasn't with the id in the URL, it was with the export format (still) not including it. http://www.sixapart.com/movabletype/docs/mtimport

Whatever you use in your urls, needs to be in your export format, irrespective of whether they're slugs or sequential / hi-low ints. Either way, I think we're saying more or less the same thing ...

You know, it dawned on me last night... The Backpack issue is probably a result of the Textile (RedCloth) library not recognizing the semicolon. They are probably processing the Textile before saving the data to the database (as they should). Redcloth is then putting the closing tag BEFORE the semicolon, thinking it had reached the end of the URL.

Duh... that is why it works here and not there. Sorry to digress from the conversation you guys are having.

This is a welcome change. But the real question on my mind, how is the dichotomy of controller/id controller/action addressed?

The whole thing leaves me a bit cold. The URL is meant to represent the resource, and the HTTP method the operation. So like someone else has said, there isn't AFAIK an HTTP method that maps to the operation "get for edit".

Should we be biting the bullet and extend HTTP?

I've seen a couple of workarounds that I like better:

GET /resource/readonly

Which would provide a readonly (not editable) version of a given resource. I'm not a Rails expert but couldn't this be mapped to the right action using routing?

Something else I like is permission based retrieval. So if you are logged in as a user with read/write privileges. Then

GET /resource

Would provide you with an editable version. AJAX style inline editing would work nicely with this approach I think.

As anyone else seen Restful alternatives?

There is a HTTP method that maps to the operation "get for edit". It's e.g. GET /companies/12345/edit. Don't let the word "edit" throw you off here, it is not the operation or the action on resource /companies/12345, rather the action is GET on the resource /companies/12345/edit. Or name it /companies/12345/editor if that's more clear.

Instead of GET /companies/new and GET /companies/12345/edit as is now the case with Rails 2.0 I'd rather have liked GET /companies/editor and GET /companies/editor/12345. That would have have been more clear (because "new" and "edit" are verbs, which have no place in URLs imo).

i have tried coding with the rails 2.0.2, but getting some errors!!!

I love Restful Rails and James Golick devised a way to make it even easier. Take a look how at "this screencast":http://www.akitaonrails.com/2008/1/25/easy-restful-rails-screencast that I made available at my blog. Cheers.

Post a comment

If you have a TypeKey or TypePad account, please Sign In

Now in Beta

  • Programming Ruby, 3rd Edition
    Third Edition, Covering Ruby 1.9, now in beta
My Photo

Site Search

  • Google Search

    The web
    PragDave

Pragmatic Stuff

Photos

  • www.flickr.com
    This is a Flickr badge showing public photos from pragdave tagged with pragdave_badge. Make your own badge here.