2010-03-09 24 views
5

Theo dõi tới How can I reverse ruby's include function, được trả lời tốt nhưng hóa ra sự đơn giản hóa vấn đề thực sự của tôi không phải là giải pháp không áp dụng được.Làm thế nào tôi có thể "thay thế" một mô-đun được bao gồm thông qua ruby ​​bao gồm chức năng

Tôi bây giờ phải đối mặt với điều này (tên đã thay đổi để bảo vệ bản sắc!):

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

module Helpers 
    include OldFormHelpers 
end 

này mang lại cho tôi:

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

Đây là mã mà tôi không thực sự có quyền truy cập vào sửa đổi, mà không forking.

Điều tôi muốn làm là tạo mô-đun mới;

module BetterFormHelpers 
    def foo 
    puts "better foo" 
    end 
end 

này cần phải loại bỏ các hành vi từ OldFormHelpers, và sau đó thêm vào những thứ mới từ BetterFormHelpers

Các giải pháp trước đây là sử dụng undef_method như vậy:

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

Tuy nhiên, sau đó BetterFormHelpers, Helpers.instance_methods không chứa "foo". Lý do cho điều này được giải thích tại http://ruby-doc.org/core/classes/Module.src/M001652.html

Sử dụng remove_method nói với tôi rằng Helpers không có phương pháp "foo", vì vậy tôi đoán tôi cần một số cách loại bỏ sự bao gồm đầu tiên kể từ chuỗi tổ tiên ...

Điều này đã nhận được một chút lâu vì vậy tôi đã ngừng đặt quá nhiều đoạn mã vào cuối, nhưng tôi thêm một phiên irb cho thấy hành vi của undef/remove và sau đó là một bao gồm.

+0

"Đây là mã mà tôi không thực sự có quyền truy cập để sửa đổi": Bản vá khỉ không phải là một tùy chọn? –

+0

Khỉ vá là một lựa chọn, loại - nhưng cách mô-đun chúng tôi đang thay thế công trình, Nó xác định các mô-đun và sau đó bao gồm chúng - nó khá phức tạp để tiêm mã một nơi nào đó vào chuỗi này để ngăn chặn bao gồm xảy ra. Mặc dù sau khi theo đuổi dòng này trong một thời gian, tôi bắt đầu nghiêng nhiều hơn theo hướng đó. – Glenjamin

Trả lời

2

Bạn không thể xác định chỉ các phương pháp sẽ không bị ghi đè?

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

(Các module bao gồm sau này sẽ được tìm kiếm đầu tiên để không có phương pháp OldFormHelpers sẽ được thực hiện nếu BetterFormHelpers cũng định nghĩa nó.)

Nếu bạn muốn tự động ghi đè lên các phương pháp hơn nữa của các mô-đun OldFormHelpers, tuy nhiên, vấn đề vẫn giữ nguyên.

Các vấn đề liên quan