2011-06-19 15 views
7

Có cách nào nhanh chóng để theo dõi các phương thức đang được gọi trên một đối tượng không? Thông thường, khi tôi làm việc với một viên ngọc ở cấp độ ngay bên dưới giao diện công cộng của họ, tôi gặp phải những lỗi khó theo dõi. Cuối cùng, tôi kết thúc việc theo dõi đối tượng thông qua mã nguồn và giữ mọi thứ trong đầu tôi.Có cách bắt giữ đơn giản để ghi lại các phương thức đang được gọi trên một đối tượng trong Ruby không?

Nhưng sẽ rất tuyệt khi có thể gọi một thứ như #log_method_calls trên một đối tượng sao cho, tất cả các phương pháp được gọi trên đó sẽ được in thành giá trị hoặc thứ gì đó. Có cách nào để thực hiện điều này?

+0

Bạn có thể muốn nhìn vào [ruby-debug] (http://bashdb.sourceforge.net/ruby-debug.html). Nó có một chút của một đường cong học tập, nhưng nó có lẽ sẽ nhiều hơn bù đắp cho nó trong thời gian lưu, cho những gì bạn đang làm. – coreyward

Trả lời

5

Có một số phương pháp để làm điều đó, tùy thuộc vào tình huống.

Nếu có thể tạo đối tượng mới thay vì quan sát được, bạn có thể dễ dàng viết một lớp người quan sát bằng cách sử dụng method_missing.

class LogProxy 
    def initialize obj 
    @obj = obj 
    end 

    def method_missing(name, *args) 
    puts "#{name} => #{args.to_s}" 
    @desk.send(name, *args) 
    end 
end 

Nếu không thể, bạn vẫn có thể sử dụng alias_method. Đó là một chút khó khăn hơn, nhưng sử dụng Module.instance_methods bạn có thể chuỗi mọi phương pháp của bất cứ điều gì.

Cái gì như:

module Logger 

    def self.included(mod) 
    mod.instance_methods.each do |m| 
     next if m =~ /with_logging/ 
     next if m =~ /without_logging/ 

     mod.class_eval do 

     define_method "#{m}_with_logging" do |*args| 
      puts "#{m} called #{args.to_s}" 
      self.send_without_logging "#{m}_without_logging", *args 
     end 

     alias_method "#{m}_without_logging", m 
     alias_method m, "#{m}_with_logging" 
     end 

    end 
    end 

end 

TargetClass.send(:include, Logger) 
+0

Cảm ơn! Hai giải pháp rất thông minh và hợp lý. Giải pháp thứ hai cũng truyền cảm hứng cho ý tưởng mở rộng lớp 'Object' bằng một phương thức như' # log_method_calls' tạo ra một lớp mới với mixin 'Logger' đang bay để bạn có thể thực hiện nó ở bất kỳ điểm nào trong ứng dụng. –

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