问题
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?
回答1:
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
来源:https://stackoverflow.com/questions/31097733/how-to-share-code-between-ruby-refinements