How to share code between ruby refinements?

♀尐吖头ヾ 提交于 2019-12-11 13:57:22

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!