In Ruby, Modules are a way of grouping together methods, classes, and constants giving you two major benefits:
- provide namespacing and thus help prevent name collisions
- implement the mixin facility, providing a controlled way of adding functionality to classes
A module can also be used as a logical entity, containing non-state changing methods ("functions") that may be called, not only from the instance level but also from class level, with the module itself as the receiver and not having to prepend the module every time you want to use the functions.
# class level MyModule.some_method # instance level include MyModule some_method
There are multiple techniques to achieve this in Ruby, but the simplest and best known are
creates module functions.
You can achieve this by:
module MyModule def some_method puts "MyModule#some_method" end module_function :some_method end
This is very similar to writing:
module MyModule def self.some_method "MyModule#some_method" end private def some_method "MyModule#some_method" end end
This could also be written as the following if you want all the subsequently defined methods to become module functions:
module MyModule module_function def some_method "MyModule#some_method" end end
The instance methods are made private:
MyModule.instance_method(:some_method).owner #=> MyModule MyModule.public_method_defined?(:some_method) #=> false MyModule.private_method_defined?(:some_method) #=> true MyModule.method(:some_method).owner #=> #<Class:MyModule> MyModule.method(:some_method).owner.singleton_class? #=> true
These functions are copies of the original, and so maybe changed independently:
class MyClass include MyModule def call_some_method some_method end end MyModule.some_method #=> "MyModule#some_method" klass = MyClass.new klass.call_some_method #=> "MyModule#some_method" module MyModule def some_method "Overridden MyModule#some_method" end end MyModule.some_method #=> "MyModule#some_method" klass.call_some_method #=> "Overridden MyModule#some_method"
The advantage of
is that when the module gets included in a class, these functions do not become public methods of the class and do not extend the class's public API, eliminating the need to maintain these methods for backward compatibility.
Another way to get something very similar is by
. By extending
within the module, all instance methods defined within the module will now be available at the module level and can also be called
module MyModule extend self def some_method "MyModule#some_method" end end
, the module will add its instance methods to its inheritance chain.
MyModule.instance_method(:some_method).owner #=> MyModule MyModule.public_method_defined?(:some_method) #=> true MyModule.method(:some_method).owner #=> MyModule MyModule.method(:some_method).owner.singleton_class? #=> false
makes the given instance methods private, then duplicates and puts them into the module's metaclass as public methods.
- creating copies of the original methods and they may be managed independently
- making the module instance methods visibility as private
On the other hand,
adds all instance methods to the module's singleton, leaving their visibilities unchanged.
- there is no method copies made, if you want to modify a method's behavior you only need to do this in one place
- no side effects, like changing the method's visibility