Ruby Mixins

Share this article

Have you ever wondered what it meant to “mixin” functionality into your classes? Have you seen include and extend used in Ruby code and wondered what was going on? If so, then you’ve come to the right place. Mixins can offer a lot of flexibility to your code and by the end of this article you’ll know how to do it using Ruby.

What’s a Mixin?

A mixin can basically be thought of as a set of code that can be added to one or more classes to add additional capabilities without using inheritance. In Ruby, a mixin is code wrapped up in a module that a class can include or extend (more on those terms later). In fact, a single class can have many mixins.

What about Inheritance?

One area I like to use mixins is for logging. In my Rails applications I like each model to have access to a logger without using a global constant of some sort. Initially I thought about using some sort of base model class (which could inherit from ActiveRecord::Base) that would provide access to a logger. However, I didn’t really like the idea of all of my models having to extend a special class just to get a logger. Yes, they would already extend ActiveRecord::Base, so what’s the difference, right? Well, what if I wanted to add access to a logger in other parts of my application which didn’t inherit from ActiveRecord::Base (or a special subclasss)? Ruby only supports single inheritance, so mixins seemed to be the best solution.

Include vs Extend

Modules can either be included or extended depending on whether the methods will be added as instance methods or class methods, respectively.
module Logging
        def logger
            @logger ||= Logger.new(opts)
        end
    end
	
    class Person
        include Logging
	
        def relocate
            logger.debug "Relocating person..."
            # do relocation stuff
        end
    end
In the example above a Logging module is defined which provides an instance to a Logger object via the logger method. The Person class includes the Logging module which will add its methods as instance methods to the Person class. It’s worth noting that everything defined in the module is added to the class including methods (public, protected, private), attributes (e.g. attr_accessor :name) and constants. If instead I wanted to provide a logger via a class method I’d use the extend method as shown below.
module Logging
        def logger
            @@logger ||= Logger.new(opts)
        end
    end

    class Person
        extend Logging
  
        def relocate
            Person.logger.debug "Relocating person..."
        
            # could also access it with this
            self.class.logger.debug "Relocating person..."
        end
    end
There are three differences shown between the last two code snippets. In the latter you can see that the “logger” method creates a class variable, @@logger, instead of an instance variable. I did this because I expected the Logger to be extended onto other classes instead of being included. Of course, I also used the extend method instead of include. Finally, access to the logger method is done through the class instead of the instance, such as Person.logger.debug. It’s also possible to mixin a module to a single instance at runtime as shown in the following example.
module Logger
        def logger
            @logger ||= Logger.new(opts)
        end
    end

    class Person; end

    p = Person.new
    # p.logger -- this would throw a NoMethodError
    p.extend Logger
    p.logger.debug "just a test"

Included vs Extended

In some circumstances you may need to know when your module has been included or extended. One use case might be to help enforce the types of classes that can include your module. For example, I had a module that would check to see if a table existed for my models, in a Rails application. However, I wanted to make sure that my module was only included in classes that inherited from ActiveRecord::Base because the module invoked the ActiveRecord::Base#table_exists? method.
module VerifyTableExistance
        def self.included(base)
            raise "#{self.name} can only be included into classes that inherit from ActiveRecord::Base, #{base.name} does not." unless (base < ActiveRecord::Base)
            raise "#{base.name} does not have a table yet" unless base.table_exists?
        end
    end

    class Person < ActiveRecord::Base
        include VerifyTableExistance
    end
The VerifyTableExistance module implements the included class method which gets invoked whenever the module is included into another module or class. This allows me to verify that the class including the module is a kind of ActiveRecord::Base and, in this example, verify a table exists for the model. Another common pattern is to define a module that will mixin instance and class methods.
module AcmeModel
        def self.included(base)
            base.extend(ClassMethods)
        end

        def brand
            "acme"
        end

        module ClassMethods
            def all
                # get all of the AcmeModel instances
                []
            end
        end
    end

    class Widget
        include AcmeModel
    end

    w = Widget.new
    w.brand	# "acme" is the output, 
    Widget.all	# invoke the class method that was added
In this example the AcmeModel provides an instance method named brand. More importantly it overrides the included class method, provided by the Module class. The included method is a callback that gets invoked whenever the module is included by antoher class or module. At that point we extend the class that included the AcmeModel, the Widget class in this example, with the ClassMethods module. Lastly, you should also know that your module can override the extended class method which acts as callback when the module is extended.

Conclusion

Hopefully you’ve gotten a quick overview of what mixins are and how to use them in Ruby. If not, or if you feel like I left something out, please leave comments. This is my first article and I hope to have many more. Also, if there’s a particular area of Ruby you’d like to see discussed then leave a comment.

Frequently Asked Questions about Ruby Mixins

What is the main purpose of using Mixins in Ruby?

Mixins in Ruby are a way to include methods from one module into another, providing a powerful alternative to multiple inheritances. This allows you to use a module to collect and bundle methods, which can then be mixed into any number of classes. This is particularly useful when you have functionality that doesn’t belong to any single class or when you want to share functionality across multiple classes.

How do you create a Mixin in Ruby?

Creating a Mixin in Ruby is a straightforward process. First, you define a module with the methods you want to include. Then, you use the ‘include’ keyword in the class where you want to mix in the module. This will make all the methods from the module available in the class as instance methods.

Can you override methods in a Mixin?

Yes, you can override methods in a Mixin. If a class includes a module and defines a method with the same name as a method in the module, the class’s method will override the module’s method. This allows for a high degree of flexibility and customization.

What is the difference between ‘include’ and ‘extend’ in Ruby Mixins?

The ‘include’ and ‘extend’ keywords in Ruby serve different purposes. ‘Include’ mixes in the specified module’s methods as instance methods in the target class, while ‘extend’ mixes in the specified module’s methods as class methods in the target class.

How do Mixins relate to the principle of DRY in Ruby?

Mixins are a perfect embodiment of the DRY (Don’t Repeat Yourself) principle in Ruby. By allowing you to define a method once and then include it in multiple classes, Mixins help to eliminate code duplication and make your code more maintainable and efficient.

Can a class include multiple Mixins in Ruby?

Yes, a class can include multiple Mixins in Ruby. This is one of the key advantages of using Mixins as it allows a class to inherit behaviors from multiple sources.

What is the order of method lookup in Ruby when using Mixins?

When a method is called in Ruby, the interpreter first looks in the class of the object. If it doesn’t find the method there, it then looks in the modules included by the class, in the reverse order they were included. If it still doesn’t find the method, it moves up to the superclass and repeats the process.

Can Mixins access instance variables of the class they’re included in?

Yes, Mixins can access and modify the instance variables of the class they’re included in. This allows Mixins to interact with the state of the object, providing a high degree of flexibility.

How do Mixins compare to inheritance in Ruby?

While inheritance allows a class to inherit behavior from a single superclass, Mixins allow a class to inherit behavior from multiple modules. This makes Mixins a powerful tool for code reuse and organization, especially when a piece of functionality doesn’t fit neatly into a single inheritance hierarchy.

Can Mixins be used in conjunction with inheritance in Ruby?

Yes, Mixins can be used in conjunction with inheritance in Ruby. A class can inherit from a superclass and include one or more modules. This allows for a high degree of flexibility and code reuse.

Craig WickesserCraig Wickesser
View Author

Craig Wickesser is a software engineer who likes to use Ruby, JRuby, Rails, JavaScript, Python, Java and MongoDB. He is also a moderator for RailsCasts, a former writer for InfoQ and a former editor for GroovyMag. You can check Craig's stuff out on his blog.

Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week
Loading form