tapping_device 0.4.10 → 0.5.3
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/.DS_Store +0 -0
- data/.github/workflows/ruby.yml +11 -4
- data/CHANGELOG.md +208 -0
- data/Gemfile.lock +22 -23
- data/README.md +206 -297
- data/images/print_calls - single entry.png +0 -0
- data/images/print_calls.png +0 -0
- data/images/print_mutations.png +0 -0
- data/images/print_traces.png +0 -0
- data/lib/tapping_device.rb +108 -114
- data/lib/tapping_device/configurable.rb +25 -0
- data/lib/tapping_device/exceptions.rb +12 -0
- data/lib/tapping_device/method_hijacker.rb +51 -0
- data/lib/tapping_device/output.rb +42 -0
- data/lib/tapping_device/output/file_writer.rb +21 -0
- data/lib/tapping_device/output/payload.rb +175 -0
- data/lib/tapping_device/output/stdout_writer.rb +9 -0
- data/lib/tapping_device/output/writer.rb +20 -0
- data/lib/tapping_device/payload.rb +4 -47
- data/lib/tapping_device/trackable.rb +84 -18
- data/lib/tapping_device/trackers/association_call_tracker.rb +17 -0
- data/lib/tapping_device/trackers/initialization_tracker.rb +27 -0
- data/lib/tapping_device/trackers/method_call_tracker.rb +9 -0
- data/lib/tapping_device/trackers/mutation_tracker.rb +112 -0
- data/lib/tapping_device/trackers/passed_tracker.rb +16 -0
- data/lib/tapping_device/version.rb +1 -1
- data/tapping_device.gemspec +5 -5
- metadata +41 -22
- data/lib/tapping_device/sql_tapping_methods.rb +0 -89
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9311ddb749d3c7bf09306161da25191c0de47734dea77f645f5d5af62a55d802
|
4
|
+
data.tar.gz: 4df7c9fef5c3a3a2b3852b5b4f4db31ec071149dd19b3fceb1df6f6b1ac191e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: deaece3e6096551df6fe3c7eb492f6049e72b32f7e19b7a8d4067f8d5a6dc9b6fe56a41d3bd9855220ae11c8adcc377cd188f51c043835845be5c2d9250bc6d1
|
7
|
+
data.tar.gz: 057766f277605fb3e80bd2797ee1256f0f6d81fbca56c95226199a72c7e14565dc353292d06711847e257d2f552e9eb3ddcd076ec35f1abd3aaf30cc9f686f5c
|
data/.DS_Store
ADDED
Binary file
|
data/.github/workflows/ruby.yml
CHANGED
@@ -33,10 +33,17 @@ jobs:
|
|
33
33
|
gem install bundler
|
34
34
|
bundle install --jobs 4 --retry 3
|
35
35
|
|
36
|
-
- name: Run test with Rails ${{ matrix.rails_version }}
|
37
|
-
|
36
|
+
- name: Run test with Rails ${{ matrix.rails_version }}
|
37
|
+
run: bundle exec rake
|
38
|
+
|
39
|
+
- name: Publish Test Coverage
|
40
|
+
uses: paambaati/codeclimate-action@v2.6.0
|
38
41
|
env:
|
39
|
-
CC_TEST_REPORTER_ID: ${{secrets.CC_TEST_REPORTER_ID}}
|
42
|
+
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
|
43
|
+
if: ${{ env.CC_TEST_REPORTER_ID != '' }}
|
40
44
|
with:
|
41
|
-
|
45
|
+
# the coverage result should already be generated by the previous step
|
46
|
+
# so we don't need to provide and command in the step
|
47
|
+
# this is just a placeholder to avoid it run the default `yarn coverage` command
|
48
|
+
coverageCommand: ruby -v
|
42
49
|
debug: true
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,208 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## [Unreleased](https://github.com/st0012/tapping_device/tree/HEAD)
|
4
|
+
|
5
|
+
[Full Changelog](https://github.com/st0012/tapping_device/compare/v0.5.2...HEAD)
|
6
|
+
|
7
|
+
**Closed issues:**
|
8
|
+
|
9
|
+
- Support write\_\* helpers [\#44](https://github.com/st0012/tapping_device/issues/44)
|
10
|
+
- Use Method\#source to replace Payload\#method\_head’s implementation [\#19](https://github.com/st0012/tapping_device/issues/19)
|
11
|
+
|
12
|
+
**Merged pull requests:**
|
13
|
+
|
14
|
+
- Support write\_\* helpers [\#47](https://github.com/st0012/tapping_device/pull/47) ([st0012](https://github.com/st0012))
|
15
|
+
- Hijack attr methods with `hijack\_attr\_methods` option [\#45](https://github.com/st0012/tapping_device/pull/45) ([st0012](https://github.com/st0012))
|
16
|
+
|
17
|
+
## [v0.5.2](https://github.com/st0012/tapping_device/tree/v0.5.2) (2020-06-10)
|
18
|
+
|
19
|
+
[Full Changelog](https://github.com/st0012/tapping_device/compare/v0.5.1...v0.5.2)
|
20
|
+
|
21
|
+
**Closed issues:**
|
22
|
+
|
23
|
+
- Add print\_mutations [\#41](https://github.com/st0012/tapping_device/issues/41)
|
24
|
+
- Add tap\_on\_mutation! [\#18](https://github.com/st0012/tapping_device/issues/18)
|
25
|
+
|
26
|
+
**Merged pull requests:**
|
27
|
+
|
28
|
+
- Print mutations [\#43](https://github.com/st0012/tapping_device/pull/43) ([st0012](https://github.com/st0012))
|
29
|
+
- Refactorings [\#42](https://github.com/st0012/tapping_device/pull/42) ([st0012](https://github.com/st0012))
|
30
|
+
|
31
|
+
## [v0.5.1](https://github.com/st0012/tapping_device/tree/v0.5.1) (2020-06-07)
|
32
|
+
|
33
|
+
[Full Changelog](https://github.com/st0012/tapping_device/compare/v0.5.0...v0.5.1)
|
34
|
+
|
35
|
+
**Fixed bugs:**
|
36
|
+
|
37
|
+
- Filter Out Entries From TappingDevice [\#35](https://github.com/st0012/tapping_device/issues/35)
|
38
|
+
|
39
|
+
**Merged pull requests:**
|
40
|
+
|
41
|
+
- Update GitHub Actions Configuration [\#40](https://github.com/st0012/tapping_device/pull/40) ([st0012](https://github.com/st0012))
|
42
|
+
- Fix typo: Guadian -\> Guardian [\#39](https://github.com/st0012/tapping_device/pull/39) ([skade](https://github.com/skade))
|
43
|
+
- Filter out calls about TappingDevice [\#38](https://github.com/st0012/tapping_device/pull/38) ([st0012](https://github.com/st0012))
|
44
|
+
- Drop tap\_sql! [\#37](https://github.com/st0012/tapping_device/pull/37) ([st0012](https://github.com/st0012))
|
45
|
+
- Add CollectionProxy class [\#36](https://github.com/st0012/tapping_device/pull/36) ([st0012](https://github.com/st0012))
|
46
|
+
|
47
|
+
## [v0.5.0](https://github.com/st0012/tapping_device/tree/v0.5.0) (2020-05-25)
|
48
|
+
|
49
|
+
[Full Changelog](https://github.com/st0012/tapping_device/compare/v0.4.11...v0.5.0)
|
50
|
+
|
51
|
+
**Closed issues:**
|
52
|
+
|
53
|
+
- Colorize output of tracing helpers [\#25](https://github.com/st0012/tapping_device/issues/25)
|
54
|
+
|
55
|
+
**Merged pull requests:**
|
56
|
+
|
57
|
+
- Update README.md [\#34](https://github.com/st0012/tapping_device/pull/34) ([st0012](https://github.com/st0012))
|
58
|
+
- Colorize output [\#33](https://github.com/st0012/tapping_device/pull/33) ([st0012](https://github.com/st0012))
|
59
|
+
- Add TappingDevice\#with to register a with condition [\#32](https://github.com/st0012/tapping_device/pull/32) ([st0012](https://github.com/st0012))
|
60
|
+
|
61
|
+
## [v0.4.11](https://github.com/st0012/tapping_device/tree/v0.4.11) (2020-04-19)
|
62
|
+
|
63
|
+
[Full Changelog](https://github.com/st0012/tapping_device/compare/v0.4.10...v0.4.11)
|
64
|
+
|
65
|
+
**Merged pull requests:**
|
66
|
+
|
67
|
+
- Update rake requirement from ~\> 10.0 to ~\> 13.0 [\#31](https://github.com/st0012/tapping_device/pull/31) ([dependabot[bot]](https://github.com/apps/dependabot))
|
68
|
+
|
69
|
+
## [v0.4.10](https://github.com/st0012/tapping_device/tree/v0.4.10) (2020-02-05)
|
70
|
+
|
71
|
+
[Full Changelog](https://github.com/st0012/tapping_device/compare/v0.4.9...v0.4.10)
|
72
|
+
|
73
|
+
**Implemented enhancements:**
|
74
|
+
|
75
|
+
- Usability improvements [\#30](https://github.com/st0012/tapping_device/pull/30) ([st0012](https://github.com/st0012))
|
76
|
+
|
77
|
+
**Merged pull requests:**
|
78
|
+
|
79
|
+
- Fix tap\_init!'s payload content [\#29](https://github.com/st0012/tapping_device/pull/29) ([st0012](https://github.com/st0012))
|
80
|
+
- Refactorings and fixes [\#28](https://github.com/st0012/tapping_device/pull/28) ([st0012](https://github.com/st0012))
|
81
|
+
|
82
|
+
## [v0.4.9](https://github.com/st0012/tapping_device/tree/v0.4.9) (2020-01-20)
|
83
|
+
|
84
|
+
[Full Changelog](https://github.com/st0012/tapping_device/compare/v0.4.8...v0.4.9)
|
85
|
+
|
86
|
+
**Implemented enhancements:**
|
87
|
+
|
88
|
+
- Improve detail\_call\_info's output format [\#27](https://github.com/st0012/tapping_device/pull/27) ([st0012](https://github.com/st0012))
|
89
|
+
|
90
|
+
## [v0.4.8](https://github.com/st0012/tapping_device/tree/v0.4.8) (2020-01-05)
|
91
|
+
|
92
|
+
[Full Changelog](https://github.com/st0012/tapping_device/compare/v0.4.7...v0.4.8)
|
93
|
+
|
94
|
+
**Closed issues:**
|
95
|
+
|
96
|
+
- Provide options for tapping on call or return events [\#23](https://github.com/st0012/tapping_device/issues/23)
|
97
|
+
|
98
|
+
**Merged pull requests:**
|
99
|
+
|
100
|
+
- Add tracing helpers [\#24](https://github.com/st0012/tapping_device/pull/24) ([st0012](https://github.com/st0012))
|
101
|
+
|
102
|
+
## [v0.4.7](https://github.com/st0012/tapping_device/tree/v0.4.7) (2019-12-29)
|
103
|
+
|
104
|
+
[Full Changelog](https://github.com/st0012/tapping_device/compare/v0.4.6...v0.4.7)
|
105
|
+
|
106
|
+
**Implemented enhancements:**
|
107
|
+
|
108
|
+
- Config test coverage for codeclimate [\#22](https://github.com/st0012/tapping_device/pull/22) ([st0012](https://github.com/st0012))
|
109
|
+
|
110
|
+
**Closed issues:**
|
111
|
+
|
112
|
+
- Support tracking ActiveRecord::Base instances by their ids [\#17](https://github.com/st0012/tapping_device/issues/17)
|
113
|
+
|
114
|
+
**Merged pull requests:**
|
115
|
+
|
116
|
+
- Refactor tests and some minor fixes [\#21](https://github.com/st0012/tapping_device/pull/21) ([st0012](https://github.com/st0012))
|
117
|
+
- Support track\_as\_records option [\#20](https://github.com/st0012/tapping_device/pull/20) ([st0012](https://github.com/st0012))
|
118
|
+
|
119
|
+
## [v0.4.6](https://github.com/st0012/tapping_device/tree/v0.4.6) (2019-12-25)
|
120
|
+
|
121
|
+
[Full Changelog](https://github.com/st0012/tapping_device/compare/v0.4.5...v0.4.6)
|
122
|
+
|
123
|
+
**Merged pull requests:**
|
124
|
+
|
125
|
+
- Add TappingDevice\#and\_print method [\#16](https://github.com/st0012/tapping_device/pull/16) ([st0012](https://github.com/st0012))
|
126
|
+
- Add Payload\#detail\_call\_info and improve method\_name's format [\#15](https://github.com/st0012/tapping_device/pull/15) ([st0012](https://github.com/st0012))
|
127
|
+
|
128
|
+
## [v0.4.5](https://github.com/st0012/tapping_device/tree/v0.4.5) (2019-12-15)
|
129
|
+
|
130
|
+
[Full Changelog](https://github.com/st0012/tapping_device/compare/v0.4.4...v0.4.5)
|
131
|
+
|
132
|
+
## [v0.4.4](https://github.com/st0012/tapping_device/tree/v0.4.4) (2019-12-15)
|
133
|
+
|
134
|
+
[Full Changelog](https://github.com/st0012/tapping_device/compare/v0.4.3...v0.4.4)
|
135
|
+
|
136
|
+
**Merged pull requests:**
|
137
|
+
|
138
|
+
- Implement tap\_passed! [\#14](https://github.com/st0012/tapping_device/pull/14) ([st0012](https://github.com/st0012))
|
139
|
+
|
140
|
+
## [v0.4.3](https://github.com/st0012/tapping_device/tree/v0.4.3) (2019-12-09)
|
141
|
+
|
142
|
+
[Full Changelog](https://github.com/st0012/tapping_device/compare/v0.4.2...v0.4.3)
|
143
|
+
|
144
|
+
## [v0.4.2](https://github.com/st0012/tapping_device/tree/v0.4.2) (2019-12-09)
|
145
|
+
|
146
|
+
[Full Changelog](https://github.com/st0012/tapping_device/compare/v0.4.1...v0.4.2)
|
147
|
+
|
148
|
+
**Merged pull requests:**
|
149
|
+
|
150
|
+
- Refactor tap\_sql! [\#13](https://github.com/st0012/tapping_device/pull/13) ([st0012](https://github.com/st0012))
|
151
|
+
- Improve tap sql [\#12](https://github.com/st0012/tapping_device/pull/12) ([st0012](https://github.com/st0012))
|
152
|
+
|
153
|
+
## [v0.4.1](https://github.com/st0012/tapping_device/tree/v0.4.1) (2019-12-06)
|
154
|
+
|
155
|
+
[Full Changelog](https://github.com/st0012/tapping_device/compare/v0.4.0...v0.4.1)
|
156
|
+
|
157
|
+
**Merged pull requests:**
|
158
|
+
|
159
|
+
- Add TappingDevice::Payload class [\#11](https://github.com/st0012/tapping_device/pull/11) ([st0012](https://github.com/st0012))
|
160
|
+
|
161
|
+
## [v0.4.0](https://github.com/st0012/tapping_device/tree/v0.4.0) (2019-11-25)
|
162
|
+
|
163
|
+
[Full Changelog](https://github.com/st0012/tapping_device/compare/v0.3.0...v0.4.0)
|
164
|
+
|
165
|
+
**Merged pull requests:**
|
166
|
+
|
167
|
+
- Support tap\_sql! [\#10](https://github.com/st0012/tapping_device/pull/10) ([st0012](https://github.com/st0012))
|
168
|
+
- Minor adjustment [\#9](https://github.com/st0012/tapping_device/pull/9) ([NickWarm](https://github.com/NickWarm))
|
169
|
+
|
170
|
+
## [v0.3.0](https://github.com/st0012/tapping_device/tree/v0.3.0) (2019-11-03)
|
171
|
+
|
172
|
+
[Full Changelog](https://github.com/st0012/tapping_device/compare/v0.2.0...v0.3.0)
|
173
|
+
|
174
|
+
**Implemented enhancements:**
|
175
|
+
|
176
|
+
- Largely improve performance by fixing bad design [\#8](https://github.com/st0012/tapping_device/pull/8) ([st0012](https://github.com/st0012))
|
177
|
+
|
178
|
+
## [v0.2.0](https://github.com/st0012/tapping_device/tree/v0.2.0) (2019-11-02)
|
179
|
+
|
180
|
+
[Full Changelog](https://github.com/st0012/tapping_device/compare/v0.1.1...v0.2.0)
|
181
|
+
|
182
|
+
**Implemented enhancements:**
|
183
|
+
|
184
|
+
- Add Device class [\#3](https://github.com/st0012/tapping_device/pull/3) ([st0012](https://github.com/st0012))
|
185
|
+
|
186
|
+
**Merged pull requests:**
|
187
|
+
|
188
|
+
- Remove tapping\_deivce/device.rb [\#7](https://github.com/st0012/tapping_device/pull/7) ([st0012](https://github.com/st0012))
|
189
|
+
- Reduce namespace [\#6](https://github.com/st0012/tapping_device/pull/6) ([st0012](https://github.com/st0012))
|
190
|
+
- Register and control all devices from Device class [\#5](https://github.com/st0012/tapping_device/pull/5) ([st0012](https://github.com/st0012))
|
191
|
+
- Support `TappingDevice::Device\#stop\_when` [\#4](https://github.com/st0012/tapping_device/pull/4) ([st0012](https://github.com/st0012))
|
192
|
+
|
193
|
+
## [v0.1.1](https://github.com/st0012/tapping_device/tree/v0.1.1) (2019-10-20)
|
194
|
+
|
195
|
+
[Full Changelog](https://github.com/st0012/tapping_device/compare/v0.1.0...v0.1.1)
|
196
|
+
|
197
|
+
**Implemented enhancements:**
|
198
|
+
|
199
|
+
- More filters, Refactoring and Readme update [\#2](https://github.com/st0012/tapping_device/pull/2) ([st0012](https://github.com/st0012))
|
200
|
+
- Support tapping ActiveRecord class/instance [\#1](https://github.com/st0012/tapping_device/pull/1) ([st0012](https://github.com/st0012))
|
201
|
+
|
202
|
+
## [v0.1.0](https://github.com/st0012/tapping_device/tree/v0.1.0) (2019-10-19)
|
203
|
+
|
204
|
+
[Full Changelog](https://github.com/st0012/tapping_device/compare/61039c87a55c664661b788e24311e263b28a3ee8...v0.1.0)
|
205
|
+
|
206
|
+
|
207
|
+
|
208
|
+
\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
|
data/Gemfile.lock
CHANGED
@@ -1,39 +1,39 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
tapping_device (0.
|
4
|
+
tapping_device (0.5.3)
|
5
5
|
activerecord (>= 5.2)
|
6
|
-
|
6
|
+
activesupport
|
7
|
+
pry
|
7
8
|
|
8
9
|
GEM
|
9
10
|
remote: https://rubygems.org/
|
10
11
|
specs:
|
11
|
-
activemodel (6.0.2
|
12
|
-
activesupport (= 6.0.2
|
13
|
-
activerecord (6.0.2
|
14
|
-
activemodel (= 6.0.2
|
15
|
-
activesupport (= 6.0.2
|
16
|
-
activesupport (6.0.2
|
12
|
+
activemodel (6.0.3.2)
|
13
|
+
activesupport (= 6.0.3.2)
|
14
|
+
activerecord (6.0.3.2)
|
15
|
+
activemodel (= 6.0.3.2)
|
16
|
+
activesupport (= 6.0.3.2)
|
17
|
+
activesupport (6.0.3.2)
|
17
18
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
18
19
|
i18n (>= 0.7, < 2)
|
19
20
|
minitest (~> 5.1)
|
20
21
|
tzinfo (~> 1.1)
|
21
|
-
zeitwerk (~> 2.2)
|
22
|
-
|
23
|
-
|
24
|
-
concurrent-ruby (1.1.5)
|
22
|
+
zeitwerk (~> 2.2, >= 2.2.2)
|
23
|
+
coderay (1.1.3)
|
24
|
+
concurrent-ruby (1.1.6)
|
25
25
|
database_cleaner (1.7.0)
|
26
26
|
diff-lcs (1.3)
|
27
27
|
docile (1.3.2)
|
28
|
-
i18n (1.8.
|
28
|
+
i18n (1.8.3)
|
29
29
|
concurrent-ruby (~> 1.0)
|
30
30
|
json (2.3.0)
|
31
|
-
method_source (0.
|
32
|
-
minitest (5.14.
|
33
|
-
pry (0.
|
34
|
-
coderay (~> 1.1
|
35
|
-
method_source (~>
|
36
|
-
rake (
|
31
|
+
method_source (1.0.0)
|
32
|
+
minitest (5.14.1)
|
33
|
+
pry (0.13.1)
|
34
|
+
coderay (~> 1.1)
|
35
|
+
method_source (~> 1.0)
|
36
|
+
rake (13.0.1)
|
37
37
|
rspec (3.8.0)
|
38
38
|
rspec-core (~> 3.8.0)
|
39
39
|
rspec-expectations (~> 3.8.0)
|
@@ -54,9 +54,9 @@ GEM
|
|
54
54
|
simplecov-html (0.10.2)
|
55
55
|
sqlite3 (1.4.1)
|
56
56
|
thread_safe (0.3.6)
|
57
|
-
tzinfo (1.2.
|
57
|
+
tzinfo (1.2.7)
|
58
58
|
thread_safe (~> 0.1)
|
59
|
-
zeitwerk (2.
|
59
|
+
zeitwerk (2.3.0)
|
60
60
|
|
61
61
|
PLATFORMS
|
62
62
|
ruby
|
@@ -64,8 +64,7 @@ PLATFORMS
|
|
64
64
|
DEPENDENCIES
|
65
65
|
bundler (~> 2.0)
|
66
66
|
database_cleaner
|
67
|
-
|
68
|
-
rake (~> 10.0)
|
67
|
+
rake (~> 13.0)
|
69
68
|
rspec (~> 3.0)
|
70
69
|
simplecov (= 0.17.1)
|
71
70
|
sqlite3 (>= 1.3.6)
|
data/README.md
CHANGED
@@ -6,417 +6,326 @@
|
|
6
6
|
[](https://codeclimate.com/github/st0012/tapping_device/test_coverage)
|
7
7
|
[](https://www.codetriage.com/st0012/tapping_device)
|
8
8
|
|
9
|
-
## Related Posts
|
10
|
-
- [Optimize Your Debugging Process With Object-Oriented Tracing and tapping_device](http://bit.ly/object-oriented-tracing)
|
11
|
-
- [Debug Rails issues effectively with tapping_device](https://dev.to/st0012/debug-rails-issues-effectively-with-tappingdevice-c7c)
|
12
|
-
- [Want to know more about your Rails app? Tap on your objects!](https://dev.to/st0012/want-to-know-more-about-your-rails-app-tap-on-your-objects-bd3)
|
13
9
|
|
10
|
+
## Introduction
|
11
|
+
`TappingDevice` makes the objects tell you what they do, so you don't need to track them yourself.
|
14
12
|
|
15
|
-
|
16
|
-
- [Introduction](#introduction)
|
17
|
-
- [Print Object’s Traces](print-objects-traces)
|
18
|
-
- [Track Calls that Generates SQL Queries](#track-calls-that-generates-sql-queries)
|
19
|
-
- [Installation](#installation)
|
20
|
-
- [Usages](#usages)
|
21
|
-
- Tracing Helpers
|
22
|
-
- [print_traces](#print_traces)
|
23
|
-
- [print_calls_in_detail](#print_calls_in_detail)
|
24
|
-
- Tapping Methods
|
25
|
-
- [tap_init!](#tap_init)
|
26
|
-
- [tap_on!](#tap_on)
|
27
|
-
- [tap_passed!](#tap_passed)
|
28
|
-
- [tap_assoc!](#tap_assoc)
|
29
|
-
- [tap_sql!](#tap_sql)
|
30
|
-
- [Options](#options)
|
31
|
-
- [Payload](#payload-of-the-call)
|
32
|
-
- [Advance Usages](#advance-usages)
|
13
|
+
#### Contact Tracing For Objects
|
33
14
|
|
34
|
-
|
35
|
-
|
15
|
+
The concept is very simple. It's basically like [contact tracing](https://en.wikipedia.org/wiki/Contact_tracing) for your Ruby objects. You can use
|
16
|
+
|
17
|
+
- `print_calls(object)` to see what the object does
|
18
|
+
- `print_traces(object)` to see how the object interacts with other objects (like used as an argument)
|
19
|
+
- `print_mutations(object)` to see what actions changed the object's state (instance variables)
|
36
20
|
|
37
|
-
|
21
|
+
Still sounds vague? Let's see some examples:
|
38
22
|
|
39
|
-
###
|
23
|
+
### `print_calls` - Track Method Calls
|
40
24
|
|
41
|
-
|
25
|
+
In [Discourse](https://github.com/discourse/discourse), it uses the `Guardian` class for authorization (like policy objects). It's barely visible in controller actions, but it does many checks under the hood. Now, let's say we want to know what the `Guardian` would do when a user creates a post; here's the controller action:
|
42
26
|
|
43
27
|
```ruby
|
44
|
-
class OrdersController < ApplicationController
|
45
28
|
def create
|
46
|
-
@
|
47
|
-
|
48
|
-
|
29
|
+
@manager_params = create_params
|
30
|
+
@manager_params[:first_post_checks] = !is_api?
|
31
|
+
|
32
|
+
manager = NewPostManager.new(current_user, @manager_params)
|
33
|
+
|
34
|
+
if is_api?
|
35
|
+
memoized_payload = DistributedMemoizer.memoize(signature_for(@manager_params), 120) do
|
36
|
+
result = manager.perform
|
37
|
+
MultiJson.dump(serialize_data(result, NewPostResultSerializer, root: false))
|
38
|
+
end
|
39
|
+
|
40
|
+
parsed_payload = JSON.parse(memoized_payload)
|
41
|
+
backwards_compatible_json(parsed_payload, parsed_payload['success'])
|
42
|
+
else
|
43
|
+
result = manager.perform
|
44
|
+
json = serialize_data(result, NewPostResultSerializer, root: false)
|
45
|
+
backwards_compatible_json(json, result.success?)
|
46
|
+
end
|
49
47
|
end
|
50
48
|
```
|
51
49
|
|
52
|
-
|
53
|
-
Passed as 'cart' in 'OrderCreationService#perform' at /Users/st0012/projects/tapping_device-demo/app/controllers/orders_controller.rb:10
|
54
|
-
Passed as 'cart' in 'OrderCreationService#validate_cart' at /Users/st0012/projects/tapping_device-demo/app/services/order_creation_service.rb:8
|
55
|
-
Called :reserved_until FROM /Users/st0012/projects/tapping_device-demo/app/services/order_creation_service.rb:18
|
56
|
-
Called :errors FROM /Users/st0012/projects/tapping_device-demo/app/services/order_creation_service.rb:9
|
57
|
-
Passed as 'cart' in 'OrderCreationService#apply_discount' at /Users/st0012/projects/tapping_device-demo/app/services/order_creation_service.rb:10
|
58
|
-
Called :apply_discount FROM /Users/st0012/projects/tapping_device-demo/app/services/order_creation_service.rb:24
|
59
|
-
……
|
60
|
-
```
|
61
|
-
|
62
|
-
(Also see [print_calls_in_detail](#print_calls_in_detail))
|
50
|
+
As you can see, it doesn't even exist in the controller action, which makes tracking it by reading code very hard to do.
|
63
51
|
|
64
|
-
|
65
|
-
However, depending on the size of your application, tapping any object could **harm the performance significantly**. **Don't use this on production**
|
66
|
-
|
67
|
-
## Installation
|
68
|
-
Add this line to your application's Gemfile:
|
52
|
+
But with `TappingDevice`. You can use `print_calls` to show what method calls the object performs
|
69
53
|
|
70
54
|
```ruby
|
71
|
-
|
55
|
+
def create
|
56
|
+
# you can retrieve the current guardian object by calling guardian in the controller
|
57
|
+
print_calls(guardian)
|
58
|
+
@manager_params = create_params
|
59
|
+
|
60
|
+
# .....
|
72
61
|
```
|
73
62
|
|
74
|
-
|
63
|
+
Now, if you execute the code, like via tests:
|
75
64
|
|
76
|
-
```
|
77
|
-
$
|
65
|
+
```shell
|
66
|
+
$ rspec spec/requests/posts_controller_spec.rb:603
|
78
67
|
```
|
79
68
|
|
80
|
-
|
69
|
+
You can get all the method calls it performs with basically everything you need to know
|
81
70
|
|
82
|
-
|
83
|
-
|
84
|
-
|
71
|
+
<img src="https://github.com/st0012/tapping_device/blob/master/images/print_calls.png" alt="image of print_calls output" width="50%">
|
72
|
+
|
73
|
+
Let's take a closer look at each entry. Everyone of them contains the method call's
|
74
|
+
- method name
|
75
|
+
- method source class/module
|
76
|
+
- call site
|
77
|
+
- arguments
|
78
|
+
- return value
|
79
|
+
|
80
|
+

|
81
|
+
|
82
|
+
These are the information you'd have to look up one by one manually (probably with many debug code writing). Now you can get all of them in just one line of code.
|
85
83
|
|
86
|
-
## Usages
|
87
84
|
|
88
|
-
### print_traces
|
85
|
+
### `print_traces` - See The Object's Traces
|
89
86
|
|
90
|
-
|
87
|
+
If you're not interested in what an object does, but what it interacts with other parts of the program, e.g., used as arguments. You can use the `print_traces` helper. Let's see how `Discourse` uses the `manager` object when creating a post
|
91
88
|
|
92
89
|
```ruby
|
93
|
-
class OrdersController < ApplicationController
|
94
90
|
def create
|
95
|
-
@
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
```
|
91
|
+
@manager_params = create_params
|
92
|
+
@manager_params[:first_post_checks] = !is_api?
|
93
|
+
|
94
|
+
manager = NewPostManager.new(current_user, @manager_params)
|
100
95
|
|
96
|
+
print_traces(manager)
|
97
|
+
# .....
|
101
98
|
```
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
Called :apply_discount FROM /Users/st0012/projects/tapping_device-demo/app/services/order_creation_service.rb:24
|
108
|
-
……
|
99
|
+
|
100
|
+
And after running the test case
|
101
|
+
|
102
|
+
```shell
|
103
|
+
$ rspec spec/requests/posts_controller_spec.rb:603
|
109
104
|
```
|
110
105
|
|
111
|
-
|
106
|
+
You will see that it performs 2 calls: `perform` and `perform_create_post`. And it's also used as `manager` argument in various of calls of the `NewPostManager` class.
|
107
|
+
|
108
|
+

|
109
|
+
|
110
|
+
### `print_mutations` - Display All State Changes At Once
|
112
111
|
|
113
|
-
|
112
|
+
Another thing that often bothers developers in debugging is to track an object's internal state changes. And `tapping_device` allows you to see all state changes with just one line of code. Let me keep using [Discourse](https://github.com/discourse/discourse) to demonstrate it.
|
114
113
|
|
115
|
-
|
116
|
-
- `awesome_print:` - will print calls in prettier format if set to `true`. Default is `false`
|
114
|
+
When updating a post, it uses an object called `PostRevisor` to revise it:
|
117
115
|
|
118
116
|
```ruby
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
117
|
+
# app/controllers/posts_controller.rb
|
118
|
+
class PostsController
|
119
|
+
def update
|
120
|
+
# ......
|
121
|
+
revisor = PostRevisor.new(post, topic)
|
122
|
+
revisor.revise!(current_user, changes, opts)
|
123
|
+
# ......
|
125
124
|
end
|
125
|
+
end
|
126
126
|
```
|
127
127
|
|
128
|
-
|
129
|
-
:validate_cart # OrderCreationService
|
130
|
-
<= {:cart=>#<Cart id: 1, total: 10, customer_id: 1, promotion_id: nil, reserved_until: nil, created_at: "2020-01-05 09:48:28", updated_at: "2020-01-05 09:48:28">}
|
131
|
-
=> nil
|
132
|
-
FROM /Users/st0012/projects/tapping_device-demo/app/services/order_creation_service.rb:8
|
133
|
-
:apply_discount # OrderCreationService
|
134
|
-
<= {:cart=>#<Cart id: 1, total: 5, customer_id: 1, promotion_id: 1, reserved_until: nil, created_at: "2020-01-05 09:48:28", updated_at: "2020-01-05 09:48:28">, :promotion=>#<Promotion id: 1, amount: 0.5e1, customer_id: nil, created_at: "2020-01-05 09:48:28", updated_at: "2020-01-05 09:48:28">}
|
135
|
-
=> true
|
136
|
-
FROM /Users/st0012/projects/tapping_device-demo/app/services/order_creation_service.rb:10
|
137
|
-
:create_order # OrderCreationService
|
138
|
-
<= {:cart=>#<Cart id: 1, total: 5, customer_id: 1, promotion_id: 1, reserved_until: nil, created_at: "2020-01-05 09:48:28", updated_at: "2020-01-05 09:48:28">}
|
139
|
-
=> #<Order:0x00007f9ebcb17f08>
|
140
|
-
FROM /Users/st0012/projects/tapping_device-demo/app/services/order_creation_service.rb:11
|
141
|
-
:perform # OrderCreationService
|
142
|
-
<= {:cart=>#<Cart id: 1, total: 5, customer_id: 1, promotion_id: 1, reserved_until: nil, created_at: "2020-01-05 09:48:28", updated_at: "2020-01-05 09:48:28">, :promotion=>#<Promotion id: 1, amount: 0.5e1, customer_id: nil, created_at: "2020-01-05 09:48:28", updated_at: "2020-01-05 09:48:28">}
|
143
|
-
=> #<Order:0x00007f9ebcb17f08>
|
144
|
-
FROM /Users/st0012/projects/tapping_device-demo/app/controllers/orders_controller.rb:11
|
145
|
-
```
|
146
|
-
|
147
|
-
The output's order might look strange. This is because `tapping_device` needs to wait for the call to return in order to have its return value.
|
128
|
+
In the `PostReviser#revise!`, it uses many instance variables to track different information:
|
148
129
|
|
149
|
-
|
130
|
+
```ruby
|
131
|
+
# lib/post_revisor.rb
|
132
|
+
def revise!(editor, fields, opts = {})
|
133
|
+
@editor = editor
|
134
|
+
@fields = fields.with_indifferent_access
|
135
|
+
@opts = opts
|
150
136
|
|
151
|
-
|
137
|
+
@topic_changes = TopicChanges.new(@topic, editor)
|
138
|
+
|
139
|
+
# ......
|
152
140
|
|
153
|
-
|
154
|
-
|
155
|
-
tap_init!(Student) do |payload|
|
156
|
-
calls << [payload[:method_name], payload[:arguments]]
|
157
|
-
end
|
141
|
+
@revised_at = @opts[:revised_at] || Time.now
|
142
|
+
@last_version_at = @post.last_version_at || Time.now
|
158
143
|
|
159
|
-
|
160
|
-
|
144
|
+
@version_changed = false
|
145
|
+
@post_successfully_saved = true
|
161
146
|
|
162
|
-
|
147
|
+
@validate_post = true
|
148
|
+
# ......
|
149
|
+
end
|
163
150
|
```
|
164
151
|
|
165
|
-
|
152
|
+
Tracking the changes of that many instance variables can be a painful task, especially when we want to know the values before and after certain method call. This is why I created `print_mutations` to save us from this.
|
166
153
|
|
167
|
-
|
154
|
+
Like other helpers, you only need 1 line of code
|
168
155
|
|
169
156
|
```ruby
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
157
|
+
# app/controllers/posts_controller.rb
|
158
|
+
class PostsController
|
159
|
+
def update
|
160
|
+
# ......
|
161
|
+
revisor = PostRevisor.new(post, topic)
|
162
|
+
print_mutations(revisor)
|
163
|
+
revisor.revise!(current_user, changes, opts)
|
164
|
+
# ......
|
175
165
|
end
|
176
166
|
end
|
177
167
|
```
|
178
168
|
|
179
|
-
And you
|
169
|
+
And then you'll see all the state changes:
|
180
170
|
|
181
|
-
|
182
|
-
name FROM /PROJECT_PATH/sample/app/views/posts/show.html.erb:5
|
183
|
-
user_id FROM /PROJECT_PATH/sample/app/views/posts/show.html.erb:10
|
184
|
-
to_param FROM /RUBY_PATH/gems/2.6.0/gems/actionpack-5.2.0/lib/action_dispatch/routing/route_set.rb:236
|
185
|
-
```
|
171
|
+
<img src="https://github.com/st0012/tapping_device/blob/master/images/print_mutations.png" alt="image of print_mutations output" width="50%">
|
186
172
|
|
187
|
-
|
173
|
+
Now you can see what method changes which states. And more importantly, you get to see all the sate changes at once!
|
188
174
|
|
189
|
-
|
175
|
+
**You can try these examples on [my fork of discourse](https://github.com/st0012/discourse/tree/demo-for-tapping-device)**
|
190
176
|
|
191
|
-
`
|
177
|
+
### `write_*` helpers
|
192
178
|
|
193
|
-
|
194
|
-
class PostsController < ApplicationController
|
195
|
-
# GET /posts/new
|
196
|
-
def new
|
197
|
-
@post = Post.new
|
179
|
+
`tapping_device` also provides helpers that write the events into files:
|
198
180
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
end
|
203
|
-
end
|
204
|
-
```
|
181
|
+
- `write_calls(object)`
|
182
|
+
- `write_traces(object)`
|
183
|
+
- `write_mutations(object)`
|
205
184
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
Passed as 'klass' in method ':get_method_for_class'
|
211
|
-
> def get_method_for_class(klass)
|
212
|
-
at /Users/st0012/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/actionpack-6.0.0/lib/action_dispatch/routing/polymorphic_routes.rb:269
|
213
|
-
Passed as 'record' in method ':handle_model'
|
214
|
-
> def handle_model(record)
|
215
|
-
at /Users/st0012/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/actionpack-6.0.0/lib/action_dispatch/routing/polymorphic_routes.rb:227
|
216
|
-
Passed as 'record_or_hash_or_array' in method ':polymorphic_method'
|
217
|
-
> def self.polymorphic_method(recipient, record_or_hash_or_array, action, type, options)
|
218
|
-
at /Users/st0012/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/actionpack-6.0.0/lib/action_dispatch/routing/polymorphic_routes.rb:139
|
185
|
+
The default destination is `/tmp/tapping_device.log`. You can change it with the `log_file` option:
|
186
|
+
|
187
|
+
```ruby
|
188
|
+
write_calls(object, log_file: "/tmp/another_file")
|
219
189
|
```
|
220
190
|
|
221
|
-
### tap_assoc!
|
222
191
|
|
223
|
-
|
192
|
+
## Installation
|
193
|
+
Add this line to your application's Gemfile:
|
224
194
|
|
225
195
|
```ruby
|
226
|
-
|
196
|
+
gem 'tapping_device', group: :development
|
227
197
|
```
|
228
198
|
|
199
|
+
And then execute:
|
200
|
+
|
229
201
|
```
|
230
|
-
|
231
|
-
line_items FROM /MY_PROJECT/app/models/line_item_container_helpers.rb:44
|
232
|
-
effective_line_items FROM /MY_PROJECT/app/models/line_item_container_helpers.rb:110
|
233
|
-
amending_orders FROM /MY_PROJECT/app/models/order.rb:385
|
234
|
-
amends_order FROM /MY_PROJECT/app/models/order.rb:432
|
202
|
+
$ bundle
|
235
203
|
```
|
236
204
|
|
237
|
-
|
238
|
-
|
239
|
-
`tap_sql!(anything_that_generates_sql_queries)` tracks sql queries generated from the target
|
205
|
+
Or install it directly:
|
240
206
|
|
241
|
-
```ruby
|
242
|
-
class PostsController < ApplicationController
|
243
|
-
def index
|
244
|
-
# simulate current_user
|
245
|
-
@current_user = User.last
|
246
|
-
# reusable ActiveRecord::Relation
|
247
|
-
@posts = Post.all
|
248
|
-
|
249
|
-
tap_sql!(@posts) do |payload|
|
250
|
-
puts("Method: #{payload[:method_name]} generated sql: #{payload[:sql]} from #{payload[:filepath]}:#{payload[:line_number]}")
|
251
|
-
end
|
252
|
-
end
|
253
|
-
end
|
254
207
|
```
|
255
|
-
|
256
|
-
```erb
|
257
|
-
<h1>Posts (<%= @posts.count %>)</h1>
|
258
|
-
......
|
259
|
-
<% @posts.each do |post| %>
|
260
|
-
......
|
261
|
-
<% end %>
|
262
|
-
......
|
263
|
-
<p>Posts created by you: <%= @posts.where(user: @current_user).count %></p>
|
208
|
+
$ gem install tapping_device
|
264
209
|
```
|
265
210
|
|
266
|
-
|
267
|
-
Method: count generated sql: SELECT COUNT(*) FROM "posts" from /PROJECT_PATH/rails-6-sample/app/views/posts/index.html.erb:3
|
268
|
-
Method: each generated sql: SELECT "posts".* FROM "posts" from /PROJECT_PATH/rails-6-sample/app/views/posts/index.html.erb:16
|
269
|
-
Method: count generated sql: SELECT COUNT(*) FROM "posts" WHERE "posts"."user_id" = ? from /PROJECT_PATH/rails-6-sample/app/views/posts/index.html.erb:31
|
270
|
-
```
|
211
|
+
**Depending on the size of your application, `TappingDevice` could harm the performance significantly. So make sure you don't put it inside the production group**
|
271
212
|
|
272
213
|
|
273
|
-
|
274
|
-
|
275
|
-
|
214
|
+
## Advance Usages & Options
|
215
|
+
|
216
|
+
### Add Conditions With `.with`
|
217
|
+
|
218
|
+
Sometimes we don't need to know all the calls or traces of an object; we just want some of them. In those cases, we can chain the helpers with `.with` to filter the calls/traces.
|
276
219
|
|
277
220
|
```ruby
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
puts(device.calls.first.trace) #=>
|
284
|
-
/Users/st0012/projects/tapping_device/spec/tapping_device_spec.rb:287:in `block (4 levels) in <top (required)>'
|
285
|
-
/Users/st0012/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rspec-core-3.8.2/lib/rspec/core/example.rb:257:in `instance_exec'
|
286
|
-
/Users/st0012/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rspec-core-3.8.2/lib/rspec/core/example.rb:257:in `block in run'
|
287
|
-
/Users/st0012/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rspec-core-3.8.2/lib/rspec/core/example.rb:503:in `block in with_around_and_singleton_context_hooks'
|
288
|
-
/Users/st0012/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rspec-core-3.8.2/lib/rspec/core/example.rb:460:in `block in with_around_example_hooks'
|
289
|
-
/Users/st0012/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rspec-core-3.8.2/lib/rspec/core/hooks.rb:464:in `block in run'
|
221
|
+
# only prints calls with name matches /foo/
|
222
|
+
print_calls(object).with do |payload|
|
223
|
+
payload.method_name.to_s.match?(/foo/)
|
224
|
+
end
|
290
225
|
```
|
291
226
|
|
292
|
-
|
293
|
-
|
227
|
+
### Options
|
228
|
+
|
229
|
+
There are many options you can pass when using a helper method. You can list all available options and their default value with
|
294
230
|
|
295
231
|
```ruby
|
296
|
-
|
297
|
-
|
298
|
-
|
232
|
+
TappingDevice::Configurable::DEFAULTS #=> {
|
233
|
+
:filter_by_paths=>[],
|
234
|
+
:exclude_by_paths=>[],
|
235
|
+
:with_trace_to=>50,
|
236
|
+
:event_type=>:return,
|
237
|
+
:hijack_attr_methods=>false,
|
238
|
+
:track_as_records=>false,
|
239
|
+
:inspect=>false,
|
240
|
+
:colorize=>true,
|
241
|
+
:log_file=>"/tmp/tapping_device.log"
|
242
|
+
}
|
299
243
|
```
|
300
244
|
|
301
|
-
|
302
|
-
|
245
|
+
Here are some commonly used options:
|
246
|
+
|
247
|
+
#### `colorize: false`
|
248
|
+
|
249
|
+
- default: `true`
|
250
|
+
|
251
|
+
By default `print_calls` and `print_traces` colorize their output. If you don't want the colors, you can use `colorize: false` to disable it.
|
252
|
+
|
303
253
|
|
304
254
|
```ruby
|
305
|
-
|
255
|
+
print_calls(object, colorize: false)
|
306
256
|
```
|
307
257
|
|
308
|
-
```
|
309
|
-
_read_attribute FROM /RUBY_PATH/gems/2.6.0/gems/activerecord-5.2.0/lib/active_record/attribute_methods/read.rb:40
|
310
|
-
name FROM /PROJECT_PATH/sample/app/views/posts/show.html.erb:5
|
311
|
-
_read_attribute FROM /RUBY_PATH/gems/2.6.0/gems/activerecord-5.2.0/lib/active_record/attribute_methods/read.rb:40
|
312
|
-
user_id FROM /PROJECT_PATH/sample/app/views/posts/show.html.erb:10
|
313
|
-
.......
|
314
258
|
|
315
|
-
|
259
|
+
#### `inspect: true`
|
316
260
|
|
317
|
-
|
318
|
-
user_id FROM /PROJECT_PATH/sample/app/views/posts/show.html.erb:10
|
319
|
-
to_param FROM /RUBY_PATH/gems/2.6.0/gems/actionpack-5.2.0/lib/action_dispatch/routing/route_set.rb:236
|
320
|
-
```
|
261
|
+
- default: `false`
|
321
262
|
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
### Payload of The Call
|
328
|
-
All tapping methods (start with `tap_`) takes a block and yield a `Payload` object as a block argument. It responds to
|
329
|
-
|
330
|
-
- `target` - the target for `tap_x` call
|
331
|
-
- `receiver` - the receiver object
|
332
|
-
- `method_name` - method’s name (symbol)
|
333
|
-
- e.g. `:name`
|
334
|
-
- `method_object` - the method object that's being called. It might be `nil` in some edge cases.
|
335
|
-
- `arguments` - arguments of the method call
|
336
|
-
- e.g. `{name: “Stan”, age: 25}`
|
337
|
-
- `return_value` - return value of the method call
|
338
|
-
- `filepath` - path to the file that performs the method call
|
339
|
-
- `line_number`
|
340
|
-
- `defined_class` - in which class that defines the method being called
|
341
|
-
- `trace` - stack trace of the call. Default is an empty array unless `with_trace_to` option is set
|
342
|
-
- `sql` - sql that generated from the call (only present in `tap_sql!` payloads)
|
343
|
-
- `tp` - trace point object of this call
|
344
|
-
|
345
|
-
|
346
|
-
#### Symbols for Payload Helpers
|
347
|
-
- `FROM` for method call’s location
|
348
|
-
- `<=` for arguments
|
349
|
-
- `=>` for return value
|
350
|
-
- `@` for defined class
|
351
|
-
|
352
|
-
#### Payload Helpers
|
353
|
-
- `method_name_and_location` - `initialize FROM /PROJECT_PATH/tapping_device/spec/payload_spec.rb:7`
|
354
|
-
- `method_name_and_arguments` - `initialize <= {:name=>\"Stan\", :age=>25}`
|
355
|
-
- `method_name_and_return_value` - `ten => 10`
|
356
|
-
- `method_name_and_defined_class` - `initialize @ Student`
|
357
|
-
- `passed_at` -
|
358
|
-
```
|
359
|
-
Passed as 'object' in method ':initialize'
|
360
|
-
at /Users/st0012/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/actionview-6.0.0/lib/action_view/helpers/tags/label.rb:60
|
263
|
+
As you might have noticed, all the objects are converted into strings with `#to_s` instead of `#inspect`. This is because when used on some Rails objects, `#inspect` can generate a significantly larger string than `#to_s`. For example:
|
264
|
+
|
265
|
+
``` ruby
|
266
|
+
post.to_s #=> #<Post:0x00007f89a55201d0>
|
267
|
+
post.inspect #=> #<Post id: 649, user_id: 3, topic_id: 600, post_number: 1, raw: "Hello world", cooked: "<p>Hello world</p>", created_at: "2020-05-24 08:07:29", updated_at: "2020-05-24 08:07:29", reply_to_post_number: nil, reply_count: 0, quote_count: 0, deleted_at: nil, off_topic_count: 0, like_count: 0, incoming_link_count: 0, bookmark_count: 0, score: nil, reads: 0, post_type: 1, sort_order: 1, last_editor_id: 3, hidden: false, hidden_reason_id: nil, notify_moderators_count: 0, spam_count: 0, illegal_count: 0, inappropriate_count: 0, last_version_at: "2020-05-24 08:07:29", user_deleted: false, reply_to_user_id: nil, percent_rank: 1.0, notify_user_count: 0, like_score: 0, deleted_by_id: nil, edit_reason: nil, word_count: 2, version: 1, cook_method: 1, wiki: false, baked_at: "2020-05-24 08:07:29", baked_version: 2, hidden_at: nil, self_edits: 0, reply_quoted: false, via_email: false, raw_email: nil, public_version: 1, action_code: nil, image_url: nil, locked_by_id: nil, image_upload_id: nil>
|
361
268
|
```
|
362
269
|
|
363
|
-
|
270
|
+
#### `hijack_attr_methods: true`
|
364
271
|
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
```
|
272
|
+
- default: `false`
|
273
|
+
- except for `tap_mutation!` and `print_mutations`
|
274
|
+
|
275
|
+
Because `TracePoint` doesn't track methods generated by `attr_*` helpers (see [this issue](https://bugs.ruby-lang.org/issues/16383) for more info), we need to redefine those methods with the normal method definition.
|
370
276
|
|
371
|
-
|
277
|
+
For example, it generates
|
372
278
|
|
373
|
-
```
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
FROM /Users/st0012/projects/tapping_device/spec/payload_spec.rb:7
|
279
|
+
```ruby
|
280
|
+
def name=(val)
|
281
|
+
@name = val
|
282
|
+
end
|
378
283
|
```
|
379
284
|
|
380
|
-
|
381
|
-
|
382
|
-
Tapping methods introduced above like `tap_on!` are designed for simple use cases. They're actually short for
|
285
|
+
for
|
383
286
|
|
384
287
|
```ruby
|
385
|
-
|
386
|
-
device.tap_on!(object)
|
288
|
+
attr_writer :name
|
387
289
|
```
|
388
290
|
|
389
|
-
|
291
|
+
This hack will only be applied to the target instance with `instance_eval`. So other instances of the class remain untouched.
|
292
|
+
|
293
|
+
The default is `false` because
|
294
|
+
|
295
|
+
1. Checking what methods are generated by `attr_*` helpers isn't free. It's an `O(n)` operation, where `n` is the number of methods the target object has.
|
296
|
+
2. It's still unclear if this hack safe enough for most applications.
|
297
|
+
|
298
|
+
|
299
|
+
### Global Configuration
|
300
|
+
|
301
|
+
If you don't want to pass options every time you use a helper, you can use global configuration to change the default values:
|
390
302
|
|
391
|
-
|
303
|
+
```ruby
|
304
|
+
TappingDevice.config[:colorize] = false
|
305
|
+
TappingDevice.config[:hijack_attr_methods] = true
|
306
|
+
```
|
392
307
|
|
393
|
-
|
394
|
-
1. Manually calling `device.stop!`
|
395
|
-
2. Setting stop condition with `device.stop_when`, like
|
308
|
+
And if you're using Rails, you can put the configs under `config/initializers/tapping_device.rb` like this:
|
396
309
|
|
397
310
|
```ruby
|
398
|
-
|
399
|
-
|
311
|
+
if defined?(TappingDevice)
|
312
|
+
TappingDevice.config[:colorize] = false
|
313
|
+
TappingDevice.config[:hijack_attr_methods] = true
|
400
314
|
end
|
401
315
|
```
|
402
316
|
|
403
|
-
#### Device states & Managing Devices
|
404
317
|
|
405
|
-
|
318
|
+
### Lower-Level Helpers
|
319
|
+
`print_calls` and `print_traces` aren't the only helpers you can get from `TappingDevice`. They are actually built on top of other helpers, which you can use as well. To know more about them, please check [this page](https://github.com/st0012/tapping_device/wiki/Advance-Usages)
|
406
320
|
|
407
|
-
- `Initial` - means the instance is initialized but hasn't tapped on anything.
|
408
|
-
- `Enabled` - means the instance is tapping on something (has called `tap_*` methods).
|
409
|
-
- `Disabled` - means the instance has been disabled. It will no longer receive any call info.
|
410
321
|
|
411
|
-
|
322
|
+
### Related Blog Posts
|
323
|
+
- [Optimize Your Debugging Process With Object-Oriented Tracing and tapping_device](http://bit.ly/object-oriented-tracing)
|
324
|
+
- [Debug Rails issues effectively with tapping_device](https://dev.to/st0012/debug-rails-issues-effectively-with-tappingdevice-c7c)
|
325
|
+
- [Want to know more about your Rails app? Tap on your objects!](https://dev.to/st0012/want-to-know-more-about-your-rails-app-tap-on-your-objects-bd3)
|
412
326
|
|
413
|
-
- `TappingDevice.devices` - Lists all registered devices with `initial` or `enabled` state. Note that any instance that's been stopped will be removed from the list.
|
414
|
-
- `TappingDevice.stop_all!` - Stops all registered devices and remove them from the `devices` list.
|
415
|
-
- `TappingDevice.suspend_new!` - Suspends any device instance from changing their state from `initial` to `enabled`. Which means any `tap_*` calls after it will no longer work.
|
416
|
-
- `TappingDevice.reset!` - Cancels `suspend_new` (if called) and stops/removes all created devices. Useful to reset the environment between test cases.
|
417
327
|
|
418
328
|
## Development
|
419
|
-
|
420
329
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
421
330
|
|
422
331
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|