Ruby - Lexical scope vs Inheritance Ruby - Lexical scope vs Inheritance ruby ruby

Ruby - Lexical scope vs Inheritance


You can think of each appearance of module Something, class Something or def something as a “gateway” into a new scope. When Ruby is searching for the definition of a name that has been referenced it first looks in the current scope (the method, class or module), and if it isn’t found there it will go back through each containing “gateway” and search the scope there.

In your example the method baz is defined as

module Foo  class Bar    def baz      puts FOO    end  endend

So when trying to determine the value of FOO, first the class Bar is checked, and since Bar doesn’t contain a FOO the search moves up through the “class Bar gateway” into the Foo module which is the containing scope. Foo does contain a constant FOO (555) so this is the result you see.

The method glorf is defined as:

class Foo::Bar  def glorf    puts FOO  endend

Here the “gateway” is class Foo::Bar, so when FOO isn’t found inside Bar the “gateway” passes through the Foo module and straight into the top level, where there is another FOO (123) which is what is displayed.

Note how using class Foo::Bar creates a single “gateway”, skipping over the scope of Foo, but module Foo; class Bar ... opens two separate “gateways”


wow, great question. The best answer I can come up with is in this case you're using the module to define a namespace.

Check this out:

FOO = 123module Foo  FOO = 555endmodule Foo  class Bar    def baz      puts FOO    end    def glorf3      puts ::FOO    end  endendclass Foo::Bar  def glorf2    puts Foo::FOO  end  def glorf    puts FOO  endendputs Foo::Bar.new.baz    # -> 555puts Foo::Bar.new.glorf  # -> 123puts Foo::Bar.new.glorf2  # -> 555puts Foo::Bar.new.glorf3  # -> 123

So my thought is that when you define:

module Foo  FOO = 555end

you are creating FOO in the namespace of Foo. So when you use it here:

module Foo  class Bar    def baz      puts FOO    end  endend

you are in the Foo namespace. However, when you refer to it in:

class Foo::Bar  def glorf    puts FOO  endend

FOO is coming from the default namespace (as illustrated by ::FOO).


the first call:

puts Foo::Bar.new.baz    # -> 555

prints the result of invoking method baz of an instance of class Foo::Bar

notice that Foo::Bar#baz definition is actually a closure on FOO. Following ruby's scope rules:

  1. FOO is searched for in Foo::Bar (the class, not the instance) scope, it is not found,
  2. FOO is searched for in the enclosing scope Foo (because we are within the module definition) and it is found there (555)

the second call:

puts Foo::Bar.new.glorf  # -> 123

prints the result of invoking method glorf of an instance of class Foo::Bar

notice that Foo::Bar#glorf definition this time is also a closure on FOO, but if we follow ruby's scope rules you'll notice that the value closed upon this time is ::FOO (top level scope FOO) in the following way:

  1. FOO is searched for in Foo::Bar (the class, not the instance) namespace, it is not found
  2. FOO is searched in the enclosing scope ('top level') and it is found there (123)