Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing module methods with ::

Tags:

ruby

Documentation I've read tells me to use Module.method to access methods in a module. However, I can use Module::method as well. 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.
like image 923
Jonathan Avatar asked Feb 16 '12 16:02

Jonathan


People also ask

How do you access a module method in Ruby?

A user cannot access instance method directly with the use of the dot operator as he cannot make the instance of the module. To access the instance method defined inside the module, the user has to include the module inside a class and then use the class instance to access that method.

How do you call a method in a module?

The method definitions look similar, too: Module methods are defined just like class methods. As with class methods, you call a module method by preceding its name with the module's name and a period, and you reference a constant using the module name and two colons.

What is :: in Ruby?

The :: is a unary operator that allows: constants, instance methods and class methods defined within a class or module, to be accessed from anywhere outside the class or module.

How do I use modules in Ruby?

Creating Modules in Ruby To define a module, use the module keyword, give it a name and then finish with an end . The module name follows the same rules as class names. The name is a constant and should start with a capital letter. If the module is two words it should be camel case (e.g MyModule).


1 Answers

Constant resolution always requires that you use ::.

Method invocation is idiomatically and usually a period (.), but :: is also legal. This is not just true for so-called module methods, but for invoking any method on any object:

class Foo
  def bar
    puts "hi"
  end
end

Foo.new::bar
#=> hi

It's not so much "syntax sugar" as it is simply alternative syntax, such as the ability to write if or case statements with either a newline, then and newline, or just then.

It is specifically allowed because Ruby allows methods with the same name as a constant, and sometimes it makes sense to think that they are the same item:

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 commonly in Ruby in the Nokogiri library, which has (for example) the Nokogiri::XML module as well as the Nokogiri.XML method. When creating an XML document, many people choose to write

@doc = Nokogiri::XML( my_xml )

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

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 the same as a constant (Sequel::Model). The second line could also be written as

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

…but it doesn't look quite as nice.

like image 189
Phrogz Avatar answered Sep 26 '22 00:09

Phrogz