Ruby Logo

Refinements & Scoped Monkey Patching

Learn safe monkey patching with refinements using refine/using keywords for lexically scoped modifications.

Home Ruby Refinements & Scoped Monkey Patching
'); opacity: 0.4;">

Refinements

Safe monkey patching with lexically scoped modifications - extend classes without global pollution

Ruby 2.0+refine/using keywords

Why Refinements Matter

Extend classes safely without breaking existing code or polluting the global namespace

PROBLEM

Global Monkey Patching

# Dangerous global modification
class String
  def palindrome?
    self == self.reverse
  end
end

# Affects ALL strings everywhere!
"level".palindrome? # Works but risky

🚨 Global changes affect entire application and dependencies

SOLUTION

Safe Refinements

# Safe, scoped modification
module StringExtensions
  refine String do
    def palindrome?
      self == self.reverse
    end
  end
end

using StringExtensions
"level".palindrome? # Safe & scoped

✅ Changes only apply where explicitly activated

Lexical Scoping

Extensions only apply in specific code blocks where using is called.

No Global Pollution

Core classes remain unmodified outside refinement scope.

Library Safe

Perfect for gems and libraries without affecting other code.

Basic Refinement Syntax

CREATE Defining Refinements

# Define a refinement module
module StringExtensions
  refine String do
    def palindrome?
      self == self.reverse
    end

    def title_case
      split(' ').map(&:capitalize).join(' ')
    end
  end
end

USE Activating Refinements

# Activate refinement in scope
class DocumentProcessor
  using StringExtensions

  def process_title(text)
    # Now we can use our extensions
    if text.palindrome?
      "Palindrome: #{text.title_case}"
    else
      text.title_case
    end
  end
end

Real-World Applications

Practical use cases where refinements shine

DSL Creation

Create expressive domain-specific languages

# Create a time-based DSL
module TimeDSL
  refine Integer do
    def seconds
      self
    end

    def minutes
      self * 60
    end

    def hours
      self * 3600
    end
  end
end

# Usage in a scheduler
class TaskScheduler
  using TimeDSL

  def run_every(interval, &block)
    Thread.new do
      loop do
        block.call
        sleep(interval)
      end
    end
  end
end

# Beautiful, readable syntax
scheduler = TaskScheduler.new
scheduler.run_every(5.minutes) { cleanup_temp_files }
scheduler.run_every(1.hour) { send_status_report }

Testing Helpers

Enhance objects for testing without affecting production

# Testing refinements for better assertions
module TestHelpers
  refine Array do
    def should_include(item)
      raise "Expected #{self} to include #{item}" unless include?(item)
    end

    def should_be_sorted
      raise "Array not sorted: #{self}" unless self == sort
    end
  end
end

# Use only in test files
class SortTest < Test::Unit::TestCase
  using TestHelpers

  def test_sorting_algorithm
    result = sort_numbers([3, 1, 4, 1, 5])
    result.should_be_sorted
    result.should_include(1)
  end
end

Refinement Best Practices

Guidelines for safe and effective refinement usage

DO

Use for Libraries & DSLs

  • Create domain-specific languages
  • Extend classes in gems safely
  • Add testing utilities
  • Scope extensions to specific modules
DON'T

Overuse or Abuse

  • Don't use for simple methods
  • Avoid in performance-critical code
  • Don't chain refinements unnecessarily
  • Avoid overly complex refinements
CAUTION

Limitations to Know

  • Doesn't work with send or public_send
  • No effect on method or instance_method
  • Can't refine core method behavior
  • Limited reflection support

Start Using Refinements Today

Safe monkey patching without the global risks

Create DSLs

Build expressive domain-specific languages for your applications

Test Helpers

Add testing utilities without affecting production code

Library Development

Create gems that extend classes safely

Scoped Extensions

Add methods only where needed with lexical scoping

Quick Navigation

Related Topics

Video Tutorial

Watch and learn refinements & scoped monkey patching

Pro Tip: After reading through the content above, watch this video to reinforce your understanding and see the concepts in action!