From 676038e9922d45c8c56d188e1e1b0cf87c73f80d Mon Sep 17 00:00:00 2001 From: jbranchaud Date: Wed, 17 Dec 2025 16:54:43 -0600 Subject: [PATCH] Add Create A Module Of Utility Functions as a Ruby TIL --- README.md | 3 +- ruby/create-a-module-of-utility-functions.md | 59 ++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 ruby/create-a-module-of-utility-functions.md diff --git a/README.md b/README.md index 4bae849..b3ec7e0 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ pairing with smart people at Hashrocket. For a steady stream of TILs, [sign up for my newsletter](https://visualmode.kit.com/newsletter). -_1708 TILs and counting..._ +_1709 TILs and counting..._ See some of the other learning resources I work on: @@ -1362,6 +1362,7 @@ If you've learned something here, support my efforts writing daily TILs by - [Create A Hash From An Array Of Arrays](ruby/create-a-hash-from-an-array-of-arrays.md) - [Create Listing Of All Middleman Pages](ruby/create-listing-of-all-middleman-pages.md) - [Create Mock Class That Can Be Overridden](ruby/create-mock-class-that-can-be-overridden.md) +- [Create A Module Of Utility Functions](ruby/create-a-module-of-utility-functions.md) - [Create Named Structs With Struct.new](ruby/create-named-structs-with-struct-new.md) - [Create Thumbnail Image For A PDF](ruby/create-thumbnail-image-for-a-pdf.md) - [Decompose Unicode Character With Diacritic Mark](ruby/decompose-unicode-character-with-diacritic-mark.md) diff --git a/ruby/create-a-module-of-utility-functions.md b/ruby/create-a-module-of-utility-functions.md new file mode 100644 index 0000000..63aab81 --- /dev/null +++ b/ruby/create-a-module-of-utility-functions.md @@ -0,0 +1,59 @@ +# Create A Module Of Utility Functions + +In my [latest blog post](https://www.visualmode.dev/create-a-module-of-utility-functions-in-ruby), +I went into full detail about how the [`Module#module_function` method](https://ruby-doc.org/3.4.1/Module.html#method-i-module_function) works. +It creates both a module of utility functions that we can access directly on +that module like we would with `self` methods. It can also be included in a +class as a way of sharing copies of those utility functions with the class. A +key point to them being copies is that they can then be overridden by the +including class. + +Here is the example I used in the blog post: + +```ruby +module MarkdownHelpers + module_function + + def heading(text, level = 1) + ("#" * level) + " #{text}" + end + + def link(text, href) + "[#{text}](#{href})" + end + + def image(alt_text, href) + "!#{link(alt_text, href)}" + end +end +``` + +I won't cover everything that the blog post covers, but what I found really nice +about this pattern is that I can call those utility functions directly with the +module as the receiver: + +```bash +$ ruby -r ./markdown_helpers.rb -e 'puts MarkdownHelpers.link("Click here", "https://example.com")' +[Click here](https://example.com) +``` + +The alternative to this generally looks like: + +```ruby +module MarkdownHelpers + def self.heading(text, level = 1) + ("#" * level) + " #{text}" + end + + def self.link(text, href) + "[#{text}](#{href})" + end + + def self.image(alt_text, href) + "!#{link(alt_text, href)}" + end +end +``` + +That would be fine, but we completely lose out on the ability to include it as a +mix-in with other classes.