module_function

Last updated at

I often incorrectly use the module_function method in Ruby. This post will look into this method's source code to understand it, which basically does these things:

  1. Set module function methods to be private.
  2. For each module function methods:
    1. Copy it to be the module's public singleton method.

The semantic meaning of a module_function is a function, which should be stateless, like some mathematical functions.

Since they are functions, we are not likely to put it to the public in the object world. That's why they are private instance methods. Also they are copied (different) objects in singleton and in instances, so it is safe to change one without affect another.

There are two more scenes to be considered:

What if I want a global singleton object?

There are at least 2 ways to do the right thing. If it provides functions with nothing to do with any object system, or you just don't like the $ sign, you just create a constant name and define singleton methods in it:

module Graphics end
def Graphics.update() @_frame_count += 1 end
# or
class << Graphics
  def update() @_frame_count += 1 end
end

If it means a global state that you have to store it, you can use the real global variable syntax:

$game_system = Game_System.new

What if a helper module whose methods are always public?

extend self !

module Animatable
  extend self
  def update
    super if defined? super
  end
end

Bonus: what if patching the Object/String/Integer/... class?

Object.include, in old ruby versions (like in RGSS) this method is private, so you have to write Object.send :include,.

module DefWithExtension
  def def_with(...)
  end
  Object.include self
end