Ruby Refinements


#1

I thought I understood Ruby refinements but now I just realized that a Using statement is required in every file before the module declaration. Is there a way to make a refinement global to a module without adding a using statement to every file?

module Smith
  module Smith::Refinements
    refine String do
      def numeric?
        Float(self) != nil rescue false
      end
    end
  end
end


using Smith::Refinements
module Smith
  def self.test1
    return '1'.numeric?
  end
end
Smith.test1 #returns true

#execute this as a separate file or paste into ruby console separate from above
module Smith
  def self.test2
    return '1'.numeric?
  end
end
Smith.test2 #returns undefined method

#2

I don’t think so. There is an explanation for it somewhere.

Also be aware that the implementation is evolving. In Ruby 2.0 the using statement needs to be in the top level ObjectSpace. But in later Ruby versions, you can put them inside class blocks and the refinements will only apply to that scope within that file.

EDIT: It looks like class scopes were added in Ruby 2.3 which SketchUp does not yet use.
(SketchUp 2018 still uses Ruby 2.2.4.)


Note that the documentation for refinements has lagged behind the actual implementation details.
I think last I looked, that the docs still stated that using statements need to be in the top level even though module and class scope was implemented.


Other 3rd party blogs etc.

… see full Google search …


#3

It looks like class scopes were added in Ruby 2.3 which SketchUp does not yet use.
(SketchUp 2018 still uses Ruby 2.2.4.)