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.