What happens when a method doesn't exist
A familiar error, looked at closely
NoMethodError has shown up many times in this series: a typo, a method called on the wrong type, a name that doesn't exist on that object.
"hello".fly
# raises: NoMethodError: undefined method 'fly' for an instance of String
The instinct is to read this as "Ruby checked, fly isn't there, error." That's close, but it skips a step, and this course, the last of the nine in this series, is built on that step.
Ruby doesn't give up at once
Before raising NoMethodError, Ruby walks up the object's ancestor chain looking for a method named fly: its class, that class's superclass, any included modules, all the way up. Only when that search comes up empty does Ruby take one more step. It calls a method named method_missing on the object, passing the attempted name, :fly, along with the arguments and block of the original call. String doesn't override method_missing, so the default version, defined on BasicObject, runs, and its job is to raise NoMethodError. That's the error every earlier course has shown. It was never a special case; it was method_missing's default behavior.
Why this matters: you can override the hook
method_missing is an ordinary method, defined on BasicObject and inherited by every object in Ruby, so any class can override it like any other method. Overriding it means stepping in at that moment, right before Ruby would raise NoMethodError, and deciding that something else should happen.
class Ghost
def method_missing(name, *args)
"you called #{name} with #{args.inspect}, and nothing by that name exists, but I intercepted it"
end
end
Ghost.new.anything_at_all(1, 2)
# => "you called anything_at_all with [1, 2], and nothing by that name exists, but I intercepted it"
anything_at_all was never defined. Calling it doesn't raise, because Ghost's own method_missing caught the call before Ruby's default one ran.
What this course covers
- Overriding
method_missingto handle calls to methods that were never defined. respond_to_missing?, the method you must override alongside it, and why skipping it is a common mistake.- Calling
superinsidemethod_missingfor anything you don't handle, so a typo still raisesNoMethodErrorinstead of being absorbed. - How this closes the nine-course Ruby OOP series, from classes to this mechanism, and what comes next.
Key takeaways
- Before raising
NoMethodError, Ruby callsmethod_missingon the object, passing the attempted method name, arguments and block. - The
NoMethodErrorseen throughout this series wasBasicObject's defaultmethod_missingrunning, not a separate error path. - Because
method_missingis an ordinary inherited method, any class can override it to catch calls to methods that don't exist. - This course is about doing that override correctly and safely, and it closes the nine-course Ruby OOP series.
Keep going with lesson 2
Overriding method_missing
The method_missing signature, and one override answering a family of calls like DynamicPoint's x, y and z.
A free account also gives you the quizzes, your progress and notes, and the discussion.