Registering Hooks and Callbacks

In the very beginning of the chapter, we looked at the BlankSlate class, and I had mentioned that there was some additional work that needed to be done to deal with things such as new method definitions on Object or module inclusion.

To recap the situation, BlankSlate is supposed to be a “naked” base class we can inherit from that doesn’t reveal any of its methods until we tell it to. We have already covered the ins and outs of how BlankSlate hides its initial instance methods and how it can selectively reveal them. The problem that remains to be solved is how to accommodate for changes that happen at runtime.

Detecting Newly Added Functionality

As we’ve seen, due to the open class system, Ruby object definitions are never really finalized. As a consequence, if you add a method to Object, it becomes available immediately to every object in the system except instances of BasicObject. To put words into code, here’s what that means:

>> a  = "foo"
=> "foo"
>> b = [1,2,3]
=> [1, 2, 3]
>> class C; end
=> nil
>> c = C.new
=> #<C:0x42a400>
>> class Object
>>   def party
>>     "wooohoo!"
>>   end
>> end
=> nil
>> a.party
=> "wooohoo!"
>> b.party
=> "wooohoo!"
>> c.party
=> "wooohoo!"

Now everyone is partying, except BlankSlate. Or more accurately, BlankSlate is being forced to party when it doesn’t want to. The solution is to set up a hook that watches for newly defined methods and hides them:

class Object class << self alias_method :blank_slate_method_added, :method_added ...

Get Ruby Best Practices now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.