Modules as Mixins in Ruby

Posted by Flatiron School  /  October 22, 2012

The following is a guest post by Kevin McNamee and originally appeared on his blog. Kevin is currently a student a The Flatiron School. You can learn more about him here, or follow him on twitter here.

Modules are similar to classes except they don’t have instances and don’t have subclasses. In ruby, modules can provide value in a wide range of uses. Modules collect related methods and constants in one singular location to share behavior across classes. Mixins allow for exactly this.

Without even writing a module, you are using mixins everyday throughout your ruby programs. You are most likely utilizing enumerables everyday. Enumerables are just modules built into ruby’s standard library. Enumerables are a set of methods that are accessable across all classes in ruby. To visualize this, let’s take a look at what we see if we check for the ancestors of the Array class in irb:

Blog post image: tumblr_mcasu5zi4Q1rtan47.png

You can see that Enumerable is mixed in to the object hierarchy of the Array class. The array is not a subclass of Enumerable, but rather inherits the behaviors and full set of methods from the enumerables.

To show an example, we want to create two classes: a Movie class and a Song class. We want each class to have similar behavior in that instances of each class can be thumbed up or thumbed down. We wouldn’t want to create a superclass in order share theses methods because we don’t want any shared properties other than the ability to be thumbed up or thumbed down. In this case, we will create a module called Rankable.

Blog post image: tumblr_mcasuli9WF1rtan47.png

Now, we can create our two classes for Movies and Songs. By including the Rankable module in both the Movie class as well as the Song class, we are able to augment the behavior to vote our movies and songs up and down.

Blog post image: tumblr_mcasv2DyLI1rtan47.png

Let’s now create a new movie instance and pass the thumbs_up method. You can see by mixing in the Rankable module, we have access to the thumbs_up method.

Blog post image: tumblr_mcasveDmi21rtan47.png

A similar method is accessible when we instantiate a new instance of the Song class.

Blog post image: tumblr_mcasvsydu81rtan47.png

Just as we looked at the ancestor hierarchy of the Array class earlier, when we check the ancestors of Movie or Song we will see a similar output. The difference here is, instead of Enumerable which remember is a module built into the ruby library, we will see our custom module, Rankable between the Movie class and Object.

Blog post image: tumblr_mcasw3fHJC1rtan47.png

When a method is passed to an instance of the Movie class, it will first look in the Movie class for the behavior of that method. If the the instance does not find that method in it’s direct class, it will start going up the chain of superclasses to find the method behavior. Before checking the next direct superclass, the instance will check for a method in the direct module. If no module exists, the class instance will only then look in direct superclass. The image visualizes this action.

Blog post image: tumblr_mcaswmJwoN1rtan47.jpg

Mixins are great for abstracting behaviors from your classes and ensuring you do are not creating duplicate code in your programs. This is a basic overview of using modules as mixins. Modules can flex the power of your ruby code in much deeper ways including a replacement of monkey patching your code as well as namespacing. Look for more in depth posts on each of these topics in the future.