Michael Kovacs' photos More of Michael Kovacs' photos
Recommend Me Cable Car Software logo

Wednesday, December 28, 2005

Ruby on rails realities part one (The Hash and Symbol Situation)

I highlighted my very first experience with rails back in August and it was a quick evaluation to say the least. After digging in a little deeper and trying to create a "real" application I have a series of gotchas with regards to writing apps using RoR that I'll cover in a series of blog postings. I've been meaning to write about the use of symbols and hashes but after chatting on IRC yesterday with the author of this post, I decided to write something about the problems that I experienced as a nuby with symbols and hashes.

RoR makes use of hash objects to store and pass information in an application. Two major areas where
hashes are used are:

1) Sessions
2) HTTP Request params

In much of the example code in the "Agile Web Development with Rails" book the use of symbols as a key for storing information in a hash is quite prevalent. In fact it's deemed as something all the "cool" developers do (how's that for an oxymoron?).

In ruby a symbol looks like this:

This symbol may be used as a key for a hash like this:
session[:my_symbol] = 'some value to retrieve later'

The above code would commonly be used in a controller's action method or on a .rhtml template page (kinda like JSP, PHP pages)

A symbol is also commonly used when retrieving parameters from the incoming HTTP request, i.e.
value = params[:form_field_value]

Seems straightforward but unfortunately the use of symbols and strings for values and keys across rails isn't always consistent. If you look at pages 303 and 304 of the Agile book you'll see where the author lays out the various implicit
objects you get while inside of a rails controller. There he mentions that params and session are "hash-like" objects where you can store and retrieve data like described above. Further the author mentions in the params section that a symbol and string may be used interchangeably for the value of a key. i.e.

both refer to the same value in the hash.

Unfortunately with the amount of symbol usage in rails and a newbie not being perfectly clear on what they are and what's valid it's fairly easy to think that :foo and 'foo' are the same for all types of Hash objects. Well as you have no doubt guessed by now this is not the case. The params hash is a special kind of hash called a "HashWithIndifferentAccess". This differs from the CGI::Session hash (a plain old Hash) in which the keys :foo and 'foo' do NOT point to the same values.

It can be quite maddening to sit there wondering where your value is when you know you've stored it but because of the number of unknowns to you (language, framework, conventions, etc) it becomes harder to confidently know where to look and what things are a "given".

Of course after you've suffered the pain it's easy to know that this difference exists but when you're first starting out and you see the use of symbols and strings interspersed in code it's not easy to know the rules, especially when they're not consistent.

Another example of inconsistency where a symbol won't work, requiring the use of a string is when you specify the target action of a redirect
:redirect_to => 'my_action'
. This tells rails to redirect to an action in the current controller named "my_action". A symbol won't work for the target method name. I'm told that symbols are now or will soon be valid for target method names. Not sure if that's as of rails 1.0 or if it's forthcoming. So
:redirect_to => :my_action 
will now do the right thing and call the method represented by the symbol. The reason this is confusing is because there are other places in rails where a symbol may be used to represent a method to call (i.e. the various form helper methods where a symbol is used for the object handle and property method to call:
textfield :my_obj, :obj_prop

Granted in this example :obj_prop is never called but is used to create the name/id of the textfield that holds the data for @my_obj.obj_prop as shown below:
 < input id="my_obj_obj_prop" name="my_obj[obj_prop]" type="text" />

The point is that a symbol is being used to represent a method and it's confusing when you're starting out and don't know what these things really respresent.

So while conventions are a great thing I have a gripe about the difference between these two fundamental structures of webapp programming. I lost hours of productivity because of problems like this at the beginning and I think it's something that new users will get tripped up on due to inconsistencies in execution.

Hopefully this entry saves a newbie from having to learn this discrepancy the hard way. More rails realities to come...

This page is powered by Blogger. Isn't yours?