Meta Methodology

Ruby clutters its objects a lot with methods for metaprogramming other methods:

Class.instance_methods.grep /method/
=> [:instance_methods, :public_instance_methods,
:protected_instance_methods, :private_instance_methods,
:method_defined?, :public_method_defined?,
:private_method_defined?, :protected_method_defined?,
:public_class_method, :private_class_method, :instance_method,
:public_instance_method, :methods, :singleton_methods,
:protected_methods, :private_methods, :public_methods,
:method, :public_method, :singleton_method,
:define_singleton_method]

Class.private_instance_methods.grep /method/
=> [:method_added, :method_removed, :method_undefined,
:remove_method, :undef_method, :alias_method, :define_method,
:instance_methods_for, :__method__, :singleton_method_added,
:singleton_method_removed, :singleton_method_undefined,
:method_missing]

It's so many methods, because working with methods is a multi-dimensional problem:

Let's put everything in some order:

Method Lists

Methods returning method lists always take a boolean argument, which will prevent inheritance if set to false¹

Method From Target Visibility
Object#singleton_methods any singleton public + protected
Object#methods any self + singleton public + protected
Object#public_methods any self + singleton public
Object#protected_methods any self + singleton protected
Object#private_methods any self + singleton private
Module#instance_methods class instances public + protected
Module#public_instance_methods class instances public
Module#protected_instance_methods class instances protected
Module#private_instance_methods class instances private

Method Defined? Checks

Instead of listing all methods and checking if the resulting array contains a specific method, you can also directly check if a method is defined.

Since Ruby 2.6, you can also pass in a boolean as second argument which will ignore the inheritance chain (similar like it is with the method listings above).

Method From Target Visibility
Module#method_defined? class instances all
Module#public_method_defined? class instances public
Module#protected_method_defined? class instances protected
Module#private_method_defined? class instances private

Method Getters

These methods will return method objects for further metaprogramming action:

Method From Target Visibility Returns
Object#singleton_method any singleton all Method
Object#method any self + singleton all Method
Object#public_method any self + singleton public Method
Module#instance_method class instances all UnboundMethod
Module#public_instance_method class instances public UnboundMethod

Method Manipulation

These methods will actually modify your objects:

Method From Target Visibility
Object#define_singleton_method any singleton public
Module#define_method (private) class instances public (see notes)
Module#remove_method (private) class instances -
Module#undef_method (private) class instances -
Module#alias_method (private) class instances same

Method Hooks

Hook methods can be defined and will be called by the Ruby interpreter when the respective event happens:

Method From Target
BasicObject#singleton_method_added any singleton
BasicObject#singleton_method_undefined any singleton
BasicObject#singleton_method_removed any singleton
Module#method_added class instances
Module#method_undefined class instances
Module#method_removed class instances
BasicObject#method_missing class instances

Method Visibility Modifiers

Besides public, protected, and private, there are two additional methods with the sole purpose of changing a method's visibility:

Method From Target Description
Module#public_class_method class singleton Makes a class's singleton method public
Module#private_class_method class singleton Makes a class's singleton method private

Current Method Name

There are two underscore-wrapped methods that return the current method's name:

Method From Returns
Kernel#__method__ (private) any Original method name
Kernel#__callee__ (private) any Aliased method name

A Better API for Metaprogramming Methods?

Metaprogramming in Ruby has evolved over time, but it might be a good idea to clean it up a little - A good example of how to clean up one of Ruby's other metaprogramming APIs is the instance gem. It gives you a neat API for working with an object's state, like setting instance variables. Someone feels like building a similar gem for Ruby's Method APIs? 2019 Update: I gave it a try! You can see the results here: object_shadow

More Idiosyncratic Ruby