Why hooks enable framework building in Ruby - Performance Analysis
We want to understand how using hooks affects the speed of running code when building frameworks.
Specifically, how does the number of operations change as the program grows?
Analyze the time complexity of the following code snippet.
class Framework
def initialize
@hooks = {}
end
def register_hook(name, &block)
@hooks[name] ||= []
@hooks[name] << block
end
def run_hook(name, *args)
@hooks[name]&.each { |hook| hook.call(*args) }
end
end
This code lets us add and run hooks by name, calling all functions registered for that hook.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Looping over all hooks registered under a given name when running that hook.
- How many times: Once for each hook function registered for that name.
As we add more hooks for a name, running that hook calls more functions.
| Input Size (number of hooks) | Approx. Operations (hook calls) |
|---|---|
| 10 | 10 |
| 100 | 100 |
| 1000 | 1000 |
Pattern observation: The number of operations grows directly with the number of hooks registered.
Time Complexity: O(n)
This means running hooks takes time proportional to how many hooks are registered for that event.
[X] Wrong: "Running hooks is always fast and constant time no matter how many hooks there are."
[OK] Correct: Each hook added means more functions to call, so running hooks takes longer as more are registered.
Understanding how hooks scale helps you explain how frameworks stay flexible yet efficient as they grow.
What if we changed the code to run hooks in parallel instead of one by one? How would the time complexity change?
Practice
Solution
Step 1: Understand what hooks do
Hooks let you add your own code at certain points in a program without changing the main code.Step 2: Why this helps frameworks
This makes frameworks flexible and easy to extend because users can add features without touching core code.Final Answer:
They allow custom code to run at specific points without changing core code -> Option BQuick Check:
Hooks enable flexible extension = C [OK]
- Thinking hooks speed up code automatically
- Confusing hooks with replacing classes
- Believing hooks prevent all errors
before_save in Ruby?Solution
Step 1: Recognize Ruby method definition syntax
Ruby methods are defined withdef method_name; ... end.Step 2: Match the hook method name
The hook methodbefore_saveis correctly defined asdef before_save; ... end.Final Answer:
def before_save; puts 'Saving'; end -> Option DQuick Check:
Ruby method syntax = A [OK]
- Using non-Ruby syntax like 'hook' keyword
- Missing 'def' keyword
- Incorrect block syntax without do/end
class Framework
def self.before_save(&block)
@before_save_hook = block
end
def save
self.class.instance_variable_get(:@before_save_hook)&.call
puts 'Saving data'
end
end
class User < Framework
before_save { puts 'Validate user' }
end
User.new.saveWhat is the output when
User.new.save is called?Solution
Step 1: Understand the hook registration
Thebefore_saveclass method stores a block in@before_save_hookfor the User class.Step 2: Analyze the save method call
Whensaveis called, it calls the stored hook block (prints 'Validate user') then prints 'Saving data'.Final Answer:
Validate user Saving data -> Option AQuick Check:
Hook runs before save message = B [OK]
- Ignoring the hook call in save method
- Expecting only 'Saving data' output
- Confusing instance and class variables
class Framework
def self.before_save(&block)
@before_save_hook = block
end
def save
@before_save_hook.call
puts 'Saving data'
end
end
class User < Framework
before_save { puts 'Validate user' }
end
User.new.saveWhat is the error in this code?
Solution
Step 1: Identify where @before_save_hook is stored
The hook is stored as a class instance variable@before_save_hook, butsavetries to call instance variable@before_save_hook.Step 2: Understand the error cause
The instance variable@before_save_hookis nil, so callingcallon it causes NoMethodError.Final Answer:
NoMethodError because @before_save_hook is nil in instance -> Option CQuick Check:
Instance vs class variable mismatch = D [OK]
- Thinking hook is stored in instance variable
- Assuming no error occurs
- Confusing syntax errors with runtime errors
before_save and run them all in order before saving. Which approach best supports this?Solution
Step 1: Understand the need for multiple hooks
To support many hooks, you must keep all hook blocks, not overwrite them.Step 2: Choose a data structure to hold hooks
An array can store multiple blocks, allowing iteration and calling each in order.Step 3: Why other options fail
Overwriting loses hooks, global variables cause conflicts, and Ruby does not call multiple methods with same name automatically.Final Answer:
Store hooks in an array and call each block in sequence before saving -> Option AQuick Check:
Multiple hooks need array storage = A [OK]
- Overwriting hooks instead of storing all
- Using global variables causing conflicts
- Expecting Ruby to call duplicate method names
Ready to prove it?
Pass the test and this pattern moves unknown
