I’m learning Ruby right now for the Rhodes mobile application framework and came across this problem: Rhodes’ HTTP client parses JSON responses into Ruby data structures, e.g.
puts @params # prints {"body"=>{"results"=>[]}}
Since the key “body” is a string here, my first attempt @params[:body] failed (is nil) and instead it must be @params['body']. I find this most unfortunate.
Can somebody explain the rationale why strings and symbols have different hashes, i.e. :body.hash != 'body'.hash in this case?
Symbols and strings serve two different purposes.
Strings are your good old familiar friends: mutable and garbage-collectable. Every time you use a string literal or
#to_smethod, a new string is created. You use strings to build HTML markup, output text to screen and whatnot.Symbols, on the other hand, are different. Each symbol exists only in one instance and it exists always (i.e, it is not garbage-collected). Because of that you should make new symbols very carefully (
String#to_symand:''literal). These properties make them a good candidate for naming things. For example, it’s idiomatic to use symbols in macros likeattr_reader :foo.If you got your hash from an external source (you deserialized a JSON response, for example) and you want to use symbols to access its elements, then you can either use HashWithIndifferentAccess (as others pointed out), or call helper methods from ActiveSupport:
Note that it’ll only touch top level and will not go into child hashes.