tapping_device 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/gempush.yml +28 -0
- data/.github/workflows/ruby.yml +9 -3
- data/Gemfile.lock +22 -0
- data/README.md +68 -37
- data/lib/tapping_device/trackable.rb +40 -9
- data/lib/tapping_device/version.rb +1 -1
- data/tapping_device.gemspec +8 -0
- metadata +32 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31bb339b2993e3656c953c0c403b4145d3047722919f86ab4d0683c577379027
|
4
|
+
data.tar.gz: 76b0b6fab4f3998173960d3a0bce5bdc6faa8155bc49fe4ec3a0ecd0196e8feb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7641adbd68125ce2cb1a2fdb96969d09dcedc8d35b0c24fc1e0136badaca586bf7287631c3b6fecc7d3909958e0c49bd2d05d2de3b41845f680fb19165ccab1e
|
7
|
+
data.tar.gz: f9d685094c3f45b3e330c2725fc61bc01a9ae11cb5e486a1fec5de9a2131860cd64160e1d83753210529dc3383523d8072437e8ff285fc589b6bb6aafe5fcf5c
|
@@ -0,0 +1,28 @@
|
|
1
|
+
name: Ruby Gem
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
tags:
|
6
|
+
- v*
|
7
|
+
|
8
|
+
jobs:
|
9
|
+
build:
|
10
|
+
name: Build + Publish
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
|
13
|
+
steps:
|
14
|
+
- uses: actions/checkout@master
|
15
|
+
- name: Set up Ruby 2.6
|
16
|
+
uses: actions/setup-ruby@v1
|
17
|
+
with:
|
18
|
+
version: 2.6.x
|
19
|
+
- name: Publish to RubyGems
|
20
|
+
run: |
|
21
|
+
mkdir -p $HOME/.gem
|
22
|
+
touch $HOME/.gem/credentials
|
23
|
+
chmod 0600 $HOME/.gem/credentials
|
24
|
+
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
25
|
+
gem build *.gemspec
|
26
|
+
gem push *.gem
|
27
|
+
env:
|
28
|
+
GEM_HOST_API_KEY: ${{secrets.RUBYGEMS_AUTH_TOKEN}}
|
data/.github/workflows/ruby.yml
CHANGED
@@ -4,11 +4,12 @@ on: [push]
|
|
4
4
|
|
5
5
|
jobs:
|
6
6
|
test:
|
7
|
-
name: Test on ruby ${{ matrix.ruby_version }}
|
7
|
+
name: Test on ruby ${{ matrix.ruby_version }} and rails ${{ matrix.rails_version }}
|
8
8
|
runs-on: ${{ matrix.os }}
|
9
9
|
strategy:
|
10
10
|
matrix:
|
11
|
-
|
11
|
+
rails_version: ['5.2', '6']
|
12
|
+
ruby_version: ['2.5', '2.6']
|
12
13
|
os: [ubuntu-latest]
|
13
14
|
steps:
|
14
15
|
- uses: actions/checkout@v1
|
@@ -16,8 +17,13 @@ jobs:
|
|
16
17
|
uses: actions/setup-ruby@v1
|
17
18
|
with:
|
18
19
|
ruby-version: ${{ matrix.ruby_version }}
|
20
|
+
- name: Install sqlite
|
21
|
+
run: |
|
22
|
+
sudo apt-get install libsqlite3-dev
|
19
23
|
|
20
|
-
- name: Build and test with
|
24
|
+
- name: Build and test with Rails ${{ matrix.rails_version }}
|
25
|
+
env:
|
26
|
+
RAILS_VERSION: ${{ matrix.rails_version }}
|
21
27
|
run: |
|
22
28
|
gem install bundler
|
23
29
|
bundle install --jobs 4 --retry 3
|
data/Gemfile.lock
CHANGED
@@ -2,13 +2,29 @@ PATH
|
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
4
|
tapping_device (0.1.0)
|
5
|
+
activerecord (~> 6.0)
|
5
6
|
|
6
7
|
GEM
|
7
8
|
remote: https://rubygems.org/
|
8
9
|
specs:
|
10
|
+
activemodel (6.0.0)
|
11
|
+
activesupport (= 6.0.0)
|
12
|
+
activerecord (6.0.0)
|
13
|
+
activemodel (= 6.0.0)
|
14
|
+
activesupport (= 6.0.0)
|
15
|
+
activesupport (6.0.0)
|
16
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
17
|
+
i18n (>= 0.7, < 2)
|
18
|
+
minitest (~> 5.1)
|
19
|
+
tzinfo (~> 1.1)
|
20
|
+
zeitwerk (~> 2.1, >= 2.1.8)
|
9
21
|
coderay (1.1.2)
|
22
|
+
concurrent-ruby (1.1.5)
|
10
23
|
diff-lcs (1.3)
|
24
|
+
i18n (1.7.0)
|
25
|
+
concurrent-ruby (~> 1.0)
|
11
26
|
method_source (0.9.2)
|
27
|
+
minitest (5.12.2)
|
12
28
|
pry (0.12.2)
|
13
29
|
coderay (~> 1.1.0)
|
14
30
|
method_source (~> 0.9.0)
|
@@ -26,6 +42,11 @@ GEM
|
|
26
42
|
diff-lcs (>= 1.2.0, < 2.0)
|
27
43
|
rspec-support (~> 3.8.0)
|
28
44
|
rspec-support (3.8.2)
|
45
|
+
sqlite3 (1.4.1)
|
46
|
+
thread_safe (0.3.6)
|
47
|
+
tzinfo (1.2.5)
|
48
|
+
thread_safe (~> 0.1)
|
49
|
+
zeitwerk (2.2.0)
|
29
50
|
|
30
51
|
PLATFORMS
|
31
52
|
ruby
|
@@ -35,6 +56,7 @@ DEPENDENCIES
|
|
35
56
|
pry
|
36
57
|
rake (~> 10.0)
|
37
58
|
rspec (~> 3.0)
|
59
|
+
sqlite3 (~> 1.4.1)
|
38
60
|
tapping_device!
|
39
61
|
|
40
62
|
BUNDLED WITH
|
data/README.md
CHANGED
@@ -2,17 +2,14 @@
|
|
2
2
|
|
3
3
|
![](https://github.com/st0012/tapping_device/workflows/Ruby/badge.svg)
|
4
4
|
|
5
|
-
`tapping_device` is a gem
|
5
|
+
`tapping_device` is a gem built on top of Ruby’s `TracePoint` class that allows you to tap method calls of specified objects. The purpose for this gem is to make debugging Rails applications easier. For example, you can use it to see who calls you `Post` records
|
6
6
|
|
7
7
|
```ruby
|
8
8
|
class PostsController < ApplicationController
|
9
9
|
include TappingDevice::Trackable
|
10
10
|
|
11
|
-
before_action :set_post, only: [:show, :edit, :update, :destroy]
|
12
|
-
|
13
|
-
# GET /posts/1
|
14
|
-
# GET /posts/1.json
|
15
11
|
def show
|
12
|
+
@post = Post.find(params[:id])
|
16
13
|
tap_on!(@post) do |payload|
|
17
14
|
puts "Method: #{payload[:method_name]} line: #{payload[:filepath]}:#{payload[:line_number]}"
|
18
15
|
end
|
@@ -23,12 +20,28 @@ end
|
|
23
20
|
And you can see these in log:
|
24
21
|
|
25
22
|
```
|
26
|
-
Method: name line: /
|
27
|
-
Method: user_id line: /
|
28
|
-
Method: to_param line: /
|
23
|
+
Method: name line: /PROJECT_PATH/sample/app/views/posts/show.html.erb:5
|
24
|
+
Method: user_id line: /PROJECT_PATH/sample/app/views/posts/show.html.erb:10
|
25
|
+
Method: to_param line: /RUBY_PATH/gems/2.6.0/gems/actionpack-5.2.0/lib/action_dispatch/routing/route_set.rb:236
|
26
|
+
```
|
27
|
+
|
28
|
+
Or you can use `tap_assoc!`. This is very useful for tracking potential n+1 query calls, here’s a sample from my work
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
tap_assoc!(order) do |payload|
|
32
|
+
puts "Assoc: #{payload[:method_name]} line: #{payload[:filepath]}:#{payload[:line_number]}"
|
33
|
+
end
|
34
|
+
```
|
35
|
+
|
36
|
+
```
|
37
|
+
Assoc: payments line: /RUBY_PATH/gems/2.6.0/gems/jsonapi-resources-0.9.10/lib/jsonapi/resource.rb:124
|
38
|
+
Assoc: line_items line: /MY_PROJECT/app/models/line_item_container_helpers.rb:44
|
39
|
+
Assoc: effective_line_items line: /MY_PROJECT/app/models/line_item_container_helpers.rb:110
|
40
|
+
Assoc: amending_orders line: /MY_PROJECT/app/models/order.rb:385
|
41
|
+
Assoc: amends_order line: /MY_PROJECT/app/models/order.rb:432
|
29
42
|
```
|
30
43
|
|
31
|
-
**Don't use this on production**
|
44
|
+
However, depending on the size of your application, tapping any object could **harm the performance significantly**. **Don't use this on production**
|
32
45
|
|
33
46
|
|
34
47
|
## Installation
|
@@ -55,24 +68,26 @@ $ gem install tapping_device
|
|
55
68
|
In order to use `tapping_device`, you need to include `TappingDevice::Trackable` module in where you want to track your code.
|
56
69
|
|
57
70
|
### Methods
|
58
|
-
- `
|
59
|
-
|
60
|
-
- `
|
61
|
-
|
62
|
-
- `stop_tapping!(object)` - this stops tapping on the given object
|
63
|
-
- shortcut - `untap!`
|
71
|
+
- `tap_init!(class)` - tracks a class’ instance initialization
|
72
|
+
- `tap_on!(object)` - tracks any calls received by the object
|
73
|
+
- `tap_assoc!(activerecord_object)` - tracks association calls on a record, like `post.comments`
|
74
|
+
- `untap!(object)` - this stops tapping on the given object
|
64
75
|
|
65
76
|
### Info of the call
|
66
77
|
All tapping methods (start with `tap_`) takes a block and yield a hash as block argument.
|
67
78
|
|
68
79
|
```ruby
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
80
|
+
{
|
81
|
+
:receiver=>#<Student:0x00007fabed02aeb8 @name="Stan", @age=18, @tapping_device=[#<TracePoint:return `age'@/PROJECT_PATH/tapping_device/spec/trackable_spec.rb:17>]>,
|
82
|
+
:method_name=>:age,
|
83
|
+
:arguments=>[],
|
84
|
+
:return_value=>18,
|
85
|
+
:filepath=>"/PROJECT_PATH/tapping_device/spec/trackable_spec.rb",
|
86
|
+
:line_number=>"171",
|
87
|
+
:defined_class=>Student,
|
88
|
+
:trace=>[],
|
89
|
+
:tp=>#<TracePoint:return `age'@/PROJECT_PATH/tapping_device/spec/trackable_spec.rb:17>
|
90
|
+
}
|
76
91
|
```
|
77
92
|
|
78
93
|
The hash contains
|
@@ -85,33 +100,34 @@ The hash contains
|
|
85
100
|
- `return_value` - return value of the method call
|
86
101
|
- `filepath` - path to the file that performs the method call
|
87
102
|
- `line_number`
|
88
|
-
- `defined_class` - in which class that defines the
|
103
|
+
- `defined_class` - in which class that defines the method being called
|
89
104
|
- `trace` - stack trace of the call. Default is an empty array unless `with_trace_to` option is set
|
90
105
|
- `tp` - trace point object of this call
|
91
106
|
|
92
107
|
|
93
108
|
### Options
|
94
|
-
- `with_trace_to` - the number of traces we want to put into `trace`. Default is `nil`, so `trace` would be empty
|
95
|
-
- `
|
109
|
+
- `with_trace_to: 10` - the number of traces we want to put into `trace`. Default is `nil`, so `trace` would be empty
|
110
|
+
- `exclude_by_paths: [/path/]` - an array of call path patterns that we want to skip. This could be very helpful when working on large project like Rails applications.
|
111
|
+
- `filter_by_paths: [/path/]` - only contain calls from the specified paths
|
96
112
|
|
97
113
|
```ruby
|
98
|
-
tap_on!(@post,
|
114
|
+
tap_on!(@post, exclude_by_paths: [/active_record/]) do |payload|
|
99
115
|
puts "Method: #{payload[:method_name]} line: #{payload[:filepath]}:#{payload[:line_number]}"
|
100
116
|
end
|
101
117
|
```
|
102
118
|
|
103
119
|
```
|
104
|
-
Method: _read_attribute line: /
|
105
|
-
Method: name line: /
|
106
|
-
Method: _read_attribute line: /
|
107
|
-
Method: user_id line: /
|
120
|
+
Method: _read_attribute line: /RUBY_PATH/gems/2.6.0/gems/activerecord-5.2.0/lib/active_record/attribute_methods/read.rb:40
|
121
|
+
Method: name line: /PROJECT_PATH/sample/app/views/posts/show.html.erb:5
|
122
|
+
Method: _read_attribute line: /RUBY_PATH/gems/2.6.0/gems/activerecord-5.2.0/lib/active_record/attribute_methods/read.rb:40
|
123
|
+
Method: user_id line: /PROJECT_PATH/sample/app/views/posts/show.html.erb:10
|
108
124
|
.......
|
109
125
|
|
110
126
|
# versus
|
111
127
|
|
112
|
-
Method: name line: /
|
113
|
-
Method: user_id line: /
|
114
|
-
Method: to_param line: /
|
128
|
+
Method: name line: /PROJECT_PATH/sample/app/views/posts/show.html.erb:5
|
129
|
+
Method: user_id line: /PROJECT_PATH/sample/app/views/posts/show.html.erb:10
|
130
|
+
Method: to_param line: /RUBY_PATH/gems/2.6.0/gems/actionpack-5.2.0/lib/action_dispatch/routing/route_set.rb:236
|
115
131
|
```
|
116
132
|
|
117
133
|
|
@@ -150,11 +166,26 @@ end
|
|
150
166
|
And you can see these in log:
|
151
167
|
|
152
168
|
```
|
153
|
-
Method: name line: /
|
154
|
-
Method: user_id line: /
|
155
|
-
Method: to_param line: /
|
169
|
+
Method: name line: /PROJECT_PATH/sample/app/views/posts/show.html.erb:5
|
170
|
+
Method: user_id line: /PROJECT_PATH/sample/app/views/posts/show.html.erb:10
|
171
|
+
Method: to_param line: /RUBY_PATH/gems/2.6.0/gems/actionpack-5.2.0/lib/action_dispatch/routing/route_set.rb:236
|
156
172
|
```
|
157
173
|
|
174
|
+
### `tap_assoc!`
|
175
|
+
|
176
|
+
```ruby
|
177
|
+
tap_assoc!(order) do |payload|
|
178
|
+
puts "Assoc: #{payload[:method_name]} line: #{payload[:filepath]}:#{payload[:line_number]}"
|
179
|
+
end
|
180
|
+
```
|
181
|
+
|
182
|
+
```
|
183
|
+
Assoc: payments line: /RUBY_PATH/gems/2.6.0/gems/jsonapi-resources-0.9.10/lib/jsonapi/resource.rb:124
|
184
|
+
Assoc: line_items line: /MY_PROJECT/app/models/line_item_container_helpers.rb:44
|
185
|
+
Assoc: effective_line_items line: /MY_PROJECT/app/models/line_item_container_helpers.rb:110
|
186
|
+
Assoc: amending_orders line: /MY_PROJECT/app/models/order.rb:385
|
187
|
+
Assoc: amends_order line: /MY_PROJECT/app/models/order.rb:432
|
188
|
+
```
|
158
189
|
|
159
190
|
|
160
191
|
## Development
|
@@ -165,7 +196,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
165
196
|
|
166
197
|
## Contributing
|
167
198
|
|
168
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
199
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/st0012/tapping_device. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
169
200
|
|
170
201
|
## License
|
171
202
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "active_record"
|
2
|
+
|
1
3
|
module TappingDevice
|
2
4
|
module Trackable
|
3
5
|
TAPPING_DEVICE = :@tapping_device
|
@@ -5,15 +7,16 @@ module TappingDevice
|
|
5
7
|
|
6
8
|
def tap_initialization_of!(klass, options = {}, &block)
|
7
9
|
raise "argument should be a class, got #{klass}" unless klass.is_a?(Class)
|
8
|
-
|
9
|
-
|
10
|
-
|
10
|
+
track(klass, condition: :tap_init?, block: block, **options)
|
11
|
+
end
|
12
|
+
|
13
|
+
def tap_association_calls!(record, options = {}, &block)
|
14
|
+
raise "argument should be an instance of ActiveRecord::Base" unless record.is_a?(ActiveRecord::Base)
|
15
|
+
track(record, condition: :tap_associations?, block: block, **options)
|
11
16
|
end
|
12
17
|
|
13
18
|
def tap_calls_on!(object, options = {}, &block)
|
14
|
-
|
15
|
-
options[:block] = block
|
16
|
-
track(object, **options)
|
19
|
+
track(object, condition: :tap_on?, block: block, **options)
|
17
20
|
end
|
18
21
|
|
19
22
|
def stop_tapping!(object)
|
@@ -21,17 +24,22 @@ module TappingDevice
|
|
21
24
|
end
|
22
25
|
|
23
26
|
alias :tap_init! :tap_initialization_of!
|
27
|
+
alias :tap_assoc! :tap_association_calls!
|
24
28
|
alias :tap_on! :tap_calls_on!
|
25
29
|
alias :untap! :stop_tapping!
|
26
30
|
|
27
31
|
private
|
28
32
|
|
29
|
-
def track(object, condition:, block:, with_trace_to: nil,
|
33
|
+
def track(object, condition:, block:, with_trace_to: nil, exclude_by_paths: [], filter_by_paths: nil)
|
30
34
|
trace_point = TracePoint.trace(:return) do |tp|
|
31
35
|
filepath, line_number = caller(CALLER_START_POINT).first.split(":")[0..1]
|
32
36
|
|
33
37
|
# this needs to be placed upfront so we can exclude noise before doing more work
|
34
|
-
next if
|
38
|
+
next if exclude_by_paths.any? { |pattern| pattern.match?(filepath) }
|
39
|
+
|
40
|
+
if filter_by_paths
|
41
|
+
next unless filter_by_paths.any? { |pattern| pattern.match?(filepath) }
|
42
|
+
end
|
35
43
|
|
36
44
|
arguments = tp.binding.local_variables.map { |n| [n, tp.binding.local_variable_get(n)] }
|
37
45
|
|
@@ -49,12 +57,35 @@ module TappingDevice
|
|
49
57
|
|
50
58
|
yield_parameters[:trace] = caller[CALLER_START_POINT..(CALLER_START_POINT + with_trace_to)] if with_trace_to
|
51
59
|
|
52
|
-
block.call(yield_parameters) if condition
|
60
|
+
block.call(yield_parameters) if send(condition, object, yield_parameters)
|
53
61
|
end
|
54
62
|
|
55
63
|
add_tapping_device(object, trace_point)
|
56
64
|
end
|
57
65
|
|
66
|
+
def tap_init?(klass, parameters)
|
67
|
+
receiver = parameters[:receiver]
|
68
|
+
method_name = parameters[:method_name]
|
69
|
+
|
70
|
+
if klass.ancestors.include?(ActiveRecord::Base)
|
71
|
+
method_name == :new && receiver.ancestors.include?(klass)
|
72
|
+
else
|
73
|
+
method_name == :initialize && receiver.is_a?(klass)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def tap_on?(object, parameters)
|
78
|
+
parameters[:receiver].object_id == object.object_id
|
79
|
+
end
|
80
|
+
|
81
|
+
def tap_associations?(object, parameters)
|
82
|
+
return false unless tap_on?(object, parameters)
|
83
|
+
|
84
|
+
model_class = object.class
|
85
|
+
associations = model_class.reflections
|
86
|
+
associations.keys.include?(parameters[:method_name].to_s)
|
87
|
+
end
|
88
|
+
|
58
89
|
def get_tapping_device(object)
|
59
90
|
object.instance_variable_get(TAPPING_DEVICE)
|
60
91
|
end
|
data/tapping_device.gemspec
CHANGED
@@ -26,6 +26,14 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
27
|
spec.require_paths = ["lib"]
|
28
28
|
|
29
|
+
if ENV["RAILS_VERSION"].to_i >= 6
|
30
|
+
spec.add_dependency "activerecord", "~> #{ENV["RAILS_VERSION"]}"
|
31
|
+
spec.add_development_dependency "sqlite3", "~> 1.4.1"
|
32
|
+
else
|
33
|
+
spec.add_dependency "activerecord", "~> 5.2"
|
34
|
+
spec.add_development_dependency "sqlite3", "~> 1.3.6"
|
35
|
+
end
|
36
|
+
|
29
37
|
spec.add_development_dependency "bundler", "~> 2.0"
|
30
38
|
spec.add_development_dependency "pry"
|
31
39
|
spec.add_development_dependency "rake", "~> 10.0"
|
metadata
CHANGED
@@ -1,15 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tapping_device
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- st0012
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-10-
|
11
|
+
date: 2019-10-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sqlite3
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.3.6
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.3.6
|
13
41
|
- !ruby/object:Gem::Dependency
|
14
42
|
name: bundler
|
15
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -73,6 +101,7 @@ executables: []
|
|
73
101
|
extensions: []
|
74
102
|
extra_rdoc_files: []
|
75
103
|
files:
|
104
|
+
- ".github/workflows/gempush.yml"
|
76
105
|
- ".github/workflows/ruby.yml"
|
77
106
|
- ".gitignore"
|
78
107
|
- ".rspec"
|
@@ -111,7 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
111
140
|
- !ruby/object:Gem::Version
|
112
141
|
version: '0'
|
113
142
|
requirements: []
|
114
|
-
rubygems_version: 3.0.
|
143
|
+
rubygems_version: 3.0.3
|
115
144
|
signing_key:
|
116
145
|
specification_version: 4
|
117
146
|
summary: tapping_device provides useful helpers to intercept method calls
|