Как разделить код между уточнениями ruby?

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

Это работает как ожидалось. Но если я хочу поделиться foo а также bar между Hash а также Array используя include, это не удается.

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

Есть ли способ поделиться кодом между уточнениями?

1 ответ

Проблема не в том, чтобы делиться. Избавляться от Array уточнение полностью, и вы получите то же самое поведение.

Согласно документации:

Уточнения активны до конца файла или до конца строки eval, соответственно. Уточнения носят лексический характер. Когда контроль переносится за пределы области, уточнение деактивируется. Это означает, что если вам требуется или загрузить файл или вызвать метод, который определен вне текущей области, уточнение будет деактивировано.

Тем не менее, то, что не удается в ваших примерах refine do ⇒ include, Язык не готов к пониманию include внутри refine пункт. Возможно, это будет возможно в будущем, когда функция выйдет из "экспериментальной" стадии.

Если вы все еще думаете, что хотите полагаться на доработки, вы можете обмануть ruby ​​(глобальные значения для ясности идеи):

$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
Другие вопросы по тегам