Class: Puppy::TracedObject

Inherits:
Object show all
Defined in:
lib/puppy.rb

Overview

This is the class which encapsulates every object instances once the Object#trace method is invoked.

Constant Summary collapse

DEFAULTS =
{
	:as     => :class,
	:caller => true,
	:step	  => false,
    :indent => true,
    :stream => STDERR
}

Instance Method Summary collapse

Constructor Details

#initialize(obj, opts = {}, &block) ⇒ TracedObject

Initializes the traced object instance with the original instance, options and conditional tracing block.



70
71
72
73
74
# File 'lib/puppy.rb', line 70

def initialize( obj, opts = {}, &block )
    @is_puppy_traced = true
	@object, @opts, @block = obj, DEFAULTS.merge(opts), block
    @stream = @opts[:stream]
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(m, *args) ⇒ Object

Here it goes, every method invoked on this object will trigger TracedObject#method_missing since we’ve undefined every instance method. This will make us able to print method call and arguments, and then invoke the original method using Object#send on the original instance.



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/puppy.rb', line 100

def method_missing( m, *args )
	begin
		if ( @block == nil || @block.call( @object, m, *args ) == true ) && @is_puppy_traced == true
        @stream << '# '
        @stream << ' ' * caller.size unless !@opts[:indent]

        as = @opts[:as]

        @stream << if as.is_a? Symbol
          @object.send as
        elsif as != nil
          as.to_s
        elsif
          @object.to_s
        end

        @stream << ".#{m}(#{args.map { |a| a.inspect }.join(', ')})"
        @stream << " [#{caller[0]}] " unless @opts[:caller] == false
        @stream << "\n"

			gets unless !@opts[:step]
		end

		@object.send m, *args
	rescue Exception => e
		raise
	end
end

Instance Method Details

#inspectObject

We need this to directly use #inspect on the traced object without the invocation being traced itself.



78
79
80
# File 'lib/puppy.rb', line 78

def inspect
  @object.send :inspect
end

#traceObject

Enables tracing.



86
87
88
# File 'lib/puppy.rb', line 86

def trace
  @is_puppy_traced = true
end

#untraceObject

Disables tracing.



91
92
93
# File 'lib/puppy.rb', line 91

def untrace
  @is_puppy_traced = false
end