rest/rails
Rails on REST Wish List
While nominally focused on specific feature requests to add to Rails, in fact many of these recommendations are also relevant for other frameowrks, and even general "REX".
REST-style URIs
That is, make the default URL style: http://host/base/table/id/style as in: http://localhost:3000/mydemo/person/113
for the default view, with an optional "/edit" on the end for, e.g., forms vs. a list.
This is subtly different than the current "table/action/id" which scaffolding generates. The central concept in REST is that every object (noun) should have a unique URI, and having an action inlined screws that up.
URL Suffix Proposal
Explicitly allow URL suffixes for alternate representations. Something like:
- http://host/base/person/1/@table
- return entity as a <table> row (XOXT)
<tr><th scope="col"><abbr title="fn">Full (Formatted) Name</abbr></td>...</tr> <tr id="person.1"><td class="fn">Ernie Prabhakar</td>...</tr>
- http://host/base/person/1/@ol
- return entity as an indexed list (XOXO)
<ol id="person.1" class="xoxo"> <li class="fn">Ernie Prabhakar</li> ... </ol>
- http://host/base/person/1/@dl
- return entity as a keyed dictionary (XOXO)
<dl id="person.1" class="xoxo" > <dt><abbr title="fn">Full Name:</abbr></dt><dd class="fn">Ernie Prabhakar</dd> ... </dl>
- http://host/base/person/1/@form
- return entity as a POSTable form
<dl id="person.1" class="xoxo" > <dt><label for="person.1.fn"><abbr title="fn">Full (Formatted) Name</abbr></label></dt> <dd><input class="fn" type="text" id="person.1.fn" value="Ernie Prabhakar"/></dd> ... </dl>
With presumably one of these as the default (no suffix) representation. The idea is to:
- extend REST to allow multiple server-side representations
- focus on structure ("form") not actions ("edit")
- make it easy to incorporate partials via AHAH with appropriate structure
- avoid the need to tweak data templates; use CSS to format the result instead
POST vs. GET
Right now, as far as I can tell, Rails doesn't differentiate results from a POST vs. results from a GET. Those are semantically different in REST, so I'd like [to know] a way to handle that cleanly. Dan Kubb suggests:
- What if the behavior for the RESTful dispatcher is to call Person.index ONLY if the corresponding Person.get_index wasn't available? Likewise for PUT requests, it would use Person.index only if Person.put_index wasn't available. I think that would be in-line with standard rails behavior.
PUT & DELETE
There should be a standard way to generate web pages that invoke all the HTTP verbs, even if modern browsers don't yet. The microformat for how this is handled today is probably something like:
<form method="post" action="/person/123"> <input type="hidden" name="method" value="put" /> <input type="submit" name="method_put" value="Save" /> <input type="submit" name="method_delete" value="Delete" /> </form>
The logic to dispatch is pretty simple:
def tunneled_method allowed_methods.find { |m| params['method_' + m] } || params[:method] end
A plus to using naming conventions within the form is that javascript could be written so that when the appropriate button is clicked a real PUT and DELETE can be done via AJAX.
XOXO-style templates
I'd like the default rhtml templates to be XOXO-compatible (e.g., dt/dd rather than <p>/<br>).
Columns as class names
In addition to 'human_readable' column names, I'd like there to be a parameter for the equivalent 'css-friendly' representation of those columns -- and for the default templates to include that.
Complete, functioning, customizable web application
I want to be able to do something like:
$ script/generate rex modelA modelB
And get a full-blown web application which includes:
- the front page, including navigation links to various model objects.
- search boxes
- entry forms
- AHAH (ajax) responses
- both list- and table- oriented model representations
The ideal is that I could use a combination of CSS and AHAH to generate the desired look, feel, and behavior of my website without actually having to touch existing HTML. As a bonus, I also want it complete enough that I can write a REST-spider to easily discover all the valid URIs and queries. Hey, a guy can dream...
XOXO instead of YAML for configuration
Okay, this last one is really nit-picky, and a little odd, but it would (IMHO) be more consistent. Right now, the config is the only non-HTML, non-Ruby file, and I at least had never seen YAML before so it looked out of place. Granted, using XHTML for config files is a little freaky at first, but when you think about it, its no worse than using custom XML tags (and way more interoperable). I'll even write the Ruby serializer myself if I have to...
OPTIONS Handling
The controller should be able to handle OPTIONS requests and know what specific methods it can handle for a given URI.
Output Content Negotiation
It would be nice to be able to have the view look at the Accept headers and choose the best template to output.
For example, imagine you had the following files:
- index.rhtml
- index.rxml
- index.rtxt
If the browser sent the Accept as text/html then the index.rhtml would be used. For text/plain the index.rtxt would be used, and so on.
If there was a way for a view handler to "register" itself and say what mime types it knows how to handle, then the optimal handler could be chosen at runtime. The handlers could do anything they want in order to output the response body, including using libraries like GD.
Input Content Negotiation
When a request has a body, it needs to be parsed and stored into the request parameters. Rails handles normal web forms and multi-part form input.. but it would be nice to be able to write custom handlers that knows how to parse requests for specific mime-types and set the appropriate request parameters inside rails.
This would allow you to POST a web form or a yaml string and have the values funneled into the same parameters -- your controller wouldn't care where the data is come from. I realize yaml is supported by rails natively, but it should be possible to register handlers for any other mime types.
Perl's Catalyst MVC is starting to do this with their HTTP::Body module.. they made it so you can write custom modules to parse any mime-types and set the request parameters.
HEAD responses
Responses to HEAD requests should be identical to GET requests, minus the body. Rails should omit sending the body for HEAD requests, but still send all the appropriate headers. Its especially important that the Content-Length be the same for HEAD and GET responses.
Conditional GET requests
When writing mod_perl handlers I was able to do something equivalent to:
def get_index # do some work to set up @resource set_etag @resource.digest_hash set_last_modified @resource.updated_at return not_modified if conditional_get? render end
This resulted in a snappier response from some apps since it didn't require a full transfer if it was not modified since my last request.
AJAX apps to use HTTP more fully
Most Rails AJAX apps use only GET and POST, but they should be encouraged to use the full set of HTTP verbs in examples.
Encouragement of Conditional GET in AJAX apps would be a bonus as well.
Implementations
See rest#Tools on the front page