1
module Ext
  refine Hash do
    def foo
      puts :in_foo
    end
    def bar
      puts :in_bar
      foo
    end
  end
end
module Test
  using Ext
  Hash.new.bar
end
# in_bar
# in_foo
# => nil

This works as expected. But if I want to share foo and bar between Hash and Array by using include, it fails.

module Shared
  def foo
    puts :in_foo
  end
  def bar
    puts :in_bar
    foo
  end
end
module Ext
  refine Hash do
    include Shared
  end
  refine Array do
    include Shared
  end
end
module Test
  using Ext
  Hash.new.bar
end
# in_bar
# NameError: undefined local variable or method `foo' for {}:Hash

Is there any way to share code between refinements?

chifung7
  • 2,531
  • 1
  • 19
  • 17

1 Answers1

0

The problem is not in sharing. Get rid of Array refinement totally and you’ll yield the same behaviour.

Accordingly to the documentation:

Refinements are active until the end of the file or the end of the eval string, respectively. Refinements are lexical in scope. When control is transferred outside the scope the refinement is deactivated. This means that if you require or load a file or call a method that is defined outside the current scope the refinement will be deactivated.

That said, what fails in your examples is refine do ⇒ include. The language is not ready to understand include inside refine clause. Maybe it would be possible in the future, when the feature will raise out of “experimental” stage.

In case you still think you want to rely on refinemenets, you might cheat ruby (globals are for a sake of idea clarity):

$ref = lambda do
  def foo
    puts :in_foo
  end
  public :foo
  def bar
    puts :in_bar
    foo
  end
  public :bar
end
module Ext
  refine ::Hash do
    $ref.call
  end
end
module Test
  using Ext
  ::Hash.new.bar
end

#⇒ in_bar
#⇒ in_foo
Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
  • The original code is monkey patching `Hash` and `Array` by re-opening them to `include Shared`. I thought that refinement might get ride of the monkey paching. – chifung7 Jun 28 '15 at 14:53