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 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