Open Classes, Monkey Patching, and Refinements
Prerequisites: Modules and mixins
Ruby classes are open: you can reopen any class — even String or
Integer — and add or change methods.
class Integer
def minutes = self * 60
end
p 5.minutes
300
Changing a class you don't own is called monkey patching. It's
powerful — Rails' 5.minutes and "title".titleize work this way —
and dangerous:
- It's global: every file, every gem in the process sees the change.
- Two libraries adding the same method name silently overwrite each other.
- A future Ruby version may add a method with the same name but different behavior.
Refinements — scoped patches
Refinements limit a patch to the files that ask for it:
module StringExtras
refine String do
def shout = upcase + "!"
end
end
module Loud
using StringExtras
def self.greet = "hello".shout
end
p Loud.greet
p "hello".respond_to?(:shout)
"HELLO!"
false
using StringExtras activates the refinement only from that point to
the end of the file (or of the module body). Everywhere else, String
is untouched.
Guidelines
- In application code, prefer a plain helper method or a small wrapper class over patching core classes.
- If you must patch, use a refinement, or put the patch in a module and
prependit so it shows up inancestorsand can callsuper. - Never monkey patch inside a gem you publish — you'd be changing every user's application.