There is no question that, in the right situation, Ruby on Rails is a great productivity multiplier. An anti-TDWTF, if you will. When used correctly, a highly-quality web site can be created with much great speed than more traditional coding methods.
Still, as Frederik was well aware, not every Ruby application is created equal. Frederik is a local Ruby expert and, as such, is frequently contacted by clients who were in just a little bit in over their head when it came to Rails. Much of Ruby's power comes from its use of convention over configuration. But just because there are reasonable defaults, does not mean that developers actually have to use them, right?
Such was the situation when Frederik ran into the following snippet of code at his current client.
# GET /users/unique/user_name?value=foo
# GET /users/unique/[email protected]
def unique
unless request.format == 'application/json'
head :unauthorized
return
end
status = if ["user_name", "email"].include?(params[:id].to_s)
User.exists?(params[:id] => params[:value]) ? 200 : 404
else
500
end
render :json => {}, :status => status
end
One thing to be aware of is that this snippet isn't a condemnation of Ruby. It's actually more about the misuse of convention. And HTTP status codes. And comments. And just about every other programming standard you can think of. Since many of you might be unfamiliar with the intricacies of Ruby, a brief explanation is in order.
First, pay no attention to the comments. While it might seem like they are an attempt to be useful, they are not. The correct paths, based on the code (and code is better documentation than comments anyway), are really /users/user_name/unique and /users/email/unique.
But drill into the code a bit more. The first block says that unless the MIME type of the request is 'application/json', then an HTTP status of 401 - Unauthorized is returned. But the last time Frederik checked (and it's still only a Google away), an invalid content-type header does not really qualified as 'unauthorized'. At least not based on 'convention'. A 400 - Bad Request is more appropriate.
As the next layer of the onion is peeled away, consider how the value of the status is determined. By convention (assuming the default Ruby routing), the id param is retrieved from the path of the request. If you request /users/user_name/unique?value=foo, the value of params[:id] would be 'user_name', while params[:value] would be 'foo'. This is why the comments are incorrect (and should never be trusted anyway).
Finally, if the path is incorrect (that is, it doesn't have user_name or email in it), then an HTTP 500 - Internal Server Error is returned. Except, of course, that it shouldn't be a 500 status code. HTTP 500 errors indicate a no more appropriate error code could be returned. And in this particular case, where the requested path is not found, an HTTP 404 - Not Found error is definitely more appropriate.
At least, that would be the convention.