In Ruby, it is possible to enhance the functionality of an existing object by including a module into a class using a mixin. It is commonplace to see code like this:
The example above is trivialized but hopefully helps to illustrate my observations. We have a module called ‘DateMethods’ which we are including into ‘MyClass’.
Within the ‘DateMethods’ module, the ‘self.included’ callback allows us to call ‘extend’ on the singleton object of ‘MyClass’ in order to extend the ‘ClassMethods’ module to create class methods.
While this approach works and it is something I have been doing myself, I can’t help but feel that this is not as syntactically pleasing as calling ‘MyClass.extend(DateMethods)’ which reads better.
We are also overriding ‘include’ to create an ‘extend’ when Ruby allows us to extend a module directly.
Rewriting the example above but using ‘extend’ instead:
Ruby provides a callback ‘extended’ which gets invoked whenever the receiver is used to extend an object. Within the ‘extended’ callback, we then ‘include’ the instance methods.
This is more flexible than ‘include’ itself as it can’t be called on instances directly. In addition, ‘include’ affects the entire class itself which may not be the intention if all you need is to have certain behavior at certain times. By using ‘extend’ on instances, we can achieve a kind of dynamic code loading:
In the above example adapted from a James Earl Gray article on mixins, only the ‘collection’ object has the ‘Pagination’ module methods since the ‘extend’ is on the singleton/metaclass of ‘collection’ object itself, which restricts the scope of the ‘Pagination’ behavior to be contained and not affecting the entire class. We could just have easily swapped out ‘Pagination’ with another module at runtime.
In summary, I feel this is a more flexible approach to writing more maintable, dynamic code.
Happy hacking!