This is what I think of REST architecture.
For every resource, there is an unique URI.
We can manipulate that object using its URI and HTTP actions [POST, GET, PUT and DELETE]. The HTTP request transfers the representation of the state of that object.
In all the texts I have read, REST is explained in a weird and confusing manner.
One more thing, RESTFUL implementation in rails produces different urls for different purposes. Like /teams -> for 'index' method... /teams/new -> for 'new' method and so on. Ain't this moving away from rest, which defines that each resource has one unique URI???
I think your understanding of REST is pretty good. It doesn't need to be any more complicated than it should be. Also @Surya outlines some very good points.
The way Rails maps the HTTP methods to controller methods is:
GET => show
PUT => update
POST => create
DELETE => destroy
Two other resources/methods that rails provides namely:
resource/new => new
resource/edit => edit
are most likely not resources for all practical purposes but are needed for building web pages and applications. If the client had full knowledge of the resource, these would not be needed. A client can just make POST
and PUT
calls with the resource information and create or update resources as needed. But since users are not expected to know the ins and outs of a resource, they need an easier interface to work with for creation or updation.
If all users were fully aware of the resources and were skillful enough with the command line, we wouldn't even need HTML. They can just curl
in their interactions with those resources :)
index
just makes it easier to work with collections. It is still a well defined resource and has a unique representation, for example /books
. How it is handled on the server side code does not make it RESTless
(I just made that up, but its awesome).
I'd start with chapter 5 of Roy Fielding's dissertation. There are a few basic principles:
- Resources: A resource could be typically something that you expose to the outside world as a part of your service. The emphasis is on identifying the resources (e.g: Book, UserList, CalculateDistance)
- URI: Give every resource an identifier (e.g: example.com/books/7654)
- Uniform interface: Use standard methods like GET, PUT. POST, DELETE, HEAD, OPTIONS
- Representations: A resource can have multiple representations. For example, a GET on a book can return a PDF of that book's content, a HTML of the content and for that matter even a GIF with the book cover and so on. A representation is essentially a collection of all the data and markup.
- Hypermedia: This one, in my opinion, is a very important principle. Implementation of this principle takes your application far ahead of the regular CRUD-like definitions the REST-style is boxed into. HATEOAS is the acronym which stands for Hypermedia as the engine of application state. When you click on a link or submit a form you are changing the state of the application, that's happening via hyperlinks (or hypermedia). There is very little coupling between a server and a client. A client navigates through the application via the links provided by the server. (there is a lot of discussion in the blogosphere on this priniciple ...) [Also look at Restfulie]
I have recently answered a question on good resources to learn REST, could be helpful.
I'm not familiar with Rails, so not addressing that part of the question.
Here is my basic outline of REST. I tried to demonstrate the thinking behind each of the components in a RESTful architecture so that understanding the concept is more intuitive. Hopefully this helps demystify REST for some people!
REST (Representational State Transfer) is a design architecture that outlines how networked resources (i.e. nodes that share information) are designed and addressed. In general, a RESTful architecture makes it so that the client (the requesting machine) and the server (the responding machine) can request to read, write, and update data without the client having to know how the server operates and the server can pass it back without needing to know anything about the client. Okay, cool...but how do we do this in practice?
The most obvious requirement is that there needs to be a universal language of some sort so that the server can tell the client what it is trying to do with the request and for the server to respond.
But to find any given resource and then tell the client where that resource lives, there needs to be a universal way of pointing at resources. This is where Universal Resource Identifiers (URIs) come in; they are basically unique addresses to find the resources.
But the REST architecture doesn’t end there! While the above fulfills the basic needs of what we want, we also want to have an architecture that supports high volume traffic since any given server usually handles responses from a number of clients. Thus, we don’t want to overwhelm the server by having it remember information about previous requests.
Therefore, we impose the restriction that each request-response pair between the client and the server is independent, meaning that the server doesn’t have to remember anything about previous requests (previous states of the client-server interaction) to respond to a new request. This means that we want our interactions to be stateless.
To further ease the strain on our server from redoing computations that have already been recently done for a given client, REST also allows caching. Basically, caching means to take a snapshot of the initial response provided to the client. If the client makes the same request again, the server can provide the client with the snapshot rather than redo all of the computations that were necessary to create the initial response. However, since it is a snapshot, if the snapshot has not expired--the server sets an expiration time in advance--and the response has been updated since the initial cache (i.e. the request would give a different answer than the cached response), the client will not see the updates until the cache expires (or the cache is cleared) and the response is rendered from scratch again.
The last thing that you’ll often here about RESTful architectures is that they are layered. We have actually already been implicitly discussing this requirement in our discussion of the interaction between the client and server. Basically, this means that each layer in our system interacts only with adjacent layers. So in our discussion, the client layer interacts with our server layer (and vice versa), but there might be other server layers that help the primary server process a request that the client does not directly communicate with. Rather, the server passes on the request as necessary.
Now, if all of this sounds familiar, then great. The Hypertext Transfer Protocol (HTTP), which defines the communication protocol via the World Wide Web is an implementation of the abstract notion of RESTful architecture (or an instance of the REST class if you're an OOP fanatic like me). In this implementation of REST, the client and server interact via GET, POST, PUT, DELETE, etc., which are part of the universal language and the resources can be pointed to using URLs.
As you might notice there are 4 HTTP actions but the basic CRUD operations in a typical web app require 7 different actions. Some of these don't actually do anything (like /new
and :id/edit
) and thus are sort of parallel to REST architecture. Also the index action does not act on the resource but rather on a collection of resource (thus also a unique url).
So the basic 4 HTTP actions map to a resource like this:
- GET maps to show ->
get /teams/:id
- PUT maps to update ->
put /teams/:id
- DELETE maps to destroy ->
delete /teams/:id
- POST is a bit of an exception, since the resource is not yet existant thus it maps to the base
/teams
So to summarize: each resource has its own unique url, plus rails defines a few additional urls for UI and collection purposes.
Like /teams -> for 'index' method...
/teams/new -> for 'new' method and so
on. Ain't this moving away from rest,
which defines that each resource has
one unique URI???
No this is not moving away from REST, because as far as REST is concerned /teams
and /teams/new
are two different resources.