2

This question is supposed to be the reverse of this one: Why use symbols as hash keys in Ruby?

As you can see, everyone agrees that symbols are the most logical choice for hash keys. However, I'm building a web application with the sinatra framework, and the request object is a hash that contains Strings as keys. Can anyone explain why this would be a design choice?

Community
  • 1
  • 1
MarioDS
  • 12,895
  • 15
  • 65
  • 121
  • 1
    Note that with Sinatra you can use [either a string or a symbol](http://stackoverflow.com/questions/8619707/accessing-sinatra-params-using-a-symbol). – Phrogz Apr 25 '13 at 17:27
  • 2
    "everyone agrees that symbols are the most logical choice for hash keys", no, they don't. It is a programmer's choice, sometimes based on herd-instinct, but more often based on what made the most sense at the time. Between strings and symbols, I use symbols usually, but I have also used regex patterns or even arrays as my keys, because it was expedient. A Hash is a container, just like an Array, and can contain all sorts of things. What we stick in there is up to us and should make sense for that application. If we're talking only about a parameter hash in Sinatra, then see @Phrogz answer. – the Tin Man Apr 25 '13 at 17:50

1 Answers1

4

Because the source of the keys--the query string--is made up of strings, so searching through this string for keys, it is most directly convenient to index the hash via the strings.

Every Symbol that is created in the Ruby runtime is allocated and never released. There is a theoretical (but unlikely) DOS attack available by sending hundreds of thousands of requests with unique query string parameters. If these were symbolized, each request would slowly grow the runtime memory pool.

Strings, on the other hand, may be garbage collected. Thousands of unique strings handled across various requests will eventually go away, with no long-term impact.

Edit: Note that with Sinatra, symbols are also available for accessing the params hash. However, this is done by creating a hash that is indexed by strings, and converting symbols (in your code) to strings when you make a request. Unless you do something like the following:

params.each{ |key,_| key.to_sym }

...you are not at risk of any symbol pseudo-DOS attack.

Phrogz
  • 296,393
  • 112
  • 651
  • 745
  • The `request` object holds much more than the query string. HTTP headers, for one. Since these are always the same, symbols would seem a more logical choice in terms of memory consumption. Also, Rack uses string keys everywhere. – MarioDS Apr 25 '13 at 17:20
  • you are confusing `params` with `request` I guess? – MarioDS Apr 25 '13 at 17:32
  • @MarioDeSchaepmeester Yes, sorry, I thought you were using the Sinatra `params` object. instead of the Rack `request`. – Phrogz Apr 25 '13 at 17:33
  • sorry for the confusion caused. I didn't know `request` belonged to Rack. This is only my first ruby project ever. – MarioDS Apr 25 '13 at 17:35