best way to organize a long piece of code in ruby refinement block

208 views Asked by At
module Access
  def last
    self[-1]
  end

  def start_end
    self[0] + last
  end
end

module StringExt
  refine String do
    include Access
  end
end

using StringExt

puts 'abcd'.last       # => d
puts 'abcd'.start_end

When a class being refined with too many connected methods, I think it is better to extract them to a module. However, in above example which demos a problem when one method calls another(see the last statement), and it produces following error.

in 'start_end': undefined local variable or method 'last' for "abcd":String (NameError)

Similar issue was solved using a global variable, which also works for my example. But I'm seeking another better way to organize inter-called methods being refined and avoid a global thing.

How would advice a better way to organize those methods?

1

There are 1 answers

0
max pleaner On BEST ANSWER

Here's a general pattern I ended up using. Basically I found no workaround for using global identifiers at some level. But this can be done fairly cleanly by making those globals classes/modules. This will be more clear as an example:

module StringPatches

  def self.non_empty?(string)
    !string.empty?
  end

  def non_empty?
    StringPatches.non_empty?(self)
  end

  def non_non_empty?
    !StringPatches.non_empty?(self)
  end

  refine String do
    include StringPatches
  end

end

class Foo
  using StringPatches
  puts "asd".non_empty? # => true
  puts "asd".non_non_empty? # => false
end

The class methods on StringPatches don't get exported to using. But since classes/modules are constants (globals) they can be accessed from anywhere.