REST Style

Hey all,

  I've historically been pretty old-school about my app design. But I'm finally taking a look into REST. I have to say I really understand George Baily's take on the thing, it's not easy to see the magic coming in. However, I figure I'll give it a good shot for a new project and see if I end up getting it.

  That being said, I have a question. What would be the stylistically correct way to approach something like adding methods to controllers like GenericController#returnCountOfAllItemsWhereX (Where X could be all Generics newer than Y, etc) I know the function that gets the value should be in the model, but historically I would have created a method in my controller similar to that (ok, not so verbose, but you know ; ) that retrieved the value from the model and sent it out.

  Another question would be if I had an association like Project (has_many :tasks) and Task(belongs_to :project), how (being stylistically correct RESTwise) would I go about getting all the Tasks for a Project from the TasksController (ie, I don't want to get the Project then Tasks, but have the Project.id). This make any sense at all?

I've considered that maybe I could create other controllers to handle those functions, which from my understanding is what I should do, but everything I've thought of in that direction just makes the app more confusing. This seems very anti-REST (per my understanding).

How would you REST experts handle these types of situation? Anyway, any help is appreciated, I feel like I'm on the edge of figuring out something very useful, but some issues like this are in my way. I get the impression that REST is a lightbulb kind of thing, and until it lights up it's just tedious seeming.

H

P.S. Just because it might help make the 2nd example a little less crazy, I'm working on a Flex/Cairngorm/RAMF/Rails project. I'm not returning associations with the Project data.

Generally when you enter a url like http://mydomain.com/projects/1/tasks, in a RESTful environment, it would mean you are planning to use both the tasks and the project as part of the resource you’re getting. I would fetch the project @project (with an :include => :tasks if needed) and get the tasks from there. That said, there’s nothing holding you back from just doing something like Task.find_by_project_id(params[:project_id]) since that’s what you’ll get in your params anyway. With a bit of creativity and ruby juggling it would even be possible to dynamically create instance variables for every foreign key that’s passed in through the params hash.

Best regards

Peter De Berdt

I'd map it to a resource like this

  GET /generics/count?X=Y

map.resources :generics, :collection => { :count => :get }

class GenericsController < ...   def count     @count = Generics.count(...params[...]...)     ...   end end

Michael

I have screen cast that shows how to use nested resources using Rails 2.0. The example is on project resource that has many iterations.

Here is the link : http://www.rubyplus.org/episodes/24-Nested-Resources-in-Rails-2-.html

Hardy said the following on 04/01/08 07:12 PM:

  Another question would be if I had an association like Project (has_many :tasks) and Task(belongs_to :project), how (being stylistically correct RESTwise) would I go about getting all the Tasks for a Project from the TasksController (ie, I don't want to get the Project then Tasks, but have the Project.id). This make any sense at all?

I've considered that maybe I could create other controllers to handle those functions, which from my understanding is what I should do, but everything I've thought of in that direction just makes the app more confusing. This seems very anti-REST (per my understanding).

As far as I can make out the nested REST end up with URLs like

  http://example.com/project/1/task/47

I come from the world of Wikis and that makes no sense to me.The 'user friendly version would

  http://example.com/HouseRenovation/GetBuildingPermit

And I don't have any problem writing a controller that doesn't have a model behind it as Daniel suggested, and there don't have to be controllers for each model. If you want to see this 'old school' look at how Instiki is implemented. Yes, its route as the '/wiki' prefix but that's not needed. None of my wikis have ever had a prefix once I get past the admin scaffolding.

To me, a 'clean url' is one that doesn't have structural or implementation specific/dependant information in it.

I've never felt comfortable with that controller-per-model and each controller-needs-a-model way of working except for the Admin:: scaffold.

How would you REST experts handle these types of situation? Anyway, any help is appreciated, I feel like I'm on the edge of figuring out something very useful, but some issues like this are in my way. I get the impression that REST is a lightbulb kind of thing, and until it lights up it's just tedious seeming.

That's my feeling too. But sometimes I seem to be the 'deaf, dumb and blind' kid and it works out and is good stuff and its a 'none of the above'.

I've considered that maybe I could create other controllers to handle those functions, which from my understanding is what I should do, but everything I've thought of in that direction just makes the app more confusing. This seems very anti-REST (per my understanding).

I've considered a WebController and TopicController but all I can see them doing is being a Web Service to return lists of Web and lists of Topics. One method in each controller. Just like that hypothetical SearchController. Yes it does make things more confusing.

There's absolutely nothing incompatible with this. REST is not about how you structure URLs, it's about how you structure your application.

Michael D. Ivey said the following on 05/01/08 01:14 AM:

As far as I can make out the nested REST end up with URLs like

  http://example.com/project/1/task/47

I come from the world of Wikis and that makes no sense to me.The 'user friendly version would

  http://example.com/HouseRenovation/GetBuildingPermit

There's absolutely nothing incompatible with this. REST is not about
how you structure URLs, it's about how you structure your application.

Which is what I've been saying. I can do it without REST therefore it has nothing to do with REST.

But why, oh, why, oh why do all the examples of nested REST go on about structuring URLs like that?

Go back and look at Ryan Bigg's excellent and comprehensive explanation in this thread. There it is:

     /forums/1/topics/1 <- showing a single topic

If this isn't a REST matter then why, oh why does it appear in just about every explanation of REST I find on the net?

Michael D. Ivey said the following on 05/01/08 01:14 AM: >> As far as I can make out the nested REST end up with URLs like >> >> http://example.com/project/1/task/47 >> >> I come from the world of Wikis and that makes no sense to me.The 'user >> friendly version would >> >> http://example.com/HouseRenovation/GetBuildingPermit > > There's absolutely nothing incompatible with this. REST is not about > how you structure URLs, it's about how you structure your application.

Which is what I've been saying. I can do it without REST therefore it has nothing to do with REST.

But why, oh, why, oh why do all the examples of nested REST go on about structuring URLs like that?

Because it makes sense. Dumbed down description of REST style: a) you have resource ("noun"), which is identified by URI b) you manipulate that noun with specific request ("verb") to that URI

So GET request to http://example.com/project/1/tasks/ will get a list of tasks for the project. POST request to the same http://example.com/project/1/tasks/ will create the new topic. Let's say its id is 47. PUT request to http://example.com/project/1/tasks/47 will update the new task. DELETE to the same URI will delete task.

Even better, by using same URI but different Accept headers: you can get diferent representations (hence the "R"), of the same resource. Same GET request, same http://example.com/project/1/tasks/ URI, but different Accept headers will let you get list of tasks in html, xml, json, etc. That applies to POST and PUT too.

That means, that having single piece of information: URI, you already can manipulate that resource. You get intuitive and consistent interface.

Now let's take http://example.com/HouseRenovation/GetBuildingPermit. How do you list all permits? How do you get a list in json? How do you update or delete it? You don't know, unless you have the list off all URIs you must use for that.

If it was REST having only URI you can do a lot.

If this isn't a REST matter then why, oh why does it appear in just about every explanation of REST I find on the net?

<...>

It is REST matter in a sense. As I told earlier, RESTful URI identifies resource, a "noun", which you can then manipulate using standard "verbs" like HTTP's GET, POST, PUT, DELETE.

http://example.com/HouseRenovation/GetBuildingPermit does not identify any noun, it looks more like method name "verb" (which is not standard). This may be nice URI, but it is not very RESTful.

Regards, Rimantas

Anton, go back to what I said earlier. REST is about thinking of your
system in terms of resources. Rails REST by convention uses that URL
scheme for nested resources, but it's not required. Until you
understand resources, you're probably not going to see a big deal
about REST.

I'll try to blog about this over the weekend, see if I can get you
closer to enlightenment.

Thank you all! A few more steps were definitely taken during this whole discussion. . .getting closer.

Bala, thanks for the screencast, keep it up!

Michael, look forward to that blog post. Hope you'll post the link here! (web page link in profile doesn't take me there).

H

Michael D. Ivey said the following on 05/01/08 01:14 AM:

I come from the world of Wikis and that makes no sense to me.The 'user friendly version would   http://example.com/HouseRenovation/GetBuildingPermit

There's absolutely nothing incompatible with this. REST is not about how you structure URLs, it's about how you structure your application.

I'm not sure I completely agree with this. The above URI feels very much like a Remote Procedure Call (RPC) type of request.

If the URI in question was based on REST conventions then why is the verb embedded in the URI? I mean why is it GetBuildingPermit? How many of these remote procedures exist, and how could I ever infer how to access these resources? I'm talking about a client accessing the resources without internal knowledge of the API? SOAP for example makes no attempt at standardizing the API, but rather they attempt to expose the internal API through the WSDL document. In order for a client to use the URI in question something similar must be provided to the consumer of the service.

So no, I don't agree that this URI is compatible with REST. It simply isn't, in my opinion. Now I'm not saying there is anything wrong with using this type of URI. Just don't try to call it RESTful (at least not in the pure form).

Contrast that with:

  http://example.com/project/1/task/47

In this example a client who understands REST would not need to know the internal details of the API in order to perform basic CRUD operations. This URI clearly references one specific resource, a specific task of a specific project. Knowing that this is based on a RESTful API, the consumer would know that they can POST them, GET them, PUT them or DELETE them. They don't need to know the specific RPC calls for manipulating them. Enter ActiveResouce. They can now have a client that can use these resources directly, without the use of complicated API exposure tools like WSDL.

Michael D. Ivey said the following on 05/01/08 01:14 AM:

>> I come from the world of Wikis and that makes no sense to me.The 'user >> friendly version would >> http://example.com/HouseRenovation/GetBuildingPermit > There's absolutely nothing incompatible with this. REST is not about > how you structure URLs, it's about how you structure your application.

I'm not sure I completely agree with this. The above URI feels very much like a Remote Procedure Call (RPC) type of request.

If the URI in question was based on REST conventions then why is the verb embedded in the URI? I mean why is it GetBuildingPermit?

Good, question, but get here might actually not be a verb in the "API", perhaps this refers to a resource (say a page which describes how to apply for a building permit from the local government) which is part of or related to another resource called HouseRenovation.

How many of these remote procedures exist, and how could I ever infer how to access these resources? I'm talking about a client accessing the resources without internal knowledge of the API? SOAP for example makes no attempt at standardizing the API, but rather they attempt to expose the internal API through the WSDL document. In order for a client to use the URI in question something similar must be provided to the consumer of the service.

So no, I don't agree that this URI is compatible with REST. It simply isn't, in my opinion.

Well it might or might not be depending on whether GetBuildingPermit in this case is the name of a resource, or actually does embed get as part of the API.

I read it that "GetBuildingPermit" was the name of a Wiki page inside a 'web' named "HouseRenovation". So it's 2 nouns, one inside the other.

If I mis-interpreted that, I agree with everything you said, not quoted here.

Robert Walker said the following on 06/01/08 02:54 AM:

Michael D. Ivey said the following on 05/01/08 01:14 AM:

I come from the world of Wikis and that makes no sense to me.The 'user friendly version would   http://example.com/HouseRenovation/GetBuildingPermit

There's absolutely nothing incompatible with this. REST is not about how you structure URLs, it's about how you structure your application.

I'm not sure I completely agree with this. The above URI feels very much like a Remote Procedure Call (RPC) type of request.

If the URI in question was based on REST conventions then why is the verb embedded in the URI? I mean why is it GetBuildingPermit? How many

` NO!! I picked a bad example. Its not a 'get", its the name of an item, like on a to-do-list or on a work breakdown structure. In some municipalities you need obtain a building permit in order to do renovations.

There is no Http-GET being referred to.

A project has a number of stages:

       obtain financing, obtain material, obtain manpower.

and one of the thing to obtain my be a building permit.

I'm sorry that this irrelevancy has come up.

My point was that a lot of the literature and example for Rails, all the way back to AWDWR use find-by_id and so things get hung up on numbers. Real people will talk of things like 'the house renovation project'. The work breakdown structure gets discussed similarly: "has the floor been sanded and re-varnished?"

  http://example.com/HouseRenovation/SandAndRevarnishFloor

What I was getting at is that the 'nested route' need not declare the controller:

  http://example.com/project/HouseRenovation/step/SandAndRevarnishFloor

Rick DeNatale said the following on 06/01/08 08:40 AM:

Michael D. Ivey said the following on 06/01/08 11:02 AM:

I come from the world of Wikis and that makes no sense to me.The
'user friendly version would   http://example.com/HouseRenovation/GetBuildingPermit

There's absolutely nothing incompatible with this. REST is not about how you structure URLs, it's about how you structure your
application.

I'm not sure I completely agree with this. The above URI feels very much like a Remote Procedure Call (RPC) type of request.

I read it that "GetBuildingPermit" was the name of a Wiki page inside
a 'web' named "HouseRenovation". So it's 2 nouns, one inside the other.

Thank you! Dead Right.

The point I was trying to make is that this need not be written

  http://example.com/web/HouseRenovation/topic/GetBuildingPermit                      ^^^ ^^^^^

I make this point because all the examples I've given of 'nested resources' have the names of the controllers in the URL.

If putting the names of the controllers in the URL is not a REST thing, then why do the people proposing REST keep on doing it? Its like they're obsessed with it. Ever last example I've see, in this thread and on the 'Net, has it.

If putting the names of the controllers in the URL is not a REST thing, then why do the people proposing REST keep on doing it? Its like they're obsessed with it. Ever last example I've see, in this thread and on the 'Net, has it.

REST thing is URIs pointing at resources. It is not about the "names of controllers" it is about resources, "nouns".

Regards, Rimantas

Because it is easy, you can get it automatically, and often it fits. In Rails it's what map.resources gives you for free. If it doesn't suit your needs, well, feel free to customize all the way you want. It'll be a bit more work, but can be RESTful all the same.

For example, I'm using some fairly generic code to audit changes to resources. Display of audit logs is handled by a single controller across all resources and I can get logs for everything, a particular resource type, or a single resource; all of this in various formats. Rails routing doesn't provide the URLs I want automatically, of course, but I can easily persuade it to do my bidding

  map.with_options(:controller => 'audits', :action => 'show') do |a|     a.audits '/audits', :format => 'html'     a.audits '/audits.:format'     a.audits ':resources/audits', :format => 'html'     a.audits ':resources/audits.:format'     a.audits ':resources/:id/audits.:format'     a.audits ':resources/:id/audits', :format => 'html'   end

Michael

Because that is the default way to do it in Rails. Most people use the defaults. Adding custom routes doesn't break REST, though.

Michael Schuerig said the following on 06/01/08 01:44 PM:

The point I was trying to make is that this need not be written

  http://example.com/web/HouseRenovation/topic/GetBuildingPermit                      ^^^ ^^^^^

I make this point because all the examples I've given of 'nested resources' have the names of the controllers in the URL.

If putting the names of the controllers in the URL is not a REST thing, then why do the people proposing REST keep on doing it? Its like they're obsessed with it. Ever last example I've see, in this thread and on the 'Net, has it.

Because it is easy, you can get it automatically, and often it fits. In Rails it's what map.resources gives you for free. If it doesn't suit your needs, well, feel free to customize all the way you want. It'll be a bit more work, but can be RESTful all the same.

For example, I'm using some fairly generic code to audit changes to resources. Display of audit logs is handled by a single controller across all resources and I can get logs for everything, a particular resource type, or a single resource; all of this in various formats. Rails routing doesn't provide the URLs I want automatically, of course, but I can easily persuade it to do my bidding

  map.with_options(:controller => 'audits', :action => 'show') do |a|     a.audits '/audits', :format => 'html'     a.audits '/audits.:format'     a.audits ':resources/audits', :format => 'html'     a.audits ':resources/audits.:format'     a.audits ':resources/:id/audits.:format'     a.audits ':resources/:id/audits', :format => 'html'   end

Have you deliberately chosen a bad example? You've still got the name of the controller in each URL. Which is what I'm trying to address in this part of the thread.

And yes, Understand "its a design decision" you made. But how could you have made it differently?

How would it for my wiki look, then? Not much different from what I have for non REST, I should imagine. Which gets back to my original concern about the HOW.

Or if it doesn't look any different and the 'wiki' is the resource, not the tables that are used, then isn't whatever I write, by definition, RESTful?