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.