Wednesday, July 16, 2008

To quote a friend

I felt it would be a good idea to post a quote from my friend (who will remain nameless since I didn't ask his permission). We were talking about our lives and careers. Both of us are sort of in a peculiar transition point.

In his words:
"You need to go where you feel most comfortable and most needed."

Thanks for your wise words, nameless friend!

Tuesday, July 01, 2008

RESTful Rails: Passing URL Parameters

I've loving developing my web apps using RESTful design patterns. It is definately a concept shift. Rather than thinking of the URL as a way to embed programmatic calls, the URL becomes fairly static. All it does is represent the application's resources (aka our Models) and provide verbiage to modify them (POST, GET, PUT, DELETE). And that's it.

RESTful design in Rails is pretty straight forward when you only ever update data with forms, but what if you need to pass parameters via a URL? For example, let's say you want to put a link like "approve" on a page so that your HR manager can simply click a link to approve a job resume.

In old rails we could have created an action called "approve" in our resumes_controller and called that action using a URL with

http://www.website.com/resumes/approve/2.


But in RESTful development we should only be treating our URL's as resource representations, not as a way to make programmatic calls. Instead we should be calling our resume resource with a :put method.

http://www.website.com/resumes/2


Ok...yeah, we're updating the resume model, but how do we tell the app what we are specifically updating on that resource? We do this by passing parameters to that resource, in this case "status" as "approved". We would want the resulting URL to be


http://www.website.com/resumes/2?status=approved


But how do we embed these parameters RESTfully? The magic? Rails does this by accepting additional parameters via the application_path() option in our link_to tag. In this case we are going to pass the :id parameter as well as a parameter called :application which is a hash including our ":status" and "approved" parameters.

<%= link_to 'approve', application_path(:id => resume.id, :resume => {:status => "approved"}), :method => :put %>


application_path() is a rails helper that takes the options specified and generates a URL in a RESTful way. In this case it will create a URL representing the resume resource, add on the parameters we passed (:id and :status) then tack on the RESTful method, in this case 'put'.

In our resumes_controller, the update action (which corresponds to put) will be called and the resume model will be committed using the update_attributes(params[:resume]) method. update_attributes will update the model with all of the corresponding parameters, in this case "status."

Shazaam! Now isn't that clean?! No extra methods in our controllers, just the typical CRUD.

Remember, conceptually speaking we are not using our URL to make a programmatic call. RESTfully speaking we are simply 'putting' (or updating) the resource specified in our URL with the modified parameters.