So Module
can be used in Ruby to provide namespacing in addition to mixins, as so:
module SomeNamespace class Animal end end animal = SomeNamespace::Animal.new
But I've also seen the following used:
module SomeNamespace end class SomeNamespace::Animal end animal = SomeNamespace::Animal.new
My question is how they're different (if they are) and which is more idiomatic Ruby?
Namespace in Ruby allows multiple structures to be written using hierarchical manner. Thus, one can reuse the names within the single main namespace. The namespace in Ruby is defined by prefixing the keyword module in front of the namespace name. The name of namespaces and classes always start from a capital letter.
What is the difference between a class and a module? Modules are collections of methods and constants. They cannot generate instances. Classes may generate instances (objects), and have per-instance state (instance variables).
You can define and access instance variables within a module's instance methods, but you can't actually instantiate a module.
Ruby module is a collection of methods and constants. A module method may be instance method or module method. Instance methods are methods in a class when module is included. Module methods may be called without creating an encapsulating object while instance methods may not.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With