From: Stefano Crocco Date: 2009-06-19T23:33:16+09:00 Subject: Re: hash of hash? On Friday 19 June 2009, Jeroen Lodewijks wrote: > |hi, > | > |I am totally new to Ruby and am trying to code a hash of a hash. > |Somehow I always get a syntax error, but am unable to resolve it. > | > |This is what I have: > | > |File 1: > |class Hashhash > | def initialize > | @dt = { 2 => {2 => "H", 3 => "C"}, > | 3 => {2 => "H", 9 => "Dh"}, > | "T" => {2 => "C", 9 => "S"} > | } > | > | return @dt > | end > |end > | > |File 2: > |require 'Hashhash' > | > |ah = Hashhash.new > | > |out = ah["T"][9] > | > |p out > | > |I always get this error: > |test.rb:5: undefined method `[]' for # > |(NoMethodError) > | > |But when I try to code something in irb it works: > |irb(main):006:0* dt = { 2 => {2 => "H", 3 => "C"}} > |=> {2=>{2=>"H", 3=>"C"}} > |irb(main):007:0> puts dt[2][2] > |H > |=> nil > | > |What am I doing wrong?? > | > |Thanks in advance First of all, what you get is not a syntax error (which would have produced an error message like: syntax error, ....). The error you see is caused by calling a method on an object for which it isn't defined. The problem is that when you call the new method of a class (in your case, Hashhash.new), you don't get the value returned by initialize, but the object created by new. This means that ah doesn't contain a hash, but a Hashhash, which doesn't have a [] method. You have several options on how to do what you want. Depending on what exactly you need, I think the easiest ones are: * define an [] method for the Hashhash class. This way, the code you wrote will work exactly as you meant. Defining such a method is easy. Inside the definition of the Hashhash class, do: def [](key) @dt[key] end Calling this method will return the hash stored in @dt under key. Since this is a hash, you'll be able to retrieve the value corresponding to the key 2 * define a method for the Hashhash class which returns the instance variable @dt and use that to access the elements. To define a method which only returns the value of an instance variable, you can use the attr_reader class method: class Hashhash attr_reader :dt def initialize ... end end Then, you can write ha = Hashhash.new ha.dt[2][2] * Do not use the Hashhash class and use a simple hash of hashes: ah = { 2 => {2 => "H", 3 => "C"}, 3 => {2 => "H", 9 => "Dh"}, "T" => {2 => "C", 9 => "S"} } ah[2][2] As for the reason it works in irb... well, from what you show us, you aren't using the same code you used in the script. At least, in this case dt isn't an instance variable (since it doesn't start with @). I hope this helps Stefano