Refinements in Ruby: in map: super: no superclass method


I was trying out refinements to see if they would help clean up some parsing code. I liked defining a couple of methods for the String class to respond to, but really didn’t want them as permanent monkey patches on String.

And so, I had a pipe mapping module with refinements:

module PipeMapping
  refine String do
    def only_lines_with_pipes
      self.lines.select { |s| s =~ /\|/ }
    end
    def pipes_to_array
      self.split('|').map(&:strip)
    end
  end
end

I added the following to my class to allow it to load itself:

  using PipeMapping
  def self.initalize_mappings
    data_to_load.only_lines_with_pipes.map(&:pipes_to_array).each do |mapping|
      # do stuff
    end
  end

I got the following output:

...in `map': super: no superclass method `pipes_to_array' for "A|B|C\n":String (NoMethodError)

The problem is that Symbol#to_proc will end up operating outside of the scope of the refinement using invocation, and will, therefore, have no knowledge of the method.

A quick change to a block works:

  using PipeMapping
  def self.initalize_mappings
    data_to_load.only_lines_with_pipes.map{|s| s.pipes_to_array}.each do |mapping|
      # do stuff
    end
  end

I’m still trying to decide if this is a satisfactory trade-off.


%d bloggers like this: