af83

Ruby and module_function

Ruby provides various features to expose methods like class level methods, instance methods, inheritance, module and so on.

Today, we will talk about module_function which is a method defined on Module.

Let's consider this meaningful code:

module ICan
  def haz(value)
    puts "I can haz #{value}"
  end
  module_function :haz
end

module Ohai
  module_function

  def bye
    puts "kthxbai"
  end

  def hello
    puts "ohai"
  end
end

ICan.haz "pizza"
# => I can haz pizza
Ohai.hello
# => ohai
Ohai.bye
# => kthxbai

class Cat
  include ICan
  include Ohai

  def have_a_nice_day
    hello
    mouse
    bye
  end

  def mouse
    haz "mouse"
  end
end

Cat.new.tap do |cat|
  cat.have_a_nice_day
  # => ohai
  # => I can haz mouse
  # => kthxbai
  cat.haz "mouse"
  # => `block in <main>': private method `haz' called for #<Cat:0x007f8a0f3075f0> (NoMethodError)
end

When a method is defined in a Module, it can be used when this module is included. With module_function, it can still be used when the module is included, but it can also be used directly on the module.

With module_function, the method hello from the module Ohai can be called when the Ohai module is included, and directly Ohai.hello.

module_function provides the same semantics as protected and private: it can be called with or without a list of methods as arguments. If given a list of methods, only these ones will be exposed as module functions. Otherwise, all methods below the module_function keyword in the class definition will be exposed.

When a class includes module_function methods, these methods will be declared as private.

Some of Ruby's standard libraries use module_function. For instance FileUtils. This is really useful when a class makes a substantial use of methods provides by FileUtils.

blog comments powered by Disqus