Prepend for method chain insertion in Ruby - Time & Space Complexity
We want to understand how adding a method at the start of a chain affects the time it takes to run.
How does inserting a method at the beginning change the work done as the chain grows?
Analyze the time complexity of the following Ruby code snippet.
class StringProcessor
def initialize(str)
@str = str
end
def upcase
@str = @str.upcase
self
end
def reverse
@str = @str.reverse
self
end
def prepend_method(new_method)
self.singleton_class.prepend(Module.new do
define_method(:process) do
send(new_method)
super()
end
end)
end
def process
@str
end
end
processor = StringProcessor.new("hello")
processor.prepend_method(:upcase)
processor.prepend_method(:reverse)
result = processor.process
This code adds methods at the start of a method chain using prepend, changing how process works.
Look for loops, recursion, or repeated calls.
- Primary operation: Calling the
processmethod which triggers the prepended methods in order. - How many times: Each prepended method runs once per
processcall, chaining through all prepended modules.
Each time we add a new method with prepend, the process call runs one more method before the original.
| Number of prepended methods (n) | Approx. Operations per process call |
|---|---|
| 1 | 2 (1 prepended + original) |
| 5 | 6 (5 prepended + original) |
| 10 | 11 (10 prepended + original) |
Pattern observation: The work grows linearly as more methods are prepended.
Time Complexity: O(n)
This means the time to run process grows directly with the number of prepended methods.
[X] Wrong: "Adding more prepended methods won't affect how long process takes."
[OK] Correct: Each prepended method adds one more step to run, so more prepends mean more work.
Understanding how method chains grow helps you reason about code efficiency and design in real projects.
What if we replaced prepend with append (using include)? How would the time complexity of process change?
Practice
prepend keyword do in Ruby when used with a module and a class?Solution
Step 1: Understand method lookup order with prepend
Usingprependplaces the module before the class in the method lookup chain, so module methods are checked first.Step 2: Compare prepend with other module inclusion methods
Unlikeincludewhich adds the module after the class,prependinserts it before, changing method resolution order.Final Answer:
It inserts the module before the class in the method lookup chain. -> Option AQuick Check:
Prepend = module methods run first [OK]
- Confusing prepend with include
- Thinking prepend replaces class methods permanently
- Assuming prepend appends module after class
Mod to a class MyClass?Solution
Step 1: Recall Ruby syntax for prepend
The correct syntax to prepend a module isprepend ModuleNameinside the class definition.Step 2: Eliminate other options
includeadds module after class,extendadds methods as class methods, andinsertis invalid syntax.Final Answer:
class MyClass; prepend Mod; end -> Option CQuick Check:
Prepend syntax = prepend ModuleName [OK]
- Using include instead of prepend
- Using extend which affects class methods
- Typing invalid keywords like insert
module M
def greet
"Hello from M, " + super
end
end
class C
prepend M
def greet
"Hello from C"
end
end
puts C.new.greetSolution
Step 1: Understand method lookup with prepend
BecauseMis prepended, itsgreetmethod is called first.Step 2: Follow the super call in module method
ThesuperinsideM#greetcalls the originalgreetinC, returning "Hello from C".Step 3: Combine returned strings
The module method returns "Hello from M, " + "Hello from C" resulting in "Hello from M, Hello from C".Final Answer:
"Hello from M, Hello from C" -> Option BQuick Check:
Prepend + super calls original method [OK]
- Ignoring super call and expecting only module output
- Thinking prepend replaces original method without super
- Expecting NoMethodError due to super
module M
def hello
super + " world"
end
end
class C
prepend M
end
puts C.new.helloSolution
Step 1: Check method definitions
The moduleMdefineshellocallingsuper, but classChas nohellomethod.Step 2: Understand super call behavior
SinceChas nohello,superhas no method to call, causing aNoMethodError.Final Answer:
NoMethodError because super has no method to call -> Option DQuick Check:
Super needs original method; missing causes NoMethodError [OK]
- Assuming super works without original method
- Thinking prepend fixes missing methods automatically
- Confusing syntax error with runtime error
module A
def info
"A" + super
end
end
module B
def info
"B" + super
end
end
class Base
def info
"Base"
end
end
class MyClass < Base
prepend A
prepend B
end
puts MyClass.new.infoSolution
Step 1: Understand multiple prepends order
Modules prepended last are checked first, soBis beforeAin lookup.Step 2: Trace method calls
B#inforuns first, returns "B" + super, which callsA#info, returning "A" + super, which callsBase#inforeturning "Base".Step 3: Combine results
Concatenate strings: "B" + "A" + "Base" = "BABase".Final Answer:
"BABase" -> Option AQuick Check:
Last prepend runs first; super chains down [OK]
- Assuming first prepended module runs first
- Ignoring method lookup order with multiple prepends
- Confusing prepend with include order
Ready to prove it?
Pass the test and this pattern moves unknown
