Refinements
A refinement is a scoped way to add or override methods on an existing class, active only in the file that opts in with using — making it far safer than global monkey-patching.
Learn Refinements in our free Ruby course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.
Part of the free Ruby course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
In this lesson you'll extend built-in classes like String and Integer without polluting them for the whole program.
What You'll Learn in This Lesson
1️⃣ Defining and Using a Refinement
Wrap a refine TargetClass do ... end block inside a module. The methods you add aren't visible until some file calls using YourModule . Before that, calling the new method raises NoMethodError — proof the change is genuinely opt-in.
2️⃣ Lexical Scope: Where a Refinement Lives
A refinement is lexically scoped: it applies to code written after using in the same file, and nowhere else. You can read the source and know exactly where it's active — there's no spooky action affecting code in other files, even code your refined methods call.
3️⃣ Safer Than Open Classes
Re-opening a built-in class changes it for the entire program, including third-party gems — a recipe for hard-to-trace conflicts. A refinement keeps the change local: outside the using scope, respond_to? still returns false , so nothing you didn't opt into can break.
🎯 Your Turn
The refinement is defined but switched off. Replace the ___ with the keyword that activates it for the file.
Add a scoped Array#second and String#blank? in one module, and prove they're invisible until using . Run with ruby extras.rb .
📋 Quick Reference — Refinements
Practice quiz
What is a refinement in Ruby?
- A global change to a class
- A new kind of module
- A scoped modification to an existing class
- A way to delete methods
Answer: A scoped modification to an existing class. A refinement is a scoped change to an existing class, opted into per file.
Which keyword defines a refinement inside a module?
- refine
- extend
- include
- prepend
Answer: refine. You define a refinement with refine SomeClass do ... end inside a module.
Which keyword activates a refinement?
- require
- import
- with
- using
Answer: using. using ThatModule turns the refinement on for the current file scope.
Before calling using, what happens if you call the refined method?
- It works globally
- It raises NoMethodError
- It returns nil
- It returns false
Answer: It raises NoMethodError. Until you call using, the method doesn't exist, so it raises NoMethodError.
What does 'lexically scoped' mean for refinements?
- Active based on where the code is written
- Active based on the runtime call chain
- Active everywhere once loaded
- Active only in tests
Answer: Active based on where the code is written. Lexical scope means activation depends on where using is written, not the call chain.
Why are refinements safer than open-class monkey-patching?
- They run faster
- They can't override methods
- The change is local to code that opts in, avoiding global pollution
- They are compiled
Answer: The change is local to code that opts in, avoiding global pollution. Code that hasn't called using never sees the change, so there's no global conflict.
Outside a refinement's scope, what does 5.respond_to?(:dollars) return for a refined Integer#dollars?
- true
- false
- nil
- an error
Answer: false. Outside the using scope the method isn't visible, so respond_to? is false.
Where must refine be written?
- At the top level
- Inside any method
- Inside a class only
- Inside a module
Answer: Inside a module. refine must be nested inside a module, otherwise Ruby raises an error.
Can using be placed inside an arbitrary method body?
- Yes, anywhere
- No, only at top level or module scope
- Only in class methods
- Only in lambdas
Answer: No, only at top level or module scope. using is allowed at top-level or module scope, not inside an arbitrary method body.
Can one module hold several refine blocks for different classes?
- No, one per module
- Only two
- Yes, group related tweaks together
- Only for built-in classes
Answer: Yes, group related tweaks together. A single module can contain multiple refine blocks for different classes.