Ruby (and Rails) nested module syntax

前端 未结 4 1847
梦如初夏
梦如初夏 2020-12-29 03:09

I\'m wondering what the difference is between the following two modules

# First Example
module Parent
  module Child
  end
end

and

相关标签:
4条回答
  • 2020-12-29 03:46

    Generally speaking, you don't want to define a module using the module Parent::Child syntax unless you can be absolutely certain that Parent is already there. A sub-Module can only be defined using the :: syntax if the parent module is defined. In your example, if you do the following, you will not get an uninitialized constant error.

    module Parent
    end
    
    module Parent::Child
    end
    
    0 讨论(0)
  • 2020-12-29 03:47

    It seems that Banister's answer is also the reason for this behaviour:

    ruby-1.9.2-p290 :001 > module A; module A; A.ancestors; end; end
     => [A::A] 
    ruby-1.9.2-p290 :002 > module A::A; A.ancestors; end
     => [A] 
    

    The inner module A is a constant inside the outer module A, and thus it's not visible using the second method.

    Editing my previous comment:

    This is explained in 7.9 "Constant Lookup" of "The Ruby Programming Language" (First Edition). The relevant part here is Module.nesting, which doesn't contain the outer module in the second example, thus A can only be found in the global scope.

    0 讨论(0)
  • 2020-12-29 04:01

    In the first example, it defines the Parent module and then the Child module. The second example, as you say yourself, must have the Parent module defined before hand. At the expense of one more line of code, you ensure that the module that you're nesting under by using your first example is always going to be defined.

    For a Rails example let's look into the railties/lib/rails/engine.rb file which re-opens the Rails module and then defines an Engine class inside of it. This could have been done with simply:

    class Rails::Engine
    

    But instead perhaps for the reasons stated above and perhaps also for clarity's sake, the module was defined first, then the class inside.

    0 讨论(0)
  • 2020-12-29 04:06

    I prefer the second method (if im sure that Parent is already defined) because it looks cleaner, esp. when the nesting is very deep.

    However the 1st method has some advantages, one not yet discussed is that a nested module gets access to any lexically available constants in the enclosing module.

    0 讨论(0)
提交回复
热议问题