One of the most powerful and at the same time crazy ideas in Ruby is Monkey patching. However, its main drawback is that its effects apply globally across your entire project and all the gems you are currently using.
The great advantage of Ruby, though, is that it allows for a compromise by scoping monkey patching to a limited context.
To achieve this, you can use Refinements: define methods in a module using the refine Class do ... end construct and activate it with using.
Starting with Ruby 3.1, you can also import methods directly from a module using import_methods:
module StringExt
module Methods
def blank? = self.nil? || self.empty?
def present? = !blank?
end
refine String do
import_methods Methods
end
end
class SomeClass
using StringExt
def some_method
"".blank?
end
end
SomeClass.new.some_method # => true
Do you use Refinements in your projects? Or do you still patch classes globally?
String.class_eval do
def blank? = self.nil? || self.empty?
def present? = !blank?
end
# The `blank?` and `present?` methods will be available
# throughout the project and in other gems being used
"hello".present? # => true
module StringExt
refine String do
def blank? = self.nil? || self.empty?
def present? = !blank?
end
end
module Validator
using StringExt
def self.valid?(text) = text.present?
end
# The `blank?` / `present?` methods will be available only in this module
Validator.valid?("") # => false
"".blank? # => undefined method 'blank?' for an instance of String (NoMethodError)