What's the difference between these Ruby namespace conventions?

后端 未结 2 1375
庸人自扰
庸人自扰 2020-12-12 19:40

So Module can be used in Ruby to provide namespacing in addition to mixins, as so:

module SomeNamespace
  class Animal

  end
end

animal = Some         


        
相关标签:
2条回答
  • 2020-12-12 19:46

    The difference lies in nesting.

    In the example below, you can see that the former method using class Foo, can get the outer scope's constant variables BAR_A without errors.

    Meanwhile, class Baz will bomb with an error of uninitialized constant A::B::Baz::BAR_A. As it doesn't bring in A::* implicitly, only A::B::*explicitly.

    module A
      BAR_A = 'Bar A!'
      module B
        BAR_B = 'Bar B!'
          class Foo
            p BAR_A
            p BAR_B
          end
      end
    end
    
    class A::B::Baz
      p BAR_A
      p BAR_B
    end
    

    Both behaviors have their place. There's no real consensus in the community in my opinion as to which is the One True Ruby Way (tm). I personally use the former, most of the time.

    0 讨论(0)
  • 2020-12-12 20:08

    The only difference between the two approaches is that the second one will throw uninitialized constant Object::SomeNamespace if the namespace hasn't previously been declared.

    When declared in a single file, I would opt for the first one because you don't have to repeat SomeNamespace.

    When using multiple files I also use the second one, to avoid running into the following problem:

    # in a.rb
    require 'b'
    
    module SomeNamespace
      def self.animal
        Animal.new
      end
    end
    
    # in b.rb
    class SomeNamespace::Animal
    
    end
    
    # irb
    require 'a' # explodes with the uninitialized constant error
    

    This example may be contrived, but it's easy to trigger it if your code base is a little bit bigger. I usually use the explicit way (your first one) to avoid this.

    One thing that may be helpful when using the second form is that it will detect typos in the namespace.

    There doesn't seem to be an established way to create namespaces, Devise for example mixes both approaches: first one, second one.

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