31

Is there any difference between

module Foo class Engine < Rails::Engine end end 

and

module Foo class Engine < ::Rails::Engine end end 

2 Answers 2

52

Constants in Ruby are nested like files and directories in filesystem. So, constants are uniquely identified by their paths.

To draw an analogy with the file system:

::Rails::Engine #is an absolute path to the constant. # like /Rails/Engine in FS. Rails::Engine #is a path relative to the current tree level. # like ./Rails/Engine in FS. 

Here is the illustration of possible error:

module Foo # We may not know about this in real big apps module Rails class Engine end end class Engine1 < Rails::Engine end class Engine2 < ::Rails::Engine end end Foo::Engine1.superclass => Foo::Rails::Engine # not what we want Foo::Engine2.superclass => Rails::Engine # correct 
Sign up to request clarification or add additional context in comments.

4 Comments

Right. So if you were to call Rails::Engine from a module using the name Module Foo, it may interpret it as Foo::Rails::Engine. I've seen errors like this at times and had to add the additional :: in front of an include.
It was taken from the book "Metaprogramming Ruby" by Paolo Perrotta. Very useful book to deepen the knowledge of the Ruby.
Nice analogy. This becomes problematic when one has modules with the same name in different scopes, since Ruby seems to use the first/nearest one it can find.
A subtle point: if Rails::Engine is defined outside of Foo and it is also not defined inside Foo then Foo::Engine1.superclass will be Rails::Engine as desired.
5
Rails::Engine #is a path relative to the current tree level. # like ./Rails/Engine in FS. 

This is not quite true!

Let's have an example:

module M Y = 1 class M Y = 2 class M Y = 3 end class C Y = 4 puts M::Y end end end # => 3 module M Y = 1 class M Y = 2 class C Y = 4 puts M::Y end end end # => 2 module M Y = 1 class M Y = 2 class M Y = 4 puts M::Y end end end # => 4 

So when you say M::Y ruby looks up for the closest defintion no matter if it is inside the current scope or outer scope or outer outer scope etc.

1 Comment

which Ruby is this? On 2.2.4 I get 3, 3, and 4 and many "top level constant already referenced warnings"

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.