Skip to content
Hooks and Reflection
step 1/5

Reading — step 1 of 5

Learn

~1 min readSingletons and Reflection

Ruby fires hooks at key points in the object lifecycle. Override them to customize behavior.

included / extended / prepended — module inclusion hooks:

module Trackable
  def self.included(base)
    puts "#{base} included Trackable"
    base.extend(ClassMethods)
  end

  module ClassMethods
    def track!
      puts "tracking #{self}"
    end
  end
end

class User
  include Trackable        # prints "User included Trackable"
end

User.track!                # works because of the extend in the hook

This is THE pattern for modules that add class-level features.

inherited — fires when a class is subclassed:

class Base
  def self.inherited(subclass)
    puts "#{subclass} inherited from Base"
  end
end

class Child < Base; end    # prints "Child inherited from Base"

method_added / method_removed / method_undefined — class-level method hooks.

Reflection helpers:

User.instance_methods(false)         # methods defined on User itself
User.instance_methods                 # all, including inherited
User.public_method_defined?(:name)
user.method(:name).source_location    # file:line where method was defined
ObjectSpace.each_object(User) { |u| puts u }   # every User instance in memory

ObjectSpace lets you walk all live objects of a type. Used by debuggers, leak detectors. Don't use in production hot paths — it's slow.

__method__ — name of the currently executing method:

def calculate
  log "in #{__method__}"
end

Useful for logging without hardcoding method names that change with refactoring.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…