Mag Moneybird cookies plaatsen? Met deze cookies kunnen wij je website bezoek analyseren en verbeteren. Meer informatie vind je in onze privacy statement.

Introduction to Mutations

About a year ago we found ourselves with an overly complicated codebase. The amount of business logic is constantly growing. We followed the ‘fat model’ approach, meaning most of this business logic is contained in our models. Actions on our models can have many obscure side effects caused by ActiveRecord callbacks.

The list of business requirements grows continuously, so the number of actions on models is growing at a constant rate too. It is hard to keep a good overview of all callbacks that are executed when performing an action, this makes the codebase error prone. We needed a way to structure our code to ensure its long-term maintainability.

The solution came in the form of a Ruby gem named Mutations. Mutations offers a way to organize our business logic into separate “commands”. For example:

    require "mutations"

    module Contacts
      class CreateContact < Mutations::Command
        required do
          string :first_name
          string :last_name

        optional do
          boolean :receive_newsletter

        def execute
          instance = first_name, last_name: last_name)

          if and receive_newsletter


The example above allows us to create a contact using the following call:!(first_name: "Money", last_name: "Bird")

As you can see in the first example, we’ve specified “required” and “optional” blocks. Mutations uses these blocks to automatically validate the input and to throw away anything that isn’t listed.

In doing so we’re effectively programming by contract. We’ve exposed a contract to which the caller must comply. If the input requirements are met the logic will be executed. If they aren’t the execution will halt, usually resulting in an error. In doing so errors will surface with a clear message just after their inception. Without Mutations this wouldn’t be the case.


Mutations helped restructure our codebase, it neatly organized our business logic into commands. It ridded our models of unwanted hooks and made our controllers a lot leaner.