📖 Scenario: Imagine you are creating a simple event system in Ruby where different parts of a program can react to certain events. This is like setting up hooks where you can attach your own code to run when something happens.
🎯 Goal: You will build a basic event hook system that allows registering and running hooks. This shows how hooks help frameworks let users add custom behavior easily.
📋 What You'll Learn
Create a hash called hooks to store event names and their attached blocks
Create a method called register_hook that takes an event name and a block, and stores the block in hooks
Create a method called run_hook that takes an event name and runs all blocks attached to that event
Demonstrate registering two hooks for the event :start and then running them
💡 Why This Matters
🌍 Real World
Many frameworks use hooks to let users add their own code at key points, like when a web request starts or finishes.
💼 Career
Understanding hooks helps you build or use frameworks that are flexible and customizable, a key skill in software development.
Progress0 / 4 steps
1
Create the hooks storage
Create a hash called hooks and set it to an empty hash {}.
Ruby
Hint
Use hooks = {} to create an empty hash.
2
Create the register_hook method
Create a method called register_hook that takes two parameters: event and a block. Inside the method, add the block to the hooks hash under the key event. Initialize the key with an empty array if it does not exist.
Ruby
Hint
Use hooks[event] ||= [] to create an array if needed, then add the block with << block.
3
Create the run_hook method
Create a method called run_hook that takes one parameter event. Inside the method, check if hooks[event] exists, then call each block stored there using call.
Ruby
Hint
Use hooks[event].each { |hook| hook.call } to run each block.
4
Register and run hooks
Register two hooks for the event :start using register_hook. The first hook should print "First start hook" and the second should print "Second start hook". Then call run_hook(:start) to run them.
Ruby
Hint
Use register_hook(:start) { puts "First start hook" } and similar for the second hook, then run_hook(:start).
Practice
(1/5)
1. What is the main reason hooks are useful in building Ruby frameworks?
easy
A. They replace the need for classes and modules
B. They allow custom code to run at specific points without changing core code
C. They speed up the program execution automatically
D. They make the program run without errors
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 B
Quick Check:
Hooks enable flexible extension = C [OK]
Hint: Hooks insert code at points without changing main code [OK]
Common Mistakes:
Thinking hooks speed up code automatically
Confusing hooks with replacing classes
Believing hooks prevent all errors
2. Which of the following is the correct syntax to define a hook method named before_save in Ruby?
easy
A. def hook :before_save; puts 'Saving'; end
B. hook before_save { puts 'Saving' }
C. before_save do puts 'Saving' end
D. def before_save; puts 'Saving'; end
Solution
Step 1: Recognize Ruby method definition syntax
Ruby methods are defined with def method_name; ... end.
Step 2: Match the hook method name
The hook method before_save is correctly defined as def before_save; ... end.
Final Answer:
def before_save; puts 'Saving'; end -> Option D
Quick Check:
Ruby method syntax = A [OK]
Hint: Ruby methods use def name; ... end syntax [OK]
Common Mistakes:
Using non-Ruby syntax like 'hook' keyword
Missing 'def' keyword
Incorrect block syntax without do/end
3. Given this Ruby code using a hook pattern:
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.save
What is the output when User.new.save is called?
medium
A. Validate user
Saving data
B. Saving data
C. NoMethodError
D. Validate user
Solution
Step 1: Understand the hook registration
The before_save class method stores a block in @before_save_hook for the User class.
Step 2: Analyze the save method call
When save is called, it calls the stored hook block (prints 'Validate user') then prints 'Saving data'.
Final Answer:
Validate user
Saving data -> Option A
Quick Check:
Hook runs before save message = B [OK]
Hint: Hook block runs before main save output [OK]
Common Mistakes:
Ignoring the hook call in save method
Expecting only 'Saving data' output
Confusing instance and class variables
4. Consider this Ruby code snippet:
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.save
What is the error in this code?
medium
A. No error, code runs fine
B. Undefined method `before_save` for User:Class
C. NoMethodError because @before_save_hook is nil in instance
D. SyntaxError due to missing end
Solution
Step 1: Identify where @before_save_hook is stored
The hook is stored as a class instance variable @before_save_hook, but save tries to call instance variable @before_save_hook.
Step 2: Understand the error cause
The instance variable @before_save_hook is nil, so calling call on it causes NoMethodError.
Final Answer:
NoMethodError because @before_save_hook is nil in instance -> Option C
Quick Check:
Instance vs class variable mismatch = D [OK]
Hint: Class vars differ from instance vars; call on nil causes error [OK]
Common Mistakes:
Thinking hook is stored in instance variable
Assuming no error occurs
Confusing syntax errors with runtime errors
5. You want to build a Ruby framework that allows users to add multiple hooks for before_save and run them all in order before saving. Which approach best supports this?
hard
A. Store hooks in an array and call each block in sequence before saving
B. Store a single block in a class variable and overwrite it each time
C. Use global variables to store hooks and call them randomly
D. Define multiple methods named before_save and rely on Ruby to call all
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 A
Quick Check:
Multiple hooks need array storage = A [OK]
Hint: Use array to keep and run multiple hooks in order [OK]
Common Mistakes:
Overwriting hooks instead of storing all
Using global variables causing conflicts
Expecting Ruby to call duplicate method names
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.