[uf-rest] RESTifying RAILs
Dan Kubb
dan.kubb at autopilotmarketing.com
Fri Nov 4 13:12:51 PST 2005
Hi Ernie,
Q: Is RESTifying Rails OT for this list? Maybe it would be
better to move this to rest-discuss or the Rails list?
> My only concern is with your mechanism for handling other methods:
> That seems a bit verbose, not to mention non-backward-compatible.
> I'd prefer something like:
You're right, replacing the way rails dispatches to methods
in the core would probably not be a good idea. I was more
thinking along the lines of providing a way for us to
dynamically choose the exact method that was dispatched to
within a controller.
>> GET /person/123 -> Person.index
>> POST /person/123 -> Person.index_POST
>
> That is, the default is GET as usual, but one can suffix a method
> to indicate a special response. I also think using ALL CAPS is
> better to a) avoid collision with normal URIs and b) signal clearly
> that this is special. Though, is CAPS in a method name bad Ruby
> hygiene?
There's something about using CAPS in ruby method
names that offends my sense of aesthetics. ;)
For the dispatched-to method names I still prefer to use
the naming convention "verb_noun" since it tends to read
better For example I prefer delete_item ("Delete the Item"),
rather than item_delete ("Item Delete"). Methods in rails
seem to be named so that when read out loud they read
like a sentence.
To avoid collision with normal URIs you could mark the
method as protected or private. That would prevent
people from using links like /person/1234/delete_index.
Also to expand on your idea about calling Person.index on
GET: 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.
> Actually, there might be another way -- automatically insert the
> necessary JavaScript to synthesize the request from a form:
>
> http://jibbering.com/2002/4/httprequest.html
>
> If we're controlling the generated HTML anyway, why not solve it on
> the client-side? This is a browser limitation, so better to fix it
> there; and if from the designer's point of view it is zero-cost why
> not pretend to do the right thing?
I thought about using AJAX to solve this problem, but I'm
just not sure I'm ready to require javascript for all
the users of my system. I guess its a trade-off either
way.
Given the choice I'd prefer to use some sort of standardized
way of tunneling PUT/DELETE/etc over POST, and use AJAX
(when available) to issue real PUT and DELETE commands.
Then once the state of browsers has caught up, I can drop
both of these approaches.
>> anyway, so I figure I'll use a convention to do it.
>
> So, what convention to you use, exactly? Explicitly specifying a
> "put_index" URI?
No, there's no placing verbs inside the URI -- I think that's
a big no-no. URI's are forever, but the representation is
malleable, so thats where I decided to compromise. I'm using
a simple naming convention within the web form, like so:
<form method="post" action="/person/123">
<!-- ... some other fields containing attributes of the
person ... -->
<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 buried inside the controller example
I sent, but its pretty simple:
def tunneled_method
allowed_methods.find { |m| params['method_' + m] } || params
[:method]
end
The submit button parameter is searched for first, and if not
found the "method" parameter is used to set the form's default
method. This handles the case where a button is explicitly
pressed or when the user just hits the return key to submit
the form; and it also allows you to label the buttons any way
you wish.
The only case I haven't decided on how to best handle is when a
form is submitted to /person/, but the user clicked on a button
that should result in a DELETE on /person/123. I'm sure its just
a matter of coming up with a naming convention and then dispatching
to the correct controller/method.
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.
Yeah, I realize this is a hack, but it seems to work fine in
practice. Obviously I would prefer it if the HTML standards
supported methods other than GET and POST, and if nested forms
were allowed; but they aren't yet. I am of course open to
suggestions if there is a better way.
--
Thanks,
Dan Kubb
More information about the microformats-rest
mailing list