What is Ruby's double-colon `::`?
::
is basically a namespace resolution operator. It allows you to access items in modules, or class-level items in classes. For example, say you had this setup:
module SomeModule
module InnerModule
class MyClass
CONSTANT = 4
end
end
end
You could access CONSTANT
from outside the module as SomeModule::InnerModule::MyClass::CONSTANT
.
It doesn't affect instance methods defined on a class, since you access those with a different syntax (the dot .
).
Relevant note: If you want to go back to the top-level namespace, do this: ::SomeModule – Benjamin Oakes
difference between dot(.) and double colon (::) in accessing class method
The double colon ::
namespace operator can also be used as a message sending operator. In other words,
foo.bar
can also be written as
foo::bar
Except when not.
In particular, .
is always a message send. ::
is usually a namespace lookup, except when it cannot possibly be. That means, for example, you cannot call a message that starts with an uppercase character, unless you also pass an argument list.
foo = Class.new do
def BAR; :method end
BAR = :constant
end
foo.BAR #=> :method
foo::BAR #=> :constant
foo::BAR() #=> :method
The fact that ::
can also be used for message sends is a historical curiosity, and is banned in most style guides except for "class factories", i.e. methods that return classes. Imagine a web framework that is set up like this:
module Controller
def self.R(path)
Class.new(AbstractController) do
# a bunch of methods for dealing with routing to `path`
end
end
end
class IndexController < Controller::R '/index.html'
def get
render 'Welcome'
end
end
In this case, in some style guides, it would be acceptable to write Controller::R
because even though R
is a method, it returns a class, so it kind-of acts like one.
But this is a special case for certain DSLs and is only allowed in certain style guides. Most style guides disallow ::
for message sends, because it is redundant with .
, because it already has a another different meaning (namespace resolution), and because it doesn't behave like .
in all cases.
What is the difference in accessing class method using dot(.) and a double colon (::) operator then?
On the one hand, you can say, there is no difference because when used as the message sending operator, they both do the exact same thing.
On the other hand, there is a difference in syntax, namely that foo::BAR
isn't a message send, it is a namespace lookup which is completely different. from foo.BAR
, which is a message send.
Ruby's double colon (::) operator usage differences
Constants in Ruby are nested like files and directories in filesystem. So, constants are uniquely identified by their paths.
To draw an analogy with the file system:
::Rails::Engine #is an absolute path to the constant.
# like /Rails/Engine in FS.
Rails::Engine #is a path relative to the current tree level.
# like ./Rails/Engine in FS.
Here is the illustration of possible error:
module Foo
# We may not know about this in real big apps
module Rails
class Engine
end
end
class Engine1 < Rails::Engine
end
class Engine2 < ::Rails::Engine
end
end
Foo::Engine1.superclass
=> Foo::Rails::Engine # not what we want
Foo::Engine2.superclass
=> Rails::Engine # correct
Idiomatic use of double-colon (double-column, or ::) syntax for Ruby methods
Would it be non-idiomatic for me to avoid ever using the
::
operator for qualifying the names of anything but classes, modules, and constants and, instead, consistently to use only dot syntax for all methods (class methods, module methods, and instance methods)?
No, it would in fact be idiomatic. Nobody ever uses ::
to call methods, ever. Period.
The only time ::
is used in conjunction with methods is when talking about methods. In that case, Foo#bar
is used to talk about instance methods (i.e. a method bar
that can be called on instances of Foo
like foo.bar
) and Foo::bar
is used to talk about singleton methods (i.e. a method bar
that can be called on Foo
itself like Foo.bar
). However, we only use ::
for talking about methods, never for calling them.
Some notes:
- Technically speaking, there are no class methods or module methods in Ruby. Every object can have methods defined only for itself (so-called singleton methods), and since classes and modules are also objects, they can also have singleton methods. So, we will sometimes talk about "class methods" or "module functions", but in reality, those are just singleton methods.
- Well … actually, I lied. Sorry. Singleton methods don't exist either. They are really just normal instance methods of the singleton class of the object. But saying "instance method of the singleton class of the object" is a mouthful, so we just say "singleton method of the object", and likewise instead of "instance method of the class object's singleton class", we say just "class method". However, we only say this in the knowledge that those things actually don't really exist, and especially when talking to newbies, I prefer to use the long form instead of the short-form jargon.
::
is used to dereference constants inside modules. The fact that those constants often point to modules or classes is not significant. Here is an example of resolving a constant which doesn't point to a module or class inside a module that isn't referenced by constant:module Foo; BAR = 42 end
foo = Foo
foo::BAR # => 42
# ^ ^------------ not a module
# |
# +---------------- not a constant
What does a double colon do inside a module?
It's a scope modifier. Prefixing your constant (Tag
) with a double colon ensures that you're looking in the root/global namespace instead of within your current module.
E.g.
module Foo
class Bar
def self.greet
"Hello from the Foo::Bar class"
end
end
class Baz
def self.scope_test
Bar.greet # Resolves to the Bar class within the Foo module.
::Bar.greet # Resolves to the global Bar class.
end
end
end
class Bar
def self.greet
"Hello from the Bar class"
end
end
The prepending is usually not neccessary as Ruby automatically looks in the global namespace, if it fails to find the referenced constant in the local module. So if no Bar
existed in the Foo module, then Bar.greet
and ::Bar.greet
would do the exact same thing.
. vs :: (dot vs. double-colon) for calling a method
It's the scope resolution operator.
An example from Wikipedia:
module Example
Version = 1.0
class << self # We are accessing the module's singleton class
def hello(who = "world")
"Hello #{who}"
end
end
end #/Example
Example::hello # => "Hello world"
Example.hello "hacker" # => "Hello hacker"
Example::Version # => 1.0
Example.Version # NoMethodError
# This illustrates the difference between the message (.) operator and the scope
# operator in Ruby (::).
# We can use both ::hello and .hello, because hello is a part of Example's scope
# and because Example responds to the message hello.
#
# We can't do the same with ::Version and .Version, because Version is within the
# scope of Example, but Example can't respond to the message Version, since there
# is no method to respond with.
Double colons before class names in Ruby?
It means that you're referring to the constant File
from the toplevel namespace. This makes sense in situations like this:
class MyClass #1
end
module MyNameSpace
class MyClass #2
end
def foo # Creates an instance of MyClass #1
::MyClass.new # If I left out the ::, it would refer to
# MyNameSpace::MyClass instead.
end
end
Related Topics
How to Reload the Current Page in Ruby on Rails
How to Uninstall Ruby Installed by Ruby-Install
Error: While Executing Gem ... (Gem::Filepermissionerror)
Validation for Non-Negative Integers and Decimal Values
Regex for Checking the Last Character
Rails Activerecord Perform Group, Sum and Count in One Query
How to Convert a Bigdecimal to a 2-Decimal-Place String
Check If a String Contains Only Digits in Ruby
How to Calculate Number of Chars Common to Two Strings
Case Statement With Multiple Values in Each 'When' Block
Difference Between Require_Relative and Require in Ruby
Pg::Connectionbad - Could Not Connect to Server: Connection Refused
How to Get Source Code of a Method Dynamically and Also Which File Is This Method Locate In
Why Does String Interpolation Work in Ruby When There Are No Curly Braces