Simply RESTful… "The missing action"

UPDATE 15/03/10: The debate continues…

The ideas in this article came about whilst I was test-driving the Simply RESTful plugin following DHH’s RailsConf keynote on the subject.

The philosophy

The first thing I came across whilst experimenting with Simply RESTful (which is great by the way), was that there is no real way of deleting items with javascript disabled. Since I am currently working on a project that needs to function on a variety of mobile devices, this instantly caused me concern.

I could think of a few ways to hack around this limitation, however I was sure there had to be a better way, hence this article. I wanted to keep the current javascript functionality but in addition have a clean non-javascript fallback.

Consider the following:

CRUD Form (GET request) POST action
(C)reate /products/new create
(R)ead /products/24 n/a
(U)pdate /products/24/edit update
(D)elete destroy

There are three “state changing” actions in CRUD, they are the ‘create’, ‘update’ and ‘delete’. You will notice from the table above that all three have a POST action1, however only two have GET actions… why is this?

Now, you see that dash in the second column… that’s “the missing action”. There is no good reason why our ‘destroy’ action shouldn’t have a corresponding form action (GET request) also. Let me explain myself…

1 The HTTP actions are PUT, POST and DELETE, however in this implementation (due to the limitations of HTML) they are all technically POST’s.

Putting it into practice

So we give ‘destroy’ it’s missing action which will act as a confirmation of our post… and what shall we call this missing action? …why let’s call it delete.

If we fill in this missing piece in our RESTful Rails puzzle, all becomes clear:

CRUD Form (GET request) POST action
(C)reate /products/new create
(R)ead /products/24 n/a
(U)pdate /products/24/edit update
(D)elete /products/24/delete destroy

Our routes would look something like:

map.resource :product, :member => { :delete => :get }</pre>
In our controller would be:
<pre lang="ruby">def delete
  @product = Product.find(params[:id])
end
def destroy
  Product.find(params[:id]).destroy if request.delete?
  redirect_to product_url
end

Our delete.rhtml would look like this:
<pre><h1>Are you sure you wish to delete ?</h1></pre>

Slight complication…

Update (13 Oct 2007): This has been fixed in more recent versions or Rails.

Now comes the slight complication… we want the javascript POST to /projects/24 to function as normal, however if javascript is disabled we want to request /projects/24;delete.

Wouldn’t it be nice if you could specify a fallback (non-javascript) href in the link_to helper, something that I’ve pondered with on many occasions. Unfortunately the link_to helper doesn’t let you override the href attribute (currently it adds a second one instead), until now.

Enter iq_noscript_friendly plugin which fixes this shortfall (I also have this as a Rails patch however the ticketing system on Trac is currently broken).

Install the plugin using:

./script/plugin install http://svn.soniciq.com/public/rails/plugins/iq_noscript_friendly/

In our listing view (index.rhtml) we are now able to do the following:

link_to 'Delete', product_url(product),
          :confirm => 'Are you sure?',
          :method => 'delete',
          :href => delete_product_url(product)

Ideally you would just give the link a class of “delete” and use unobtrusive javascript to make it do the delete request.

Beautiful.

Summary

By adding “the missing action”, we are able to POST as usual (using javascript) to ‘destroy’ but gracefully fallback to our ‘delete’ form when javascript is not available. Besides, why shouldn’t ‘destroy’ get it’s own form action… ‘create’ has ‘new’ and ‘update’ has ‘edit’?

Now to make this whole thing even better, lets make it part of the convention. ‘delete’ should default to GET and therefore negate the need for :member => { :delete => :get } in our routes.rb… DHH?

I would love to hear peoples comments on this technique as I’m using it for everything now and it works a treat.

Com’on… use “the missing action”, be kind to those without javascript, and lets make it the convention!

Rock on RESTfulness.

Finally running on the latest Typo (4.0)

I’ve been putting off upgrading Typo for a while now (due to lack of time). This blog is now running on -3.99.4- 4.0 (missed the update by 2 hours!).
I have added a temporary fix to “TheLucid Typo theme”:/typo_themes/lucid.zip however keep a lookout for the new version coming soon as promised.
Please reply to this post with any features you would like to see in the next theme release.

Code beauty vs. Obsession

h3. When does the search for beautiful code become an obsession?
Rightly so, “David Heinemeier Hansson”:http://www.loudthinking.com/arc/000419.html constantly pushes for beautiful code, however this in now becoming an obsession for me and I may soon need professional help…
You know things are getting bad when you do something similar to the following:

thing = {
  :store_dir => "public/master",
  :scaled_dir => "public/variants",
  :tmp_dir => "public/temp"
}

And then _have_ to change it so that the symbol names are the same length!!:

thing = {
  :storage_dir => "public/master",
  :variant_dir => "public/variants",
  :tmp_img_dir => "public/temp"
}

I am finding myself becoming more and more obsessional about stuff like this.
* Where is the threshold?
* When does code beauty become an obsession?
If anyone else is suffering from this terrible disorder, please post here, I need support to get through this 😉

Here comes 2006…

With 2006 on the horizon there are so many things that I have still yet to accomplish.
This is not a new years resolution list, more of a reminder to myself as to what I want to get out of the new year.
h3. Moving premises
Something that is sure to help with a fresh start is the fact that “SonicIQ”:http://www.soniciq.com is moving premises on the 1st of Feb. Initial chaos no doubt what with phone lines being transfered etc. but still, a change of location is always good for a bit of variety.
h3. Aims for the new year
* Get the sodding “SonicIQ”:http://www.soniciq.com site live. Four to five years of trading and still only a holding page due to the constant workload.
* Make more time for personal projects, ideas that have been floating around in my head for years and not seen the light of day.
* Take the stress out of work and actually start enjoying it again. With so much to do and not enough time you tend to loose focus on why your actually running a business in the first place.
* Decorate the flat! – Had my flat for three years and still not finished decorating… that’s just silly.
* Have a cracking summer and *go to the beach*. Living five minutes walk from the beach and visiting it once in 2005 is again just silly…
* Make the most of free time. I tend to wear myself down with work that any free time I get is spent lounging around, sleeping and/or stressing about deadlines.
I’m sure I could keep this list going for ever, so I’ll stop now. Hopefully this _will_ act as a reminder to myself to at least act on a couple of these points.
So here is to a prosperous 2006… bring it on, I’m ready this time.

Lucid theme gets a polish… ish..

h3. A few amends to the lucid theme:
* I’ve added a little colour scheme switcher (purely for the purposes of demonstrating the theme with different colours).
* I have added a minty scheme as requested by “Thomas Aylott”:http://subtlegradient.com. Also there is a bleached version, which is basically the theme stripped of most images and colour.
* There is now a transparent search panel which slides down with the results.
Please note that the colour picker is experimental and is only intended to show the theme with different schemes. When the comp. is finished, I will release the schemes separately.
h3. Todo
* Comment styling.
* Cookie getting and setting for fixed/fluid layouts.
* General tidy up.
Time is once again an issue, feel free to make suggestions and I will try to incorporate them as and when I get the time.
p.s. try viewing the theme with images off.

Typo theme contest entry

Well, what can I say. I managed to submit my theme just in time (in it’s current state) however it’s far from finished 🙁 …too much work, not enough play.
Theme is tested in Safari, Firefox and IE6 Win (currently a small issue with IE5.5).
h3. Main features
* Safari search field (and a mimicked version for other browsers).
* A little calendar icon next to each post.
* Lightweight design i.e. divs and images kept to a minimum (although there are few extra divs for fluid).
* Fixed and Fluid designs (a couple of people beat me to it on this one).
* Ruby red colour scheme to depict Typo’s origins.
I had a shed load of features that should have made it into the entry, just didn’t leave myself enough time.
I also had bleached and mint versions of the same theme in the pipeline which looked 100 times better however I ran out of time. These obviously won’t make it into the comp however if anyone is interested, let me know.
h3. What have I leaned from this?
Rounded corners ==+== fluid layout ==+== hatching + vertical gradient= absolute nightmare!! Why? …two words “Internet Explorer”.
I generally don’t like using extra markup for layout however it is necessary for fluid + rounded corner layouts. That I can like with, it’s the fact that 80% of the time spent on this theme was used on workarounds for IE and it’s lack of proper transparent png support.