Как я могу "заменить" модуль, включенный через функцию включения ruby? - PullRequest
5 голосов
/ 09 марта 2010

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

Я сейчас столкнулся с этим (имена изменены для защиты личности!):

module OldFormHelpers
  def foo
    puts "foo"
  end
  def bar
    puts "bar"
  end
end

module Helpers
  include OldFormHelpers
end

Это дает мне:

Helpers.instance_methods
=> ["bar", "foo"]
Helpers.ancestors
=> [Helpers, OldFormHelpers]

Это код, который я не имею права изменять без разветвления.

Я хочу создать новый модуль;

module BetterFormHelpers
  def foo
    puts "better foo"
  end
end

Для этого необходимо удалить поведение из OldFormHelpers, а затем добавить новый материал из BetterFormHelpers

Предыдущее решение было использовать undef_method примерно так:

Helpers.module_eval do
  OldFormHelpers.instance_methods do |m|
    undef_method(m)
  end
end

Однако после включения BetterFormHelpers файл Helpers.instance_methods не содержит «foo». Причина этого объясняется в http://ruby -doc.org / core / classes / Module.src / M001652.html

Использование remove_method говорит мне, что Helpers не имеет метода "foo", поэтому я думаю, мне нужен какой-то способ удалить первое включение из цепочки предков ...

Это становилось немного длиннее, поэтому я перестал вставлять так много фрагментов ближе к концу, но я добавил сеанс irb, показывающий поведение undef / remove, а затем включение.

1 Ответ

2 голосов
/ 14 июля 2010

Разве вы не можете определить только те методы, которые не будут перезаписаны?

Helpers.module_eval do
  (OldFormHelpers.instance_methods - BetterFormHelpers.instance_methods).each do |m|
    undef_method(m)
  end
end

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

Если вы хотите динамически перезаписать другие методы модуля OldFormHelpers, проблема остается прежней.

...