- 3.1 REST in a Rather Small Nutshell
- 3.2 Resources and Representations
- 3.3 REST in Rails
- 3.4 Routing and CRUD
- 3.5 The Standard RESTful Controller Actions
- 3.6 Singular Resource Routes
- 3.7 Nested Resources
- 3.8 RESTful Route Customizations
- 3.9 Controller-Only Resources
- 3.10 Different Representations of Resources
- 3.11 The RESTful Rails Action Set
- 3.12 Conclusion
3.10 Different Representations of Resources
One of the precepts of REST is that the components in a REST-based system exchange representations of resources. The distinction between resources and their representations is vital.
As a client or consumer of REST services, you don't actually retrieve a resource from a server; you retrieve representations of that resource. You also provide representations: A form submission, for example, sends the server a representation of a resource, together with a request—for example, PUT—that this representation be used as the basis for updating the resource. Representations are the exchange currency of resource management.
3.10.1 The respond_to Method
The ability to return different representations in RESTful Rails practice is based on the respond_to method in the controller, which, as you've seen in the previous chapter, allows you to return different responses depending on what the client wants. Moreover, when you create resource routes you automatically get URL recognition for URLs ending with a dot and a :format parameter.
For example, assume that you have resources :auctions in your routes file and some respond_to logic in the AuctionsController like
def index @auctions = Auction.all respond_to do |format| format.html format.xml { render :xml => @auctions } end end
which will let you to connect to this URL: /auctions.xml
The resource routing will ensure that the index action gets executed. It will also recognize the .xml at the end of the route and interact with respond_to accordingly, returning the XML representation.
There is also a more concise way of handling this now using the respond_with method.
class AuctionsController < ApplicationController respond_to :html, :xml, :json def index @auctions = Auction.all respond_with(@auctions) end end
Here we've told our controller to respond to html, xml, and json so that each action will automatically return the appropriate content. When the request comes in, the responder would attempt to do the following given a .json extension on the URL:
- Attempt to render the associated view with a .json extension.
- If no view exists, call to_json on the object passed to responds_with.
- If the object does not respond to to_json, call to_format on it.
For nested and namespaced resources, simply pass all the objects to the respond_to method similar to the way you would generate a route.
respond_with(@user, :managed, @client)
Of course, all of this is URL recognition. What if you want to generate a URL ending in .xml?
3.10.2 Formatted Named Routes
Let's say you want a link to the XML representation of a resource. You can achieve it by passing an extra argument to the RESTful named route:
link_to "XML version of this auction", auction_path(@auction, :xml)
This will generate the following HTML:
<a href="/auctions/1.xml">XML version of this auction</a>
When followed, this link will trigger the XML clause of the respond_to block in the show action of the auctions controller. The resulting XML may not look like much in a browser, but the named route is there if you want it.
The circuit is now complete: You can generate URLs that point to a specific response type, and you can honor requests for different types by using respond_to. All told, the routing system and the resource-routing facilities built on top of it give you quite a set of powerful, concise tools for differentiating among requests and, therefore, being able to serve up different representations.