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
