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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 23d3086bd40ed2665b040147abdbd7ca9cf2fd6e8d0e4300e0dfe8c6c14def70
4
- data.tar.gz: b980e4cbf079204151b81645aa9c097254c0be1f514c2e09482ee3a4ede1ec68
3
+ metadata.gz: 9311ddb749d3c7bf09306161da25191c0de47734dea77f645f5d5af62a55d802
4
+ data.tar.gz: 4df7c9fef5c3a3a2b3852b5b4f4db31ec071149dd19b3fceb1df6f6b1ac191e8
5
5
  SHA512:
6
- metadata.gz: 4d731a0cc9436e48354a55afe094cd16ce93778876fd541702813645be21e2d77cdfa0580b93486c0a59ddf48c614df9106d752483842da5bec2bb19ee06e97a
7
- data.tar.gz: 1de7093fd6b474260a7b819ddffa8839dc26ff5e5553d450084515e9ce6b1d69cb97066c69fa49f48777548e18768dd52dc8114efc5a469e63e870f3005086c2
6
+ metadata.gz: deaece3e6096551df6fe3c7eb492f6049e72b32f7e19b7a8d4067f8d5a6dc9b6fe56a41d3bd9855220ae11c8adcc377cd188f51c043835845be5c2d9250bc6d1
7
+ data.tar.gz: 057766f277605fb3e80bd2797ee1256f0f6d81fbca56c95226199a72c7e14565dc353292d06711847e257d2f552e9eb3ddcd076ec35f1abd3aaf30cc9f686f5c
Binary file
@@ -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 }} and publish result
37
- uses: paambaati/codeclimate-action@v2.3.0
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
- coverageCommand: bundle exec rake
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
@@ -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)*
@@ -1,39 +1,39 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- tapping_device (0.4.10)
4
+ tapping_device (0.5.3)
5
5
  activerecord (>= 5.2)
6
- awesome_print
6
+ activesupport
7
+ pry
7
8
 
8
9
  GEM
9
10
  remote: https://rubygems.org/
10
11
  specs:
11
- activemodel (6.0.2.1)
12
- activesupport (= 6.0.2.1)
13
- activerecord (6.0.2.1)
14
- activemodel (= 6.0.2.1)
15
- activesupport (= 6.0.2.1)
16
- activesupport (6.0.2.1)
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
- awesome_print (1.8.0)
23
- coderay (1.1.2)
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.2)
28
+ i18n (1.8.3)
29
29
  concurrent-ruby (~> 1.0)
30
30
  json (2.3.0)
31
- method_source (0.9.2)
32
- minitest (5.14.0)
33
- pry (0.12.2)
34
- coderay (~> 1.1.0)
35
- method_source (~> 0.9.0)
36
- rake (10.0.4)
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.6)
57
+ tzinfo (1.2.7)
58
58
  thread_safe (~> 0.1)
59
- zeitwerk (2.2.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
- pry
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
  [![Test Coverage](https://api.codeclimate.com/v1/badges/3e3732a6983785bccdbd/test_coverage)](https://codeclimate.com/github/st0012/tapping_device/test_coverage)
7
7
  [![Open Source Helpers](https://www.codetriage.com/st0012/tapping_device/badges/users.svg)](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
- ## Table of Content
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
- ## Introduction
35
- `tapping_device` is a debugging tool built based on a concept called `object-oriented tracing` and on top of Ruby's `TracePoint` class. It allows you to inspect an object’s behavior, and thus build the program’s execution path for later debugging. Here’s a post to explain how to use `object-oriented tracing` and this gem to improve your debugging workflow: [Optimize Your Debugging Process With Object-Oriented Tracing and tapping_device](http://bit.ly/object-oriented-tracing).
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
- Sample usage:
21
+ Still sounds vague? Let's see some examples:
38
22
 
39
- ### Print Object’s Traces
23
+ ### `print_calls` - Track Method Calls
40
24
 
41
- Let your objects report to you, so you don’t need to guess how they work!
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
- @cart = Cart.find(order_params[:cart_id])
47
- print_traces(@cart, exclude_by_paths: [/gems/])
48
- @order = OrderCreationService.new.perform(@cart)
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
- gem 'tapping_device', group: :development
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
- And then execute:
63
+ Now, if you execute the code, like via tests:
75
64
 
76
- ```
77
- $ bundle
65
+ ```shell
66
+ $ rspec spec/requests/posts_controller_spec.rb:603
78
67
  ```
79
68
 
80
- Or install it yourself as:
69
+ You can get all the method calls it performs with basically everything you need to know
81
70
 
82
- ```
83
- $ gem install tapping_device
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
+ ![explanation of individual entry](https://github.com/st0012/tapping_device/blob/master/images/print_calls%20-%20single%20entry.png)
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
- It prints the object's trace. It's like mounting a GPS tracker + a spy camera on your object, so you can inspect your program through the object's eyes.
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
- @cart = Cart.find(order_params[:cart_id])
96
- print_traces(@cart, exclude_by_paths: [/gems/])
97
- @order = OrderCreationService.new.perform(@cart)
98
- end
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
- Passed as 'cart' in 'OrderCreationService#perform' at /Users/st0012/projects/tapping_device-demo/app/controllers/orders_controller.rb:10
103
- Passed as 'cart' in 'OrderCreationService#validate_cart' at /Users/st0012/projects/tapping_device-demo/app/services/order_creation_service.rb:8
104
- Called :reserved_until FROM /Users/st0012/projects/tapping_device-demo/app/services/order_creation_service.rb:18
105
- Called :errors FROM /Users/st0012/projects/tapping_device-demo/app/services/order_creation_service.rb:9
106
- Passed as 'cart' in 'OrderCreationService#apply_discount' at /Users/st0012/projects/tapping_device-demo/app/services/order_creation_service.rb:10
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
- ### print_calls_in_detail
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
+ ![image of print_traces output](https://github.com/st0012/tapping_device/blob/master/images/print_traces.png)
109
+
110
+ ### `print_mutations` - Display All State Changes At Once
112
111
 
113
- It prints the object's calls in detail (including call location, arguments, and return value). It's useful for observing an object's behavior when debugging.
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
- #### Options
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
- class OrdersController < ApplicationController
120
- def create
121
- @cart = Cart.find(order_params[:cart_id])
122
- service = OrderCreationService.new
123
- print_calls_in_detail(service)
124
- @order = service.perform(@cart)
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
- ### tap_init!
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
- `tap_init!(class)` - tracks a class’ instance initialization
137
+ @topic_changes = TopicChanges.new(@topic, editor)
138
+
139
+ # ......
152
140
 
153
- ```ruby
154
- calls = []
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
- Student.new("Stan", 18)
160
- Student.new("Jane", 23)
144
+ @version_changed = false
145
+ @post_successfully_saved = true
161
146
 
162
- puts(calls.to_s) #=> [[:initialize, {:name=>"Stan", :age=>18}], [:initialize, {:name=>"Jane", :age=>23}]]
147
+ @validate_post = true
148
+ # ......
149
+ end
163
150
  ```
164
151
 
165
- ### tap_on!
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
- `tap_on!(object)` - tracks any calls received by the object.
154
+ Like other helpers, you only need 1 line of code
168
155
 
169
156
  ```ruby
170
- class PostsController < ApplicationController
171
- before_action :set_post, only: [:show, :edit, :update, :destroy]
172
-
173
- def show
174
- tap_on!(@post).and_print(:method_name_and_location)
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 can see these in log:
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
- Also check the `track_as_records` option if you want to track `ActiveRecord` records.
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
- ### tap_passed!
175
+ **You can try these examples on [my fork of discourse](https://github.com/st0012/discourse/tree/demo-for-tapping-device)**
190
176
 
191
- `tap_passed!(target)` tracks method calls that **takes the target as its argument**. This is particularly useful when debugging libraries. It saves your time from jumping between files and check which path the object will go.
177
+ ### `write_*` helpers
192
178
 
193
- ```ruby
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
- tap_passed!(@post) do |payload|
200
- puts(payload.passed_at(with_method_head: true))
201
- end
202
- end
203
- end
204
- ```
181
+ - `write_calls(object)`
182
+ - `write_traces(object)`
183
+ - `write_mutations(object)`
205
184
 
206
- ```
207
- Passed as 'record' in method ':polymorphic_mapping'
208
- > def polymorphic_mapping(record)
209
- 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:131
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
- `tap_assoc!(activerecord_object)` tracks association calls on a record, like `post.comments`
192
+ ## Installation
193
+ Add this line to your application's Gemfile:
224
194
 
225
195
  ```ruby
226
- tap_assoc!(order).and_print(:method_name_and_location)
196
+ gem 'tapping_device', group: :development
227
197
  ```
228
198
 
199
+ And then execute:
200
+
229
201
  ```
230
- payments FROM /RUBY_PATH/gems/2.6.0/gems/jsonapi-resources-0.9.10/lib/jsonapi/resource.rb:124
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
- ### tap_sql!
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
- ### Options
274
- #### with_trace_to
275
- It takes an integer as the number of traces we want to put into `trace`. Default is `nil`, so `trace` would be empty.
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
- stan = Student.new("Stan", 18)
279
- tap_on!(stan, with_trace_to: 5)
280
-
281
- stan.name
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
- #### track_as_records
293
- It makes the device to track objects as they are ActiveRecord instances. For example:
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
- tap_on!(@post, track_as_records: true)
297
- post = Post.find(@post.id) # same record but a different object
298
- post.title #=> this call will be recorded as well
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
- #### exclude_by_paths
302
- It takes an array of call path patterns that we want to skip. This could be very helpful when working on a large project like Rails applications.
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
- tap_on!(@post, exclude_by_paths: [/active_record/]).and_print(:method_name_and_location)
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
- # versus
259
+ #### `inspect: true`
316
260
 
317
- name FROM /PROJECT_PATH/sample/app/views/posts/show.html.erb:5
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
- #### filter_by_paths
323
-
324
- Like `exclude_by_paths`, but work in the opposite way.
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
- You can also set `passed_at(with_method_head: true)` to see the method's head.
270
+ #### `hijack_attr_methods: true`
364
271
 
365
- ```
366
- Passed as 'object' in method ':initialize'
367
- > def initialize(template_object, object_name, method_name, object, tag_value)
368
- 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
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
- - `detail_call_info`
277
+ For example, it generates
372
278
 
373
- ```
374
- initialize @ Student
375
- <= {:name=>"Stan", :age=>25}
376
- => 25
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
- ### Advance Usages
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
- device = TappingDevice.new { # tapping action }
386
- device.tap_on!(object)
288
+ attr_writer :name
387
289
  ```
388
290
 
389
- And if you want to do some more configurations like stopping them manually or setting stop condition, you must have a `TappingDevie` instance. You can either get them like the above code or save the return value of `tap_*!` method calls.
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
- #### Stop tapping
303
+ ```ruby
304
+ TappingDevice.config[:colorize] = false
305
+ TappingDevice.config[:hijack_attr_methods] = true
306
+ ```
392
307
 
393
- Once you have a `TappingDevice` instance in hand, you will be able to stop the tapping by
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
- device.stop_when do |payload|
399
- device.calls.count >= 10 # stop after gathering 10 calls’ data
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
- Each `TappingDevice` instance can have 3 states:
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
- When debugging, we may create many device instances and tap objects in several places. Then it'll be quite annoying to manage their states. So `TappingDevice` has several class methods that allows you to manage all `TappingDevice` instances:
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).