putter 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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:
|