Navindra Umanee wrote:

>Why does the first one work but not the second one?
>  
>
As mathew said, def is just a command to define a method, it runs when 
the interpreter gets to that line. What makes the first one work and the 
second one not, however, is a matter of scope. When 'def' is called, it 
defines a method in a certain place. That place is determined by what 
'class' or 'module' it's in. So class Test; def foo; end end defines a 
method on Test objects.

#1: def moo; puts 'moo' end is *not inside a 'class' or 'module' block*. 
This is important. You may be defining a class method boo on Test (well, 
a singleton method on the Test object), but your @@class_variables won't 
actually be class variables of Test, because it's outside the class 
block. It's out in the wild. Here's what the PickAxe2 (p. 346) has to 
say about that:

"Outside a class or module definition, a definition with an unadorned 
method name is added as a private method to class Object, and hence may 
be called in any context without an explicit receiver."

So what's happening here?

Test.boo calls the Test.boo method you defined, which defines a private 
method moo on Object. The 'def' keyword, as you've seen returns nil. So 
Test.boo returns nil. Test.boo.moo tries to invoke the moo method on the 
nil object. Since nil.is_a? Object, it has the moo method that you just 
defined.

(I'm thinking the PickAxe may be wrong? about the private thing since 
you can call #moo with an explicit receiver -- sounds more like public. 
Can somebody explain?)

#2: When Test.boo is called, moo is defined as an instance method on 
Test. Test.boo returns nil, as before, but nil is not a Test object, so 
the moo method does not exist.

---

So... The best way to do what you actually want depends on what you 
actually want. Are you just trying to group a bunch of similar methods 
inside a subcomponent of Test, or do you want the Test.boo.moo method to 
be dynamically generated based on what Test.boo does? If the latter, 
then keep in mind that every method call returns an Object. What you 
want to do is make Test.boo return an Object that has a moo method on it.

Devin