DEV Community

Germán Alberto Gimenez Silva
Germán Alberto Gimenez Silva

Posted on • Originally published at rubystacknews.com on

🐒 Monkey Patching in Ruby: What It Is and Why You Should Be Careful

May 28, 2025

Monkey patching is a powerful and controversial technique in Ruby. It involves reopening existing classes and modifying or adding methods directly. Let’s dive into what it is, why it can be problematic, and some better ways to achieve similar goals.


What is Monkey Patching?

In Ruby, you can add or change the behavior of any class at runtime:


class String
  def shout
    upcase + "!"
  end
end

puts "hello".shout # => "HELLO!"

Enter fullscreen mode Exit fullscreen mode

While this flexibility can be tempting, it also comes with risks.


💡 Need to Extend Class Behavior Safely?

If you’re looking to extend class behavior in your application following best practices, I can help!

Contact Me


The Problems with Monkey Patching

Article content
The Problems with Monkey Patching

🔴 Global Impact : Changes to core classes affect all parts of your application, including libraries that depend on them. This can lead to subtle bugs and maintenance nightmares.

🔴 Unexpected Behavior : Other developers (or your future self) might not expect your modifications, especially when debugging issues in seemingly unrelated code.

🔴 Compatibility Issues : If a gem or Ruby itself later adds a method with the same name, you could break things in unpredictable ways.


A Better Alternative: Refinements

Introduced in Ruby 2.0, Refinements provide a way to modify classes locally instead of globally:


class String
  def greet
    "Hello, " + self
  end
end

module ShoutRefinement
  refine String do
    def greet
      "HELLO, " + upcase
    end
  end
end

using ShoutRefinement

puts "world".greet # => "HELLO, WORLD"

Enter fullscreen mode Exit fullscreen mode

The beauty of refinements is that they only affect the scope where using is declared, preventing unintended global changes.


Decorators: Another Clean Approach

For situations where you want to extend behavior without changing the class itself , the Decorator Pattern can be a great fit. A decorator wraps the original object, adding behavior while delegating to the original methods:


class User
  def name
    "Alice"
  end
end

class UserDecorator
  def initialize(user)
    @user = user
  end

  def name
    @user.name.upcase
  end
end

user = User.new
decorated_user = UserDecorator.new(user)

puts decorated_user.name # => "ALICE"

Enter fullscreen mode Exit fullscreen mode

With decorators, you avoid changing core classes and keep your code flexible and maintainable.


Conclusion

While monkey patching can be handy, it’s often better to use refinements or decorators for local and explicit changes. These techniques keep your code clean and avoid hidden side effects.

Have you used monkey patching or refinements in your work? Let me know your thoughts!

Article content

Top comments (0)