Notes to self

Ruby refinements example

Refinements is a Ruby 2.0 answer to monkey patches that can take control of your program without you realizing it. Next time you will be tempted to monkey patch something, think twice and consider using refinements.

Let’s say we want to use the ordinal method from ActiveSupport without requiring AS and without monkey-patching directly.

Here is how a refinement of that would look like:

module CoreClassesExtentions
  refine String do
    # Returns the suffix that should be added to a number to denote the position
    # in an ordered sequence such as 1st, 2nd, 3rd, 4th.
    #
    #   ordinal(1)     # => "st"
    #   ordinal(2)     # => "nd"
    #   ordinal(1002)  # => "nd"
    #   ordinal(1003)  # => "rd"
    #   ordinal(-11)   # => "th"
    #   ordinal(-1021) # => "st"
    def ordinal(number)
      abs_number = number.to_i.abs

      if (11..13).include?(abs_number % 100)
        "th"
      else
        case abs_number % 10
        when 1; "st"
        when 2; "nd"
        when 3; "rd"
          else    "th"
        end
      end
    end
  end
end

Now if I want to use this within my application I can just tell Ruby I want to use the refined classes with using keyword:

using CoreClassesExtentions

'1'.ordinal # => "st"

This would change the string behaviour for the whole file. Since Ruby 2.3 we can use it explicitly within a class:

class VeryNiceClass
  using CoreClassesExtentions

  def ending(input)
    input.ordinal
  end
end
Check out my book
Deployment from Scratch is unique Linux book about web application deployment. Learn how deployment works from the first principles rather than YAML files of a specific tool.
by Josef Strzibny
RSS