Переопределить module_function внутри класса ruby ​​с доступом к оригиналу - PullRequest
0 голосов
/ 10 ноября 2018

Я пытаюсь переопределить вспомогательный метод Rails, который определен так:

class Foo
  module Bar

    def orig
      # orig code
    end

    alias o orig

    module_function :o
    module_function :orig

  end
end

Так что я могу переопределить и добавить функциональность к orig и o примерно так:

def orig
  # new code
  # super (run orig code)
end
alias o orig

Я просмотрел несколько различных методов исправления обезьян , но, похоже, они не работают. Я считаю, что module_function - это то, что его отбрасывает.

Кто-нибудь знает, как мне этого добиться?

Ответы [ 2 ]

0 голосов
/ 10 ноября 2018

Практически любое обстоятельство, когда вы в прошлом использовали патчирование обезьян, в настоящее время может быть решено с помощью наследования и Module#prepend:

module Foo
  def bar(arg)
    "self=#{self}, arg=#{arg}"
  end
  module_function :bar
end

module FooExtension
  def bar(arg)
    super(arg + 1)
  end
end

[Foo, Foo.singleton_class].each do |mod|
  mod.prepend FooExtension
end

Foo.bar(1) #=> "self=Foo, arg=2"

class MyClass
  include Foo
end

MyClass.new.bar(1) #=> "self=#<MyClass:0x00007fb66a86cbf8>, arg=2"
0 голосов
/ 10 ноября 2018

Вот обходной путь. Вы можете повторно открыть модуль, сделать несвязанную ссылку на исходный метод экземпляра, а затем переопределить его, чтобы вызвать оригинальный метод (с некоторым измененным поведением).

Во-первых, оригинальное определение:

module Foo
  def bar(arg)
    "self=#{self}, arg=#{arg}"
  end
  module_function :bar
end

Далее, повторное открытие и переопределение метода:

module Foo
  OrigBarMethod = instance_method(:bar)
  def bar(arg)
    Foo::OrigBarMethod.bind(self).call(arg + 1)
  end
  module_function :bar
end

puts Foo.bar(1) # => "self=Foo, arg=2"

Я использую bind(self), чтобы исходный метод все еще мог использовать self, например:

class MyClass
  include Foo
end

MyClass.new.send(:bar, 1) # => "self=#<MyClass:0x00007fb66a86cbf8>, arg=2"
...