All original content is created in Ukrainian. Not all content has been translated yet. Some posts may only be available in Ukrainian.Learn more

module_function in Ruby: When module methods are available as modular and as functions

Post cover: module_function in Ruby: When module methods are available as modular and as functions
Table of contentsClick link to navigate to the desired location
This content has been automatically translated from Ukrainian.
In Ruby, modules allow you to organize code, but sometimes you need the method to be available as for module instances, yes and directly from the module (as a function). Module_function is used for this.

How module_function works

  • Makes a method private for module instances (read about private here).
  • Adds also a "modular copy" of the method, which can be called without creating an object.
model MathHelper
  def square(x)
    x * x
  end

  module_function :square
end
Now you can call the method directly through the module:
MathHelper.square(5) # => 25
Or use it inside other module methods (as private):
model MathHelper
  def cube(x)
    square(x) * x
  end

  module_function :cube
end

MathHelper.cube(3) # => 27

Features

Private for module installations:
include MathHelper
square(5) # => NoMethodError (because square became private)
Suitable for utilities
module_function is often used in "static utilities", so as not to create a module object to call functions.
In short:
  • module_function makes the method at the same time:
    • Private for installations (via include)
    • Available as a function through the module
MathHelper.square(5) # works
include MathHelper
square(5) # error
This is convenient for modules that have a set of utilities, as in standard Ruby libraries (Math, Enumerable for example).
But if you pay attention to the point - private for installations (via include), so you can ask, what about extend and advance ( wrote about these methods here)? 
  • The module method becomes private for copies i available through the module itself.
  • Call through include does not work directly (method is private).
  • Call via extend works as a class method.
  • Call via prepend does not work on the object (method is private).
Still hard to understand? Let's take a closer look at:
module_function does two things at the same time:
  1. Private for copies
    • If you include a module (include) or do prepend, the method becomes private to all properties, meaning you can't call him just like that: obj.method -lt'll be a mistake.
    • Ruby does so so that you cannot accidentally call this method on an instance.
  2. Available through the module itself
    • Ruby creates a copy of the method at the module level.
    • Therefore, you can call: ModuleName.method - it works as a "static function".
Simple example:
module Utils
  def greet
    "Hello"
  end
  module_function :greet
end

# Through the module you can
Utils.greet # => "Hello"

# You can't do it through include — because it's private
include Utils
green # => error NoMethodError
  • Why does extend work?
    extend adds module methods in singleton class class or object. There, the method is called through a class/object, not an instance, that is works.
  • Why does prepend not work?
    prepend inserts the method into the ancestral chain, but the original method remains private -> an object cannot call it directly.

This post doesn't have any additions from the author yet.

28 Oct 14:42

How &:to_s works in Ruby and what Symbol#to_proc is

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
What are Proc and Lambda in Ruby?
28 Oct 15:57

What are Proc and Lambda in Ruby?

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
What happens if you call [1, 2, 3].map(&Person)
29 Oct 17:54

What happens if you call [1, 2, 3].map(&Person)

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
Singleton class (eigenclass) in Ruby: what it is and why it is needed
29 Oct 18:29

Singleton class (eigenclass) in Ruby: what it is and why it is needed

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
==, equal?, eql?, === in Ruby: what is checked and when to use
29 Oct 20:47

==, equal?, eql?, === in Ruby: what is checked and when to use

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
Include, Extend, Prepend in Ruby: how they work and what's the difference
29 Oct 21:20

Include, Extend, Prepend in Ruby: how they work and what's the difference

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
What is memoization in Ruby?
30 Oct 10:17

What is memoization in Ruby?

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
is_a?, kind_of?, instance_of? — how does Ruby check object type?
30 Oct 19:55

is_a?, kind_of?, instance_of? — how does Ruby check object type?

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
&& vs and — difference in Ruby that can break your code
30 Oct 20:23

&& vs and — difference in Ruby that can break your code

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
The variables in Ruby are @, @@ and class instance variable
30 Oct 20:54

The variables in Ruby are @, @@ and class instance variable

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
The difference between blank?, present?, empty? but nil? in Ruby
30 Oct 21:06

The difference between blank?, present?, empty? but nil? in Ruby

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
What Middleware is in Ruby on Rails and when it is used
04 Nov 10:39

What Middleware is in Ruby on Rails and when it is used

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska