Question

I've run into a weird problem using hashes as a class variable. After I run the following code, I expect that the class variable @@class_hash should contain {:one => {'a' => 'one'}, :two => {'a' => 'two'}}.

However, after I run this code, @@class_hash is {:one => {'a' => 'two'}, :two => {'a' => 'two'}}.

Why is that?

class Klass
  @@class_hash = Hash.new({})

  def fun1
    @@class_hash[:one]['a'] = 'one'
  end

  def fun2
    @@class_hash[:two]['a'] = 'two'
  end

  def class_hash
    @@class_hash
  end
end

klass = Klass.new

klass.fun1
h1 = klass.class_hash
raise "h2[:one]['a'] should be 'one', not 'two'" if h1[:one]['a'] == 'two'
klass.fun2
h2 = klass.class_hash
raise "h2[:one]['a'] should be 'one', not 'two'" if h2[:one]['a'] == 'two'
Was it helpful?

Solution

The argument to Hash.new is used as the default value, in your case {}.

Every access to an unknown key uses that exact same object (ruby isn't magically duping it for you), so in your case the value for each key is the exact same hash. You can accomplish what I think you intended with the block form

Hash.new {|hash, key| hash[key] ={} }

In this case a different empty hash is used for each missing key.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top