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?