Mixin - mixins made classier.
Mixin extends Ruby‘s Module class with a small, yet powerful set of features that make the experience of writing mixins more like that of writing classes when it comes to defining class methods.
Typically, the way to implement a mixin that defines class methods for its includees (at least that I have noticed) is to define a module within the mixin module, usually called ClassMethods, which gets automatically extended to an including class by overwriting the mixin‘s inherited method. This technique is usually sufficient for most situations, but it has a few limitations. One of these is the fact that class attributes referenced in ClassMethods do not exist in the same scope as the enclosing mixin‘s class attributes.
When to use it
Mixin comes in handy in following situations:
- When you are writing a mixin with class methods that need to access class attributes defined within the mixin module.
- When you want to define a "sub-mixin" module which includes another mixin in order to expand upon its class methods in addition to its instance methods (similar to defining a hierarchy of abstract base classes). This includes calls to super to invoke a "super-mixin‘s" implementation of a given class method.
- When you wish that certian module methods would get ‘inherited’ by including modules in the same manner that class methods get inherited by subclasses.
- When you simply get tired of writing the same old "def self.inherited(base); base.extend(ClassMethods)" method (or some variation of it) over and over again, thereby violating the sacred DRY principle ;)
Example
require 'mixin'
module FooBase
@@foo_class_attr = "FooBase's class attribute"
class_mixin do
def foo_class_method
@@foo_class_attr + " accessed from FooBase's class mixin"
end
end
end
module FooExtended
include FooBase
class_mixin do
def another_foo_class_method
@@foo_class_attr + " accessed from FooExtended's class mixin"
end
end
end
class FooBar
include FooExtended
end
FooBar.foo_class_method -> "FooBase's class attribute accessed from FooBase's class mixin"
FooBar.another_foo_class_method -> "FooBase's class attribute accessed from FooExtended's class mixin"
Extra Stuff
As briefly mentioned above, Mixin also provides a way to define module methods on a mixin that get ‘inherited’ by including modules, but that are not extended to classes. The semantics for defining such methods are identical to defining class methods via class_mixin (see module_mixin).
Also packaged with Mixin is the bonus mixin Metable which provides a fistful of useful metaprogramming-friendly methods such as alias_singleton_method and define_class_method.
Installation
% sudo gem install mixin
License
Copyright (c) 2008 Christian Herschel Stevenson, Persapient Systems. Released under the same license as Ruby.
Support
You‘re pretty much looking at it.
For more information, contact stevenson@persapient.com. This documentation can be found online at api.persapient.com/mixin