putter 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +2 -0
- data/README.md +53 -8
- data/lib/putter/follower.rb +5 -8
- data/lib/putter/instance_follower.rb +11 -0
- data/lib/putter/method_creator.rb +16 -0
- data/lib/putter/print_strategy.rb +5 -4
- data/lib/putter/proxy_method_data.rb +16 -0
- data/lib/putter/version.rb +1 -1
- data/lib/putter/watcher.rb +53 -0
- data/lib/putter.rb +10 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7b61e558de7dab6687ddc1e44fcb1a66ae6a4669
|
4
|
+
data.tar.gz: 23a571a29ea9c44223a86e9762d02d5eb13d7352
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b700661ef9567e2e9f5b19880a491f0e37f7b7fd32597e024a04c0fd18df13bf5147add15a3dc49956a92850e0eb31df52eb13b1c89d0e31d03e00978f59b5d8
|
7
|
+
data.tar.gz: a5c554a5f52c2181a8d39cedfbeb50950a4b3d5420c1f99cf453f08797edd4b44e25a8d307f36d1265c18d3aab53b9f30290460c2e4cd28df913bfead72d3915
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -24,9 +24,15 @@ Or install it yourself as:
|
|
24
24
|
|
25
25
|
## Usage
|
26
26
|
|
27
|
+
There are two ways to use putter. `Putter.follow` and `Putter.watch`.
|
28
|
+
|
27
29
|
### Putter.follow
|
28
30
|
|
29
|
-
|
31
|
+
`Putter.follow` will allow you to create a wrapper around an object and then you can pass that wrapped object around. The advantage to using follow is that if a method is called that doesn't exist, or a method is created at runtime, the wrapped object will intercept those calls. This works on both instances and classes. However, following a class will not result in created instances of that class being followed.
|
32
|
+
|
33
|
+
Additionally, following an object will not allow you to intercept calls to a class that occurred outside the wrapped object. For that functionality, use `Putter.watch`
|
34
|
+
|
35
|
+
`Putter.follow` usage:
|
30
36
|
|
31
37
|
```ruby
|
32
38
|
class MyObject
|
@@ -48,7 +54,7 @@ Service.do_stuff(object)
|
|
48
54
|
Will output:
|
49
55
|
|
50
56
|
```bash
|
51
|
-
Putter Debugging: Object instance -- Method: :hello, Args: [:world, "!"], Result: "Hello world!"
|
57
|
+
Putter Debugging: Object instance ./putter/README.md:57 -- Method: :hello, Args: [:world, "!"], Result: "Hello world!"
|
52
58
|
```
|
53
59
|
|
54
60
|
#### `Putter.follow` Options
|
@@ -61,18 +67,58 @@ Putter.follow(
|
|
61
67
|
)
|
62
68
|
```
|
63
69
|
|
70
|
+
### Putter.watch
|
71
|
+
|
72
|
+
`Putter.watch` can be used on classes to follow created instances of the class or to intercept method calls that occur throughout your application.
|
73
|
+
|
74
|
+
`Putter.follow` usage:
|
75
|
+
|
76
|
+
```ruby
|
77
|
+
class MyObject
|
78
|
+
def self.hello_class(arg, punc)
|
79
|
+
"The class says hello #{arg.to_s}#{punc}"
|
80
|
+
end
|
81
|
+
|
82
|
+
def hello_instance(arg, punc)
|
83
|
+
"An instance says hello #{arg.to_s}#{punc}"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
Putter.watch(MyObject)
|
88
|
+
MyObject.hello_class("world", "!")
|
89
|
+
my_obj = MyObject.new
|
90
|
+
my_obj.hello_instance("world", "!")
|
91
|
+
```
|
92
|
+
|
93
|
+
Will output:
|
94
|
+
|
95
|
+
```bash
|
96
|
+
Putter Debugging: Object ./putter/README.md:96 -- Method: :hello_class, Args: [:world, "!"], Result: "The class says hello world!"
|
97
|
+
Putter Debugging: Object instance 1 ./putter/README.md:97 -- Method: :hello_instance, Args: [:world, "!"], Result: "The instance says hello world!"
|
98
|
+
```
|
99
|
+
|
100
|
+
#### `Putter.follow` Options
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
Putter.watch(
|
104
|
+
ClassToFollow,
|
105
|
+
label: "My object", # Label to use after "Putter Debugging: My object". Will be "ClassName" for classes or "ClassName instance #" for instances
|
106
|
+
)
|
107
|
+
```
|
108
|
+
|
64
109
|
## Configuration
|
65
110
|
|
66
111
|
Putter currently has 3 configuration options:
|
67
112
|
|
68
113
|
```ruby
|
69
114
|
Putter.configure do |config|
|
70
|
-
# 'print_strategy' takes a block that receives
|
71
|
-
# and result respectively. This block will be used after each method
|
72
|
-
# puts or logger calls, to print or any other method callbacks
|
115
|
+
# 'print_strategy' takes a block that receives five arguments with the label, line,
|
116
|
+
# method, args array, and result respectively. This block will be used after each method
|
117
|
+
# is called, it must contain puts or logger calls, to print or any other method callbacks
|
118
|
+
# that are helpful.
|
73
119
|
# Defaults to Putter::PrintStrategy::Default
|
74
|
-
config.print_strategy = Proc.new do |label, method, args, result|
|
75
|
-
puts "Label: #{label}, Method: #{method}, Args: #{args}, Result: #{result}"
|
120
|
+
config.print_strategy = Proc.new do |label, line, method, args, result|
|
121
|
+
puts "#{line} - Label: #{label}, Method: #{method}, Args: #{args}, Result: #{result}"
|
76
122
|
end
|
77
123
|
|
78
124
|
# 'ignore_methods_from' takes an array of class names and will ignore both class and instance methods
|
@@ -90,7 +136,6 @@ end
|
|
90
136
|
## Planned Features
|
91
137
|
Feel free to open a PR to implement any of these if they are not yet added:
|
92
138
|
|
93
|
-
- Ability to watch any instance of a class calling a method
|
94
139
|
- Active Record specific printing
|
95
140
|
- Checking Rails.env to double check that putter is not called in production
|
96
141
|
|
data/lib/putter/follower.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
module Putter
|
2
2
|
class Follower < BasicObject
|
3
|
+
include MethodCreator
|
4
|
+
|
3
5
|
attr_reader :object, :proxied_methods, :proxy
|
4
6
|
|
5
7
|
def initialize(obj, options={})
|
@@ -26,14 +28,9 @@ module Putter
|
|
26
28
|
end
|
27
29
|
|
28
30
|
def add_method(method)
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
result = super *proxy_args, &blk
|
33
|
-
::Putter.configuration.print_strategy.call label, method, args_string, result
|
34
|
-
result
|
35
|
-
end
|
36
|
-
end
|
31
|
+
data = ProxyMethodData.new(method, @label)
|
32
|
+
|
33
|
+
add_putter_method_to_proxy(@proxy, :instance_exec, data)
|
37
34
|
end
|
38
35
|
|
39
36
|
def _add_method?(method)
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Putter
|
2
|
+
module InstanceFollower
|
3
|
+
@@putter_followed_instances = []
|
4
|
+
|
5
|
+
def new(*args, &blk)
|
6
|
+
result = super *args, &blk
|
7
|
+
@@putter_followed_instances << result
|
8
|
+
::Putter.follow(result, label: "#{name} instance #{@@putter_followed_instances.count}")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Putter
|
2
|
+
module MethodCreator
|
3
|
+
def add_putter_method_to_proxy(proxy, eval_method, data)
|
4
|
+
proxy.send(eval_method, data) do |data|
|
5
|
+
define_method(data.method) do |*proxy_args, &blk|
|
6
|
+
line = caller.find {|call| call.match(data.stack_trace_ignore_regex)}
|
7
|
+
line = line.split(::Dir.pwd)[1]
|
8
|
+
args_string = proxy_args.to_s
|
9
|
+
result = super *proxy_args, &blk
|
10
|
+
::Putter.configuration.print_strategy.call data.label, line, data.method, args_string, result
|
11
|
+
result
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -2,10 +2,11 @@ require "colorize"
|
|
2
2
|
|
3
3
|
module Putter
|
4
4
|
module PrintStrategy
|
5
|
-
Default = Proc.new do |label, method, args, result|
|
6
|
-
prefix = "\tPutter Debugging: ".colorize(:cyan)
|
7
|
-
|
8
|
-
|
5
|
+
Default = Proc.new do |label, line, method, args, result|
|
6
|
+
prefix = "\tPutter Debugging: #{label} ".colorize(:cyan)
|
7
|
+
line = !line.nil? ? ".#{line} " : " "
|
8
|
+
suffix = "-- Method: :#{method}, Args: #{args}, Result: #{result}".colorize(:green)
|
9
|
+
puts prefix + line + suffix
|
9
10
|
end
|
10
11
|
end
|
11
12
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Putter
|
2
|
+
class ProxyMethodData
|
3
|
+
STACK_TRACE_IGNORE_REGEX = /(?!.*(\.rbenv|\.rvm|\/lib\/putter\/follower))(^.*$)/
|
4
|
+
|
5
|
+
attr_reader :method, :label
|
6
|
+
|
7
|
+
def initialize(method, label)
|
8
|
+
@method = method
|
9
|
+
@label = label
|
10
|
+
end
|
11
|
+
|
12
|
+
def stack_trace_ignore_regex
|
13
|
+
STACK_TRACE_IGNORE_REGEX
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/putter/version.rb
CHANGED
@@ -0,0 +1,53 @@
|
|
1
|
+
module Putter
|
2
|
+
class Watcher
|
3
|
+
extend MethodCreator
|
4
|
+
|
5
|
+
@label = ""
|
6
|
+
|
7
|
+
def self.watch(obj, options={})
|
8
|
+
_set_label(options[:label], obj.name)
|
9
|
+
|
10
|
+
class << obj
|
11
|
+
prepend InstanceFollower
|
12
|
+
prepend Putter::Watcher.class_proxy(self)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.class_proxy(klass)
|
17
|
+
proxy = MethodProxy.new
|
18
|
+
|
19
|
+
methods_to_proxy(klass).each do |method|
|
20
|
+
data = ProxyMethodData.new(method, label)
|
21
|
+
add_putter_method_to_proxy(proxy, :module_exec, data)
|
22
|
+
end
|
23
|
+
|
24
|
+
proxy
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.methods_to_proxy(klass)
|
28
|
+
ignored_methods = []
|
29
|
+
|
30
|
+
Putter.configuration.ignore_methods_from.each do |klass|
|
31
|
+
ignored_methods += klass.methods
|
32
|
+
end
|
33
|
+
|
34
|
+
klass.instance_methods - ignored_methods + Putter.configuration.methods_whitelist.map(&:to_sym) + [:new]
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.label
|
38
|
+
@label
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.label=(label)
|
42
|
+
@label = label
|
43
|
+
end
|
44
|
+
|
45
|
+
def self._set_label(label, class_name)
|
46
|
+
if !label.nil? && label != ""
|
47
|
+
@label = label
|
48
|
+
else
|
49
|
+
@label = class_name
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/putter.rb
CHANGED
@@ -1,10 +1,15 @@
|
|
1
1
|
require "putter/configuration"
|
2
2
|
require "putter/errors"
|
3
|
-
require "putter/
|
3
|
+
require "putter/instance_follower"
|
4
|
+
require "putter/method_creator"
|
4
5
|
require "putter/method_proxy"
|
5
6
|
require "putter/print_strategy"
|
7
|
+
require "putter/proxy_method_data"
|
6
8
|
require "putter/version"
|
7
9
|
|
10
|
+
require "putter/follower"
|
11
|
+
require "putter/watcher"
|
12
|
+
|
8
13
|
module Putter
|
9
14
|
include Errors
|
10
15
|
|
@@ -16,6 +21,10 @@ module Putter
|
|
16
21
|
Putter::Follower.new(obj, options)
|
17
22
|
end
|
18
23
|
|
24
|
+
def self.watch(obj, options={})
|
25
|
+
Putter::Watcher.watch(obj, options)
|
26
|
+
end
|
27
|
+
|
19
28
|
def self.configuration
|
20
29
|
@configuration ||= Configuration.new
|
21
30
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: putter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John DeWyze
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-07-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|
@@ -109,9 +109,13 @@ files:
|
|
109
109
|
- lib/putter/configuration.rb
|
110
110
|
- lib/putter/errors.rb
|
111
111
|
- lib/putter/follower.rb
|
112
|
+
- lib/putter/instance_follower.rb
|
113
|
+
- lib/putter/method_creator.rb
|
112
114
|
- lib/putter/method_proxy.rb
|
113
115
|
- lib/putter/print_strategy.rb
|
116
|
+
- lib/putter/proxy_method_data.rb
|
114
117
|
- lib/putter/version.rb
|
118
|
+
- lib/putter/watcher.rb
|
115
119
|
- putter.gemspec
|
116
120
|
homepage: https://github.com/dewyze/putter
|
117
121
|
licenses:
|