extend and Module Functions

Published by Programming Line in Ruby. Last updated .

You already know that include mixes a module’s methods into every instance of a class. But sometimes you don’t want every instance to gain new behavior — you want just one specific object to gain it, or you want a module’s methods to behave like utility functions you call directly on the module itself (think Math.sqrt(9)). That’s exactly what extend and module_function are for. Together they let you attach behavior at a much more precise level than include allows: to a single object, to a class itself, or to a module acting as its own namespace.

Overview: How extend and module_function work

Every object in Ruby — and remember, in Ruby everything is an object, including classes themselves — has a hidden, one-off class that sits directly above it in the method lookup chain. This is called the object’s singleton class (sometimes the eigenclass). It exists specifically to hold methods that belong to that one object and no other. When you write obj.extend(SomeModule), Ruby inserts SomeModule into obj‘s singleton class, exactly as if you had written class << obj; include SomeModule; end. The methods become available on obj immediately, but no other instance of obj‘s class is affected at all.

Because classes are themselves objects (instances of Class), this same trick works on a class. class Foo; extend SomeModule; end inserts SomeModule into Foo‘s singleton class — and a class’s singleton class is precisely the chain Ruby searches when you call a method directly on the class, i.e. a "class method". This is why extend is a clean, idiomatic way to add class-level methods from a module, without resorting to the classic self.included hook and a nested ClassMethods module.

module_function solves a different but related problem: building a module that behaves like a self-contained toolbox, callable directly on the module (like Math.sqrt or Math.hypot) rather than mixed into some other class. Called with no arguments inside a module body, module_function changes the behavior of every method defined below it: each one becomes a singleton method on the module itself (so you can call MyModule.some_method) and its original instance-method version is made private. You can also call it with one or more method names (as symbols or strings) to convert specific, already-defined methods instead of "everything from here down".

There is a close cousin worth knowing: extend self, written inside a module body. It achieves a similar practical result — the module’s own methods become callable on the module — but it does so by extending the module with itself, so the methods stay public if they were already public. Many modern Ruby style guides prefer extend self over module_function for exactly this reason: it doesn’t silently make your instance methods private.

Syntax

object.extend(ModuleName)

class SomeClass
  extend ModuleName
end

module SomeModule
  module_function

  def helper
    # becomes SomeModule.helper, and a private instance method
  end
end

module AnotherModule
  extend self

  def helper
    # becomes AnotherModule.helper, and stays a public instance method
  end
end
Form What it does
object.extend(Mod) Mixes Mod‘s instance methods into just this one object’s singleton class.
extend Mod inside a class body Mixes Mod‘s instance methods into the class’s singleton class, i.e. adds them as class methods.
module_function (bare) Every method defined afterward becomes callable on the module itself, and is demoted to a private instance method.
module_function :name Converts one already-defined method by name instead of everything below the call.
extend self Alternative to module_function that keeps the methods public if they were already public.

Examples

Example 1: extend on a single object

module Greetable
  def greet
    "Hello, I'm #{name}!"
  end
end

class Person
  attr_reader :name

  def initialize(name)
    @name = name
  end
end

alice = Person.new("Alice")
bob = Person.new("Bob")

alice.extend(Greetable)

puts alice.greet
puts bob.respond_to?(:greet)

Output:

Hello, I'm Alice!
false

alice.extend(Greetable) drops Greetable into alice‘s singleton class only. Calling alice.greet works because Ruby’s method lookup checks the singleton class before Person. bob was never extended, so bob.respond_to?(:greet) is false — Person the class was never touched.

Example 2: extend on a class itself

module Describable
  def describe
    "This is the #{name} class."
  end
end

class Robot
  extend Describable
end

puts Robot.describe

Output:

This is the Robot class.

Since Robot is itself an object (an instance of Class), extend Describable inserts Describable into Robot‘s singleton class, making describe behave as a class method. Inside describe, self is Robot, so the bare call name resolves to Robot.name — the built-in Class#name method that returns a class’s name as a string.

Example 3: module_function for a utility module

module TemperatureConverter
  module_function

  def celsius_to_fahrenheit(celsius)
    (celsius * 9.0 / 5) + 32
  end

  def fahrenheit_to_celsius(fahrenheit)
    (fahrenheit - 32) * 5.0 / 9
  end
end

puts TemperatureConverter.celsius_to_fahrenheit(100)
puts TemperatureConverter.fahrenheit_to_celsius(32)

Output:

212.0
0.0

module_function with no arguments means both methods defined after it become directly callable on the module (TemperatureConverter.celsius_to_fahrenheit), exactly like Ruby’s own Math module. Under the hood these are the same methods you’d get from def self.celsius_to_fahrenheit, but module_function also keeps a private instance-method copy around in case the module is ever mixed in with include.

How it works step by step

  • Ruby gives every object a singleton class that sits just above its regular class in the method lookup chain, and it is normally empty and invisible.
  • Calling obj.extend(Mod) inserts Mod into that singleton class’s own ancestor chain, the same way include inserts a module into a class’s ancestor chain.
  • When you later call obj.some_method, Ruby searches the singleton class first, finds Mod‘s method there, and uses it — before ever looking at obj‘s real class.
  • Because a class is an object of class Class, extending a class inserts the module into the class’s singleton class, which is precisely where Ruby looks up methods called directly on the class (its "class methods").
  • Inside a module body, module_function (bare) flips a switch: every def that follows is compiled twice conceptually — once as a private instance method, and once as a singleton method on the module, so Module.method_name works immediately.

Common Mistakes

Mistake 1: using include when you meant extend

module Sayable
  def say_hi
    "Hi from #{self}"
  end
end

class Widget
  include Sayable
end

puts Widget.say_hi

This raises NoMethodError: undefined method 'say_hi' for class Widget. include mixes say_hi in as an instance method, so only a Widget.new instance could call it — the class object Widget itself never gets it. The fix is to use extend instead, which targets the class’s own singleton class:

module Sayable
  def say_hi
    "Hi from #{self}"
  end
end

class Widget
  extend Sayable
end

puts Widget.say_hi

Output:

Hi from Widget

Mistake 2: forgetting module_function makes the instance version private

module TemperatureConverter
  module_function

  def celsius_to_fahrenheit(celsius)
    (celsius * 9.0 / 5) + 32
  end
end

class Thermometer
  include TemperatureConverter
end

t = Thermometer.new
puts t.celsius_to_fahrenheit(0)

This raises NoMethodError: private method 'celsius_to_fahrenheit' called. module_function deliberately made the instance-method copy private, because the module was designed to be used as a namespaced toolbox, not mixed into other classes. The fix is to call it the way it was meant to be called — directly on the module:

module TemperatureConverter
  module_function

  def celsius_to_fahrenheit(celsius)
    (celsius * 9.0 / 5) + 32
  end
end

puts TemperatureConverter.celsius_to_fahrenheit(0)

Output:

32.0

If you genuinely want the methods to stay public and mixable, use extend self in the module body instead of module_function — it exposes the methods on the module without demoting the instance versions to private.

Best Practices

  • Use extend when only one object, or a class as a whole, needs a module’s behavior — not every instance of that class.
  • Use module_function or extend self for stateless helper modules meant to be called directly, the way Math or Comparable-style utility modules are used.
  • Prefer extend self over bare module_function if you ever want the methods to remain public and mixable elsewhere — it avoids the private-instance-method surprise.
  • Don’t reach for class << self just to add a handful of class methods from a module — a simple extend is usually clearer.
  • Remember only nil and false are falsy in Ruby; checking respond_to? after an extend call is a truthy/falsy check like any other, so 0 or "" returned from a method would still be treated as true.

Practice Exercises

  • Write a module Loggable with a method log(message) that prints "[LOG] <message>". Extend a single hash or array instance with it and call log on that instance only, then show that a second instance of the same class does not have log.
  • Write a module StringUtils using module_function with a method shout(text) that returns the text upcased with an exclamation mark appended. Call it directly on the module and confirm calling it as a mixed-in instance method raises a NoMethodError.
  • Rewrite your StringUtils module using extend self instead of module_function, mix it into a class with include, and show that instances of that class can now call shout successfully.

Summary

  • extend mixes a module’s instance methods into a single object’s (or class’s) singleton class, affecting only that one object.
  • Extending a class inserts the module into the class’s singleton class, which is exactly where Ruby looks up methods called directly on the class — giving you class-level methods.
  • module_function (bare) makes subsequent methods callable directly on the module and demotes their instance-method versions to private.
  • module_function :name converts specific, already-defined methods instead of everything below the call.
  • extend self achieves a similar toolbox effect to module_function but keeps the methods public, making it safer if the module might also be mixed in elsewhere.