Mar 31
Reopening modules in Ruby
Open class definitions in ruby allow libraries to add functionality to existing objects. Standard practice is to define a module with the new functionality and include it into the existing class ( Jay fields on the subject here ). Unfortunately this model breaks when you want to update a module.
For instance the following doesn’t work:
module ExampleModule def original_method end end class ExampleClass include ExampleModule end #re-open the module and extend module ExampleModule module Extension def extension_method end end include Extension end obj = ExampleClass.new obj.original_method #OK obj.extension_method #nope!
For whatever reason in ruby 1.9 at least changes to the inclusions of the module are not automatically seen in the class the way a new method in the module itself would be.
Unfortunately there doesn’t appear to be a good way around this. One option is to re-open and directly modify the module, which is what we’re trying to avoid. The other option is to re-include the module after extending it as follows:
class ExampleClass include ExampleModule end obj.extension_method #OK
Unfortunately if you are using open classes as an extension mechanism you are opening yourself up for a lot of confusing problems. Why? Suppose my extension used a module to override original_method (originally provided by ExampleModule) in ExampleClass
module OverrideOriginalMethod def original_method end end class ExampleClass include OverrideOriginalMethod end #...update example module... #reinclude ExampleModule so changes take effect class ExampleClass include ExampleModule end obj.extension_method #OK #oops! This is ExampleModule::original_method obj.original_method