Trans
7/22/2006 8:19:00 PM
Wes Gamble wrote:
> All,
>
> I have a Rails app where I load a YAML file into a class variable (in my
> application.rb file so it's available to all controllers), like so:
>
> @@config = YAML.load_file("#{RAILS_ROOT}/config/eSimplyConf.yml")
>
> and I created a method to give me back this hash:
>
> def config
> @@config
> end
>
> However, I notice that when I call config[:key_name], I don't get
> anything, but when I call config['key_name'] I do get the value. I
> further verified that if I called config[:key_name.to_s], I will get the
> value, thus underscoring the distinction between symbol and string here
> as the type of key_name.
>
> I was under the impression that symbols and strings were interchangeable
> for the purpose of addressing a hash element. Is this not the case? Is
> my problem that YAML.load_file generates keys that are strings instead
> of symbols, and of course, I'm using Rails, so that I expect all of my
> hash keys to be symbols :)?
As Ezra points out they are not the same in Ruby. A hash key can be any
object whatsoever. It could even be a number or another hash:
{ {:a=>1} => 'yep' }
Since symbols and strings are not the same thing, they likewise do not
represent the same keys. Versitle Ruby's hash is. Common it is not.
Lets be honest, 80% of the time, if not more we simply want a "keyword"
representation for out hash keys. Ruby's hash does not make that
straigiht foward and no doubt we've all spent too much time fusing with
to_s and to_sym in this regard.
I've offered some ideas for improvement in this area, symbol to string
coercion for instance. But that seems to be just as problematic. My
last consideration was a way to "normalize keys on the fly"
h = Hash.new.key_by{ |k| k.to_sym }
h["x"] = 1
h #=> {:x=>1}
I point out one last issue in this regard though, is that I have found
that I generally want my keys as symbols in code, but when I dump or
load YAML I want them as strings. Two extra time-consuming steps to do
this, so I end up just blowing wads of memory and sticking with
strings. :(
Anyhow sorry to ramble on. But I would be interested it what others
have thoughtof for dealing with this.
As a solution in your case you might be interested in what I often do,
use Facets OpenCascade. It can load simple YAML configs into a nice
method-based access object:
s = %{
---
a: "a"
b:
x: "x"
}
oc = OpenCascade.new( YAML.load(s) )
oc.a #=> "a"
oc.b.x #=> "x"
T.