Method_missing for catch-all in Ruby - Time & Space Complexity
We want to understand how the time it takes to run a method_missing catch-all grows as we call different methods.
Specifically, how does the program behave when it handles unknown method calls?
Analyze the time complexity of the following code snippet.
class CatchAll
def method_missing(name, *args)
"You called: #{name} with #{args.length} arguments"
end
end
obj = CatchAll.new
obj.any_method(1, 2, 3)
This code catches any unknown method call and returns a message including the method name and argument count.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The method_missing is called once per unknown method call.
- How many times: Once per unknown method call; no loops or recursion inside method_missing.
Each unknown method call triggers method_missing once, doing a simple string operation.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 unknown calls | 10 simple string operations |
| 100 unknown calls | 100 simple string operations |
| 1000 unknown calls | 1000 simple string operations |
Pattern observation: The work grows directly with the number of unknown method calls, each handled quickly.
Time Complexity: O(n)
This means the time grows linearly with the number of unknown method calls made.
[X] Wrong: "method_missing runs once and handles all unknown calls at once."
[OK] Correct: method_missing runs separately for each unknown call, so time adds up with each call.
Understanding how method_missing works helps you reason about dynamic method handling and its cost in real programs.
"What if method_missing called another method inside that loops over arguments? How would the time complexity change?"
Practice
What is the main purpose of the method_missing method in Ruby?
Solution
Step 1: Understand what
method_missingdoesmethod_missingis called when an object receives a method call it does not have defined.Step 2: Identify its purpose
It allows handling these unknown method calls dynamically, enabling flexible behavior.Final Answer:
To catch calls to methods that do not exist and handle them dynamically. -> Option AQuick Check:
method_missingcatches unknown methods [OK]
- Thinking method_missing defines new methods automatically
- Confusing method_missing with attr_accessor
- Assuming method_missing overrides existing methods
Which of the following is the correct syntax to define method_missing in a Ruby class?
class Example # Your code here end
Solution
Step 1: Recall method_missing signature
The method receives the missing method's name as a symbol and any arguments as a splat array.Step 2: Check each option's parameters
def method_missing(method_name, *args) puts "Unknown method: #{method_name} with args: #{args}" end correctly usesmethod_name, *argsto capture method name and all arguments.Final Answer:
def method_missing(method_name, *args) puts "Unknown method: #{method_name} with args: #{args}" end -> Option CQuick Check:
Correct parameters = def method_missing(method_name, *args) puts "Unknown method: #{method_name} with args: #{args}" end [OK]
- Forgetting the splat (*) before args
- Using only one parameter for method_missing
- Passing args without splat causing errors
What will be the output of this Ruby code?
class CatchAll
def method_missing(name, *args)
"Called #{name} with #{args.join(', ')}"
end
end
obj = CatchAll.new
puts obj.hello('world')Solution
Step 1: Understand method_missing behavior
The method_missing catches the call tohellowhich is undefined and returns a string with method name and arguments.Step 2: Evaluate the output
Callingobj.hello('world')triggers method_missing with name:helloand args['world'], so output is "Called hello with world".Final Answer:
Called hello with world -> Option BQuick Check:
method_missing output = Called hello with world [OK]
- Expecting NoMethodError instead of method_missing output
- Confusing method name symbol with string
- Ignoring args passed to method_missing
Identify the error in this Ruby class using method_missing:
class Test
def method_missing(name)
puts "Missing: #{name}"
end
end
Test.new.unknown_method(1, 2)Solution
Step 1: Check method_missing parameters
The callunknown_method(1, 2)passes two arguments, but method_missing only accepts one parametername.Step 2: Identify the fix
To handle any number of arguments, method_missing must accept*argsas a splat parameter.Final Answer:
method_missing should accept a splat argument for extra parameters. -> Option AQuick Check:
Missing splat args causes error [OK]
- Ignoring extra arguments passed to missing method
- Assuming puts return is enough
- Thinking method_missing can't be defined in classes
Given this class, what will obj.foo.bar(1) output?
class CatchAll
def method_missing(name, *args)
if name == :bar
"Handled bar with #{args[0]}"
else
self
end
end
end
obj = CatchAll.new
puts obj.foo.bar(1)Solution
Step 1: Trace obj.foo call
Callingobj.footriggers method_missing withname=:foo, which returnsself(the object itself).Step 2: Trace .bar(1) call on returned self
Calling.bar(1)triggers method_missing withname=:barand args[1], which returns "Handled bar with 1".Final Answer:
Handled bar with 1 -> Option DQuick Check:
Chained method_missing returns handled string [OK]
- Expecting NoMethodError on first call
- Not realizing method_missing returns self for chaining
- Assuming args are missing for bar method
Ready to prove it?
Pass the test and this pattern moves unknown
