liveBook · Manning

Refinement

As explained in The Well-Grounded Rubyist, Fourth Edition

refine is a Ruby method that defines a refinement for a class within a block.

Suppose a string needs a `shout` method for one part of a program, but not everywhere. A refinement puts that method in a module and makes it available only where the module is activated. section 13.2.5

module Shout
  refine String do          1
    def shout
      self.upcase + "!!!"
    end
  end
end

class Person
  attr_accessor :name

  using Shout                 2
  def announce
    puts "Announcing #{name.shout}"
  end
end

david = Person.new
david.name = "David"
david.announce  #1

`refine String` defines `shout`; `using Shout` makes it available to the `Person` class, including its `announce` method. section 13.2.5

`refine` takes a class and a block containing the behavior to add. `using` activates the containing module from that point through the end of the class or module definition. Called outside either definition, `using` remains effective through the end of its file; reopening the class in another file does not carry the refinement along. section 13.2.5

This scope matters when changing core behavior. A global override can unexpectedly change code that relies on a method’s original return value—for example, code that tests whether `gsub!` returned `nil`. A refinement keeps the change from overflowing into surrounding code. section 13.2.1

module Shout
  def shout
    self.upcase + "!!!"
  end
end

module ApplyShoutToString
  refine String do
    import_methods Shout
  end
end

class Person
  attr_accessor :name

  using ApplyShoutToString
  def announce
    puts "Announcing #{name.shout}"
  end
end

david = Person.new
david.name = "David"
david.announce  #1

`import_methods` lets a refinement take methods from a separate module instead of defining them directly inside the `refine` block. section 13.2.5

How The Well-Grounded Rubyist, Fourth Edition covers it

How deep it goes
Explains refine, using, class and file boundaries, and import_methods without developing method-lookup internals.
Examples
Demonstrates a scoped String#shout in Person#announce and imports the method from a separate module.
What it assumes
Assumes familiarity with Ruby classes, modules, and methods while introducing refinement syntax through an example.
What you can do after
Apply it via Ruby's refine, using, and import_methods to add behavior within a chosen lexical scope.
How it connects
Contrasts refinements with core-class overrides and connects them to modules and imported methods.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of The Well-Grounded Rubyist, Fourth Edition. The section links point to the parts of the book it draws on.