Including a Module. With Parameters!

Posted on March 11, 2016 by Carsten Zimmermann

The Ruby include statement only allows for one type of argument: the module constant(s) to include. Oftentimes I wish it would be possible to pass arguments that the included module receives as optional parameters to its included callback like so:

Module#included is the method that gets called when the module is included somewhere. Unlike in my would-be-nice example, it only receives one argument: the constant of the including class.

Additional arguments to include are expected to be modules, allowing you to include more than one module on one line.

A way to parameterize the behaviour of included modules is to add a singleton method in the included class and then have that class method accept parameters to do whatever (e.g. set class-wide variables or dynamically define methods).

This is obviously a contrived example, but what I dislike about it is the two lines of meta programming that serve the same purpose: dynamically adding something to the including class. Also, the define_greeter class method is probably not needed anywhere else in the class and this is against my sense of aesthetics.

Now, how about dynamically creating a module and then including that one? Like … a module factory? How do we even start? It’s actually quite easy: the include statement only accepts arguments of type Module. So all we have to make sure that whatever we pass to include returns a proper Ruby Module. I give you this:

Voila! ModuleFactory.new(…) returns a module which can be included, thus combining the include statement with the dynamic meta-programming. The provided examples are all a bit abstract but I will provide a more concrete (Rails 5!) example in a follow-up post.