2010-03-09 2 views
5

후속편으로 How can I reverse ruby's include function까지 답변을 드렸지 만 실제 문제를 간략화하여 해결 방법이 적용되지 않았다는 것을 알았습니다. 내가 지금이 직면하고있어루비를 통해 포함 된 모듈을 "대체"할 수있는 기능은 무엇입니까?

(이름은 신원을 보호하기 위해 변경!) :

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] 

이 정말에 액세스 할 수없는 코드가 수정없이, 포크없이.

내가 원하는 것은 새로운 모듈을 만드는 것입니다.

OldFormHelpers에서 행동을 제거하고 BetterFormHelpers

이전 솔루션에서 새로운 물건을 추가 할 필요가

module BetterFormHelpers 
    def foo 
    puts "better foo" 
    end 
end 

은과 같이 undef_method을 사용하는 것이었다 :

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

그러나, 포함한 후 BetterFormHelpers, Helpers.instance_methods에는 "foo"가 포함되어 있지 않습니다. ... 그 이유는 Helpers는 "foo는"방법이 없음을 알려줍니다 http://ruby-doc.org/core/classes/Module.src/M001652.html

remove_method 사용에 설명되어 있습니다, 그래서 내가 조상 체인에서 첫 번째 포함을 제거하는 방법이 필요 추측

이것은 조금 길어지고 끝까지 많은 스 니펫을 넣는 것을 중단했지만, undef/remove와 그 다음 include의 동작을 보여주는 irb 세션을 추가합니다.

+0

"수정하기 위해 실제로 액세스 할 수없는 코드입니다.": 원숭이 패치는 옵션이 아닙니까? –

+0

원숭이 패치는 일종의 옵션입니다.하지만 우리가 교체 할 모듈이 작동하는 방식에 따라 모듈을 정의한 다음 포함시킵니다. 포함 사태를 막기 위해이 체인의 어딘가에 코드를 삽입하는 것은 매우 까다로운 작업입니다. 이 라인을 잠시 후에 추측했지만, 나는 그 방향으로 더 기울기 시작했습니다. – Glenjamin

답변

2

덮어 쓰지 않는 메소드 만 정의 해제 할 수 있습니까?

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

은 (BetterFormHelpers는 또한 그것을 정의하는 경우에는 OldFormHelpers 메소드가 실행되지 않도록 후자 포함 모듈은 먼저 검색됩니다.)

동적으로 OldFormHelpers 모듈의 추가 방법을 덮어 쓰려면

을하지만, 문제는 동일하게 유지됩니다.

관련 문제