Access to module methods with ::

The documentation I read tells me to use Module.method to access the methods in the module. However, I can use the Module :: method. Is this syntactic sugar, or am I confused?

module Cat FURRY_LEVEL = 4 def self.sound %w{meow purr hiss zzzz}.sample end end puts Cat.sound # This works. puts Cat::sound # This also works. Why?! puts Cat.FURRY_LEVEL # Expected error occurs here. puts Cat::FURRY_LEVEL # This works. 
+7
source share
2 answers

Permanent permission always requires the use of :: .

The method call is idiomatic and usually a period ( . ), But :: also legal. This is not true for the so-called modular methods, but for calling any method for any object:

 class Foo def bar puts "hi" end end Foo.new::bar #=> hi 

This is not so much “syntactic sugar” as just an alternative syntax, for example, the ability to write if or case either with a new line, then new line, or simply then .

This is specifically allowed since Ruby allows methods with the same name as the constant, and sometimes it makes sense to think that they are the same element:

 class Foo class Bar attr_accessor :x def initialize( x ) self.x = x end end def self.Bar( size ) Foo::Bar.new( size ) end end p Foo::Bar #=> Foo::Bar (the class) p Foo::Bar(42) #=> #<Foo::Bar:0x2d54fc0 @x=42> (instance result from method call) 

You see this usually in Ruby in the Nokogiri library, which has (for example) Nokogiri::XML , as well as the Nokogiri.XML method. When creating an XML document, many people prefer to write

 @doc = Nokogiri::XML( my_xml ) 

You also see this in the Sequel library, where you can also write:

 class User < Sequel::Model # Simple class inheritance class User < Sequel::Model(DB[:regular_users]) # Set which table to use 

Again, we have a method (Sequel.Model) named just like a constant (Sequel :: Model) . The second line can also be written as

 class User < Sequel.Model(DB[:regular_users]) 

& hellip, but it doesn’t look so good.

+9
source

:: is called scope resolution operator , which is used to determine if scope defined by method, class or constant .

In the following example, we use :: to access the Base class, which is defined in the ActiveRecord module

 ActiveRecord::Base.connection_config # => {:pool=>5, :timeout=>5000, :database=>"db/development.sqlite3", :adapter=>"sqlite3"} 

We use :: to access the constants defined in the module

 > Cat::FURRY_LEVEL => 4 > Cat.FURRY_LEVEL => undefined method `FURRY_LEVEL' for Cat:Module (NoMethodError) 

The operator . used to call the module method (defined with self.) of the module.

Summary. Despite the fact that both :: and . perform the same task here, it is used for different purposes. You can read more here.

+5
source

All Articles