4 Ways to Write Module Functions
Tags: ruby
Published: 2019-09-26 14:20:00

This is not a best practices post.

Let's say that you wanted to add some functions that operated on strings, but didn't want to monkeypatch the String class. Let's also say that you take inspiration from Apache Commons' Lang library and wanted to create your own version of [StringUtils](https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html).

We want to end up with functions can be called like this:
```ruby
StringUtils.alphanumeric? "Hello123" # true
StringUtils.alphanumeric? "Hello World" # false
```

Since `StringUtils` is not an object that we'd want to instantiate, we'll write it as a module.

Now you have to make choice: how do we want to write the code so that the module itself can be the receiver for these methods.

## Option 1: Prepend `self` to the method name
```ruby
module StringUtils
  def self.alphanumeric?(str)
    /\A[0-9a-zA-Z]+\z/.match? str
  end
end
```

This is equivalent to `def StringUtils.alphanumeric?`, which is an example hosted on the [official Ruby docs website](https://ruby-doc.org/docs/ruby-doc-bundle/ProgrammingRuby/book/tut_modules.html). However, Rubocop will complain and suggest that you switch to `self.alphanumeric?` instead.

## Option 2: Put them in the "Singleton Class" (Eigenclass)
```ruby
module StringUtils
  class << self
    def alphanumeric?(str)
      /\A[0-9a-zA-Z]+\z/.match? str
    end
  end
end
```

I was thoroughly confused when I first read this type of code. Plus, if you search *Ruby Singleton class* and you'll find dozens of unrelated hits about implementing the singleton pattern. Good thing we came up with the much clearer name: "eigenclass".

Anyway, this option is nice because you can group all of the methods you want the module to receive inside a block. For that reason, I often see this option used inside of classes, alongside instance methods.

## Option 3: `extend self`
```ruby
module StringUtils
  extend self
    
  def alphanumeric?(str)
    /\A[0-9a-zA-Z]+\z/.match? str
  end
end
```

I saw this in the [Pact source code](https://github.com/pact-foundation/pact-ruby/blob/master/spec/support/spec_support.rb) and was taken aback.

This code allows you to call `StringUtils.alphanumeric?`, but it also allows you to `include StringUtils` in some other class.

I have a hard time thinking of a use case in which you'd want that.


## Option 4: `module_function`
```ruby
module StringUtils
  module_function
    
  def alphanumeric?(str)
    /\A[0-9a-zA-Z]+\z/.match? str
  end
end
```
All methods defined under the `module_function` line can be received by the module itself, AND will be made private so they can't be included in classes. You can also put `module_function` on the bottom of you module and give it symbol arguments so that you can pick and choose the affected methods:

```ruby
module StringUtils
  def alphanumeric?(str)
    /\A[0-9a-zA-Z]+\z/.match? str
  end

  module_function :alphanumeric?
end
```


## Conclusion

I won't say which option I'd choose to write this code. While there are nuanced arguments for each option, they all get the job done. I started this post by saying that it's not about best practice.

It's often hard to wrap your head around the patterns used in code you haven't written yourself. This is especially notable when someone writes code that you would have written differently.  I hope that seeing these snippets side by side will help you recognize what's going on when reading other people's code in the future.


**Bonus**
Here's a fun fact: If you type `extend self` while using Rubocop, it'll instruct you to use `module_method` instead. However, these are clearly not the same! [More here.](https://github.com/rubocop-hq/ruby-style-guide/issues/556)