object_inspector 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -10
- data/Gemfile.lock +3 -1
- data/README.md +207 -44
- data/bin/console +2 -0
- data/lib/object_inspector/conversions.rb +22 -0
- data/lib/object_inspector/inspector.rb +18 -31
- data/lib/object_inspector/object_interrogator.rb +10 -2
- data/lib/object_inspector/scope.rb +82 -0
- data/lib/object_inspector/version.rb +1 -1
- data/lib/object_inspector.rb +50 -6
- data/object_inspector.gemspec +2 -2
- metadata +21 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 93cdfccb3e1e30286035a4c152053794eb78ba6b99e3bf7b6d5679ca60c8f8fb
|
4
|
+
data.tar.gz: e551588d9bc978dd5676a14188787a55eed91b0e81c31c44479ac88559f350bc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2ed62b8237dff20c6de7157c1c6475b08643396cc0fc1b71f2c334a562ca9253ee8da911949fc63c0549bad881e8f2704817c6c28bc265b6fd596ca5c5e47ad8
|
7
|
+
data.tar.gz: 6ff191c8ed79769432a2792b3c0c88d7ff6aae372d5ce323e455b6e890caecdb131dcf25ccdfd704fb9ec26bf416413330535d169dbe2d0f38d48c40485a3310
|
data/CHANGELOG.md
CHANGED
@@ -1,18 +1,24 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
### 0.3.0 - 2018-04-14
|
2
|
+
|
3
|
+
- Remove optional dependency on ActiveSupport::StringInquirer. [Scopes are now objects](https://github.com/pdobb/object_inspector/blob/master/lib/object_inspector/scope.rb) that act like ActiveSupport::StringInquirer objects.
|
4
|
+
- Add ObjectInspector::Scope.join_flags helper method.
|
5
|
+
- Add ObjectInspector::Scope.join_info helper method.
|
6
|
+
- Scope: Show an out-of-scope-placeholder symbol (*) when predicate is not matched and a block is given.
|
7
|
+
- Scope: Add wild-card "all" scope that is always evaluated as true / a match.
|
8
|
+
- Add ability to specify multiple scopes. e.g. my_object.inspect(scope: %i[verbose complex])
|
9
|
+
- Add gem defaults configuration.
|
4
10
|
|
5
11
|
|
6
12
|
### 0.2.0 - 2018-04-12
|
7
13
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
+
- Automatically inspect wrapped Objects, if applicable.
|
15
|
+
- Use `display_name` if defined on object, in place of `inspect_name`.
|
16
|
+
- Add on-the-fly inspect methods when Symbols are passed in to #inspect.
|
17
|
+
- Update the `flags` and `info` demarcation symbols.
|
18
|
+
- Add ObjectInspector::TemplatingFormatter, and use it as the new default since it's faster.
|
19
|
+
- Rename ObjectInspector::DefaultFormatter to ObjectInspector::CombiningFormatter.
|
14
20
|
|
15
21
|
|
16
22
|
### 0.1.0 - 2018-04-09
|
17
23
|
|
18
|
-
|
24
|
+
- Initial release!
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
object_inspector (0.
|
4
|
+
object_inspector (0.3.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
@@ -20,6 +20,7 @@ GEM
|
|
20
20
|
builder
|
21
21
|
minitest (>= 5.0)
|
22
22
|
ruby-progressbar
|
23
|
+
object_identifier (0.1.0)
|
23
24
|
pry (0.11.3)
|
24
25
|
coderay (~> 1.1.0)
|
25
26
|
method_source (~> 0.9.0)
|
@@ -43,6 +44,7 @@ DEPENDENCIES
|
|
43
44
|
byebug (~> 10.0)
|
44
45
|
minitest (~> 5.0)
|
45
46
|
minitest-reporters (~> 1.2)
|
47
|
+
object_identifier (~> 0.1)
|
46
48
|
object_inspector!
|
47
49
|
pry (~> 0.11)
|
48
50
|
pry-byebug (~> 3.6)
|
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# ObjectInspector
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/object_inspector.svg)](https://badge.fury.io/rb/object_inspector)
|
4
|
-
[![Build Status](https://travis-ci.org/
|
4
|
+
[![Build Status](https://travis-ci.org/pdobb/object_inspector.svg?branch=master)](https://travis-ci.org/pdobb/object_inspector)
|
5
5
|
[![Test Coverage](https://api.codeclimate.com/v1/badges/34e821263d9e0c33d536/test_coverage)](https://codeclimate.com/github/pdobb/object_inspector/test_coverage)
|
6
6
|
[![Maintainability](https://api.codeclimate.com/v1/badges/34e821263d9e0c33d536/maintainability)](https://codeclimate.com/github/pdobb/object_inspector/maintainability)
|
7
7
|
|
@@ -32,6 +32,24 @@ Tested MRI Ruby Versions:
|
|
32
32
|
* 2.3.7
|
33
33
|
* 2.4.4
|
34
34
|
* 2.5.1
|
35
|
+
* edge
|
36
|
+
|
37
|
+
|
38
|
+
## Configuration
|
39
|
+
|
40
|
+
Global/default values for ObjectInspector can be configured via the ObjectInspector::Configuration object.
|
41
|
+
|
42
|
+
_Note: In a Rails app, the following would go in e.g. `config/initializers/object_inspector.rb`_
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
# Default values are shown.
|
46
|
+
ObjectInspector.configure do |config|
|
47
|
+
config.wild_card_scope = "all"
|
48
|
+
config.out_of_scope_placeholder = "*"
|
49
|
+
config.flags_separator = " / "
|
50
|
+
config.info_separator = " | "
|
51
|
+
end
|
52
|
+
```
|
35
53
|
|
36
54
|
|
37
55
|
## Usage
|
@@ -60,13 +78,13 @@ class MyObject
|
|
60
78
|
def inspect
|
61
79
|
ObjectInspector::Inspector.inspect(self,
|
62
80
|
identification: "My Object",
|
63
|
-
flags: "FLAG1",
|
81
|
+
flags: "FLAG1 / FLAG2",
|
64
82
|
info: "INFO",
|
65
83
|
name: "NAME")
|
66
84
|
end
|
67
85
|
end
|
68
86
|
|
69
|
-
MyObject.new.inspect # => "<My Object(FLAG1) INFO :: NAME>"
|
87
|
+
MyObject.new.inspect # => "<My Object(FLAG1 / FLAG2) INFO :: NAME>"
|
70
88
|
```
|
71
89
|
|
72
90
|
Or, define `inspect_identification`, `inspect_flags`, `inspect_info`, and `inspect_name` as either public or private methods on Object.
|
@@ -80,12 +98,12 @@ class MyObject
|
|
80
98
|
private
|
81
99
|
|
82
100
|
def inspect_identification; "My Object" end
|
83
|
-
def inspect_flags; "FLAG1" end
|
101
|
+
def inspect_flags; "FLAG1 / FLAG2" end
|
84
102
|
def inspect_info; "INFO" end
|
85
103
|
def inspect_name; "NAME" end
|
86
104
|
end
|
87
105
|
|
88
|
-
MyObject.new.inspect # => "<My Object(FLAG1) INFO :: NAME>"
|
106
|
+
MyObject.new.inspect # => "<My Object(FLAG1 / FLAG2) INFO :: NAME>"
|
89
107
|
```
|
90
108
|
|
91
109
|
|
@@ -118,7 +136,7 @@ end
|
|
118
136
|
MyObject.new.inspect # => "<My Object(FLAG1) INFO :: NAME>"
|
119
137
|
```
|
120
138
|
|
121
|
-
Or, define `inspect_identification`, `inspect_flags`, `inspect_info`, and `inspect_name` in Object.
|
139
|
+
Or, define `inspect_identification`, `inspect_flags`, `inspect_info`, and `inspect_name` (or `display_name`) in Object.
|
122
140
|
|
123
141
|
```ruby
|
124
142
|
class MyObject
|
@@ -127,61 +145,181 @@ class MyObject
|
|
127
145
|
private
|
128
146
|
|
129
147
|
def inspect_identification; "My Object" end
|
130
|
-
def inspect_flags; "FLAG1" end
|
148
|
+
def inspect_flags; "FLAG1 / FLAG2" end
|
131
149
|
def inspect_info; "INFO" end
|
132
|
-
def inspect_name; "NAME" end
|
150
|
+
def inspect_name; "NAME" end # Or: def display_name; "NAME" end
|
133
151
|
end
|
134
152
|
|
135
|
-
MyObject.new.inspect # => "<My Object(FLAG1) INFO :: NAME>"
|
153
|
+
MyObject.new.inspect # => "<My Object(FLAG1 / FLAG2) INFO :: NAME>"
|
136
154
|
```
|
137
155
|
|
138
156
|
|
139
|
-
##
|
157
|
+
## Scopes
|
140
158
|
|
141
|
-
|
159
|
+
Use the `scope` option to define the scope of the `inspect_*` methods. The supplied value will be wrapped by the ObjectInspector::Scope helper object.
|
160
|
+
The default value is `ObjectInspector::Scope.new(:self)`.
|
161
|
+
|
162
|
+
|
163
|
+
### Scope Names
|
164
|
+
|
165
|
+
ObjectInspector::Scope acts like [ActiveSupport::StringInquirer](http://api.rubyonrails.org/classes/ActiveSupport/StringInquirer.html). This is a prettier way to test for a given type of "scope" within objects.
|
166
|
+
|
167
|
+
The ObjectInspector::Scope objects in these examples are the same as specifying `<scope_name>` like this:
|
142
168
|
|
143
169
|
```ruby
|
144
|
-
|
145
|
-
|
170
|
+
my_object.inspect(scope: <scope_name>)
|
171
|
+
```
|
146
172
|
|
147
|
-
def my_method1; "Result1" end
|
148
|
-
def my_method2; "Result2" end
|
149
173
|
|
150
|
-
|
151
|
-
|
174
|
+
Options:
|
175
|
+
- `:self` (Default) -- Is meant to confine object interrogation to self (don't interrogate neighboring objects).
|
176
|
+
- `:all` -- Is meant to match on all scopes, regardless of their name.
|
177
|
+
- `<custom>` -- Anything else that makes sense for the object to key on.
|
152
178
|
|
153
|
-
|
154
|
-
|
155
|
-
|
179
|
+
```ruby
|
180
|
+
scope = ObjectInspector::Scope.new
|
181
|
+
scope.self? # => true
|
182
|
+
scope.verbose? # => false
|
183
|
+
scope.complex? # => false
|
184
|
+
```
|
185
|
+
|
186
|
+
|
187
|
+
#### Multiple Scope Names
|
188
|
+
|
189
|
+
It is also possible to pass in multiple scope names to match on.
|
190
|
+
|
191
|
+
```ruby
|
192
|
+
scope = ObjectInspector::Scope.new(%i[verbose complex])
|
193
|
+
scope.self? # => false
|
194
|
+
scope.verbose? # => true
|
195
|
+
scope.complex? # => true
|
196
|
+
```
|
197
|
+
|
198
|
+
|
199
|
+
#### The "Wild Card" Scope
|
200
|
+
|
201
|
+
Finally, `:all` is a "wild card" scope name, and will match on all scope names.
|
202
|
+
|
203
|
+
```ruby
|
204
|
+
scope = ObjectInspector::Scope.new(:all)
|
205
|
+
scope.self? # => true
|
206
|
+
scope.verbose? # => true
|
207
|
+
scope.complex? # => true
|
208
|
+
```
|
209
|
+
|
210
|
+
|
211
|
+
### Scope blocks
|
212
|
+
|
213
|
+
Passing a block to a scope predicate falls back to the out-of-scope placeholder (`*` by default) if the scope does not match.
|
214
|
+
|
215
|
+
```ruby
|
216
|
+
scope = ObjectInspector::Scope.new(:verbose)
|
217
|
+
scope.verbose? { "MATCH" } # => "MATCH"
|
218
|
+
scope.complex? { "MATCH" } # => "*"
|
219
|
+
```
|
220
|
+
|
221
|
+
|
222
|
+
### Scope Joiners
|
223
|
+
|
224
|
+
ObjectInspector::Scope also offers helper methods for uniformly joining inspect elements:
|
225
|
+
- `join_flags` -- Joins flags with ` / ` by default
|
226
|
+
- `join_info` -- Joins info items with ` | ` by default
|
227
|
+
|
228
|
+
```ruby
|
229
|
+
scope = ObjectInspector::Scope.new(:verbose)
|
230
|
+
scope.join_flags([1, 2, 3]) # => "1 / 2 / 3"
|
231
|
+
scope.join_info([1, 2, 3]) # => "1 | 2 | 3"
|
156
232
|
```
|
157
233
|
|
158
234
|
|
159
|
-
|
235
|
+
### Conversion to ObjectInspector::Scope
|
160
236
|
|
161
|
-
|
237
|
+
ObjectInspector::Conversions.Scope() is available for proper conversion to ObjectInspector::Scope objects. Though this should rarely be necessary as conversion is performed automatically when calling `<my_object>.inspect(scope: <scope_name>)`.
|
238
|
+
|
239
|
+
```ruby
|
240
|
+
ObjectInspector::Conversions.Scope(:self)
|
241
|
+
# => #<ObjectInspector::Scope:0x007ff78ab8e7f8 @name="self">
|
242
|
+
|
243
|
+
scope = ObjectInspector::Scope.new(:verbose)
|
244
|
+
result = ObjectInspector::Conversions.Scope(scope)
|
245
|
+
# => #<ObjectInspector::Scope:0x007ff78ac9c140 @name="verbose">
|
246
|
+
|
247
|
+
scope.object_id == result.object_id # => true
|
248
|
+
```
|
162
249
|
|
163
|
-
|
164
|
-
|
250
|
+
|
251
|
+
## Full Example
|
165
252
|
|
166
253
|
```ruby
|
167
254
|
class MyObject
|
168
255
|
include ObjectInspector::InspectorsHelper
|
169
256
|
|
170
|
-
|
171
|
-
|
257
|
+
attr_reader :name,
|
258
|
+
:a2
|
259
|
+
|
260
|
+
def initialize(name, a2 = 2)
|
261
|
+
@name = name
|
262
|
+
@a2 = a2
|
263
|
+
end
|
264
|
+
|
265
|
+
def associated_object1
|
266
|
+
OpenStruct.new(flags: "AO1_FLAG1")
|
267
|
+
end
|
268
|
+
|
269
|
+
def associated_object2
|
270
|
+
OpenStruct.new(flags: "AO2_FLAG1")
|
271
|
+
end
|
272
|
+
|
273
|
+
private
|
172
274
|
|
173
|
-
|
174
|
-
|
275
|
+
def inspect_identification
|
276
|
+
identify(:a2)
|
277
|
+
end
|
175
278
|
|
176
|
-
|
177
|
-
flags
|
279
|
+
def inspect_flags(scope:)
|
280
|
+
flags = ["DEFAULT_FLAG"]
|
178
281
|
|
179
|
-
flags
|
282
|
+
flags <<
|
283
|
+
scope.verbose? {
|
284
|
+
[
|
285
|
+
associated_object1.flags,
|
286
|
+
associated_object2.flags,
|
287
|
+
]
|
288
|
+
}
|
289
|
+
|
290
|
+
scope.join_flags(flags)
|
291
|
+
end
|
292
|
+
|
293
|
+
def inspect_info(scope:)
|
294
|
+
info = ["Default Info"]
|
295
|
+
info << "Complex Info" if scope.complex?
|
296
|
+
info << scope.verbose? { "Verbose Info" }
|
297
|
+
|
298
|
+
scope.join_info(info)
|
299
|
+
end
|
300
|
+
|
301
|
+
# Or `def inspect_name`
|
302
|
+
def display_name
|
303
|
+
name
|
180
304
|
end
|
181
305
|
end
|
182
306
|
|
183
|
-
MyObject.new
|
184
|
-
|
307
|
+
my_object = MyObject.new("Name")
|
308
|
+
|
309
|
+
my_object.inspect
|
310
|
+
# => "<MyObject[a2:2](DEFAULT_FLAG / *) Default Info | * :: Name>"
|
311
|
+
|
312
|
+
my_object.inspect(scope: :complex)
|
313
|
+
# => "<MyObject[a2:2](DEFAULT_FLAG / *) Default Info | Complex Info | * :: Name>"
|
314
|
+
|
315
|
+
my_object.inspect(scope: :verbose)
|
316
|
+
# => "<MyObject[a2:2](DEFAULT_FLAG / AO1_FLAG1 / AO2_FLAG1) Default Info | Verbose Info :: Name>"
|
317
|
+
|
318
|
+
my_object.inspect(scope: %i[self complex verbose])
|
319
|
+
# => "<MyObject[a2:2](DEFAULT_FLAG / AO1_FLAG1 / AO2_FLAG1) Default Info | Complex Info | Verbose Info :: Name>"
|
320
|
+
|
321
|
+
my_object.inspect(scope: :all)
|
322
|
+
# => "<MyObject[a2:2](DEFAULT_FLAG / AO1_FLAG1 / AO2_FLAG1) Default Info | Complex Info | Verbose Info :: Name>"
|
185
323
|
```
|
186
324
|
|
187
325
|
|
@@ -207,17 +345,37 @@ class MyWrappedObject
|
|
207
345
|
|
208
346
|
private
|
209
347
|
|
210
|
-
def inspect_flags; "FLAG1" end
|
348
|
+
def inspect_flags; "FLAG1 / FLAG2" end
|
211
349
|
def inspect_info; "INFO" end
|
212
350
|
end
|
213
351
|
|
214
352
|
MyWrapperObject.new.inspect
|
215
|
-
# => "<MyWrapperObject(WRAPPER_FLAG1)> ⇨ <MyWrappedObject(FLAG1) INFO>"
|
353
|
+
# => "<MyWrapperObject(WRAPPER_FLAG1)> ⇨ <MyWrappedObject(FLAG1 / FLAG2) INFO>"
|
216
354
|
```
|
217
355
|
|
218
356
|
This feature is recursive.
|
219
357
|
|
220
358
|
|
359
|
+
## On-the-fly Inspect Methods
|
360
|
+
|
361
|
+
When passed as an option (as opposed to being called via an Object-defined method) symbols will be called/evaluated on Object on the fly.
|
362
|
+
|
363
|
+
```ruby
|
364
|
+
class MyObject
|
365
|
+
include ObjectInspector::InspectorsHelper
|
366
|
+
|
367
|
+
def my_method1; "Result1" end
|
368
|
+
def my_method2; "Result2" end
|
369
|
+
|
370
|
+
def inspect_info; :my_method2 end
|
371
|
+
end
|
372
|
+
|
373
|
+
MyObject.new.inspect(info: "my_method1") # => "<MyObject my_method1>"
|
374
|
+
MyObject.new.inspect(info: :my_method2) # => "<MyObject Result2>"
|
375
|
+
MyObject.new.inspect # => "<MyObject my_method2>"
|
376
|
+
```
|
377
|
+
|
378
|
+
|
221
379
|
## Custom Formatters
|
222
380
|
|
223
381
|
A custom inspect formatter can be defined by implementing the interface defined by [ObjectInspector::BaseFormatter](https://github.com/pdobb/object_inspector/blob/master/lib/object_inspector/formatters/base_formatter.rb) and then passing that into ObjectInspector::Inspector.new.
|
@@ -235,18 +393,19 @@ class MyObject
|
|
235
393
|
def inspect
|
236
394
|
super(formatter: MyCustomFormatter,
|
237
395
|
identification: "IDENTIFICATION",
|
238
|
-
flags: "FLAG1
|
396
|
+
flags: "FLAG1 / FLAG2",
|
239
397
|
info: "INFO",
|
240
398
|
name: "NAME")
|
241
399
|
end
|
242
400
|
end
|
243
401
|
|
244
402
|
MyObject.new.inspect
|
245
|
-
# => "[IDENTIFICATION Flags: FLAG1
|
403
|
+
# => "[IDENTIFICATION Flags: FLAG1 / FLAG2 -- Info: INFO -- Name: NAME]"
|
246
404
|
```
|
247
405
|
|
248
|
-
See
|
249
|
-
|
406
|
+
See examples:
|
407
|
+
- [ObjectInspector::TemplatingFormatter]
|
408
|
+
- [ObjectInspector::CombiningFormatter]
|
250
409
|
|
251
410
|
|
252
411
|
## Performance
|
@@ -283,6 +442,7 @@ play scripts/benchmarking/formatters.rb
|
|
283
442
|
# == Done
|
284
443
|
```
|
285
444
|
|
445
|
+
|
286
446
|
#### Benchmarking Custom Formatters
|
287
447
|
|
288
448
|
Custom Formatters may be similarly gauged for comparison by adding them to the `custom_formatter_klasses` array before playing the script.
|
@@ -312,23 +472,26 @@ class MyObject
|
|
312
472
|
include ObjectInspector::InspectorsHelper
|
313
473
|
|
314
474
|
def my_method1
|
315
|
-
|
475
|
+
1
|
316
476
|
end
|
317
477
|
|
318
478
|
def my_method2
|
319
|
-
|
479
|
+
2
|
320
480
|
end
|
321
481
|
|
322
482
|
private
|
323
483
|
|
324
|
-
def inspect_identification
|
325
|
-
|
484
|
+
def inspect_identification
|
485
|
+
identify(:my_method1, :my_method2)
|
486
|
+
end
|
487
|
+
|
488
|
+
def inspect_flags; "FLAG1 / FLAG2" end
|
326
489
|
def inspect_info; "INFO" end
|
327
490
|
def inspect_name; "NAME" end
|
328
491
|
end
|
329
492
|
|
330
493
|
MyObject.new.inspect
|
331
|
-
# => "<MyObject[my_method1:
|
494
|
+
# => "<MyObject[my_method1:1, my_method2:2](FLAG1 / FLAG2) INFO :: NAME>"
|
332
495
|
```
|
333
496
|
|
334
497
|
|
data/bin/console
CHANGED
@@ -0,0 +1,22 @@
|
|
1
|
+
module ObjectInspector
|
2
|
+
# ObjectInspector::Conversions defines conversion functions used by
|
3
|
+
# ObjectInspector.
|
4
|
+
module Conversions
|
5
|
+
|
6
|
+
module_function
|
7
|
+
|
8
|
+
# Convert the passed in value to an {ObjectInspector::Scope} object.
|
9
|
+
# Just returns the pass in value if it already is an
|
10
|
+
# {ObjectInspector::Scope} object.
|
11
|
+
#
|
12
|
+
# @return [ObjectInspector::Scope]
|
13
|
+
def Scope(value)
|
14
|
+
case value
|
15
|
+
when ObjectInspector::Scope
|
16
|
+
value
|
17
|
+
else
|
18
|
+
ObjectInspector::Scope.new(value)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -5,26 +5,18 @@ module ObjectInspector
|
|
5
5
|
#
|
6
6
|
# @attr object [Object] the object being inspected
|
7
7
|
# @attr scope [Symbol] Object inspection type. For example:
|
8
|
-
# :self (default) -- Means: Only interrogate self
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
# for combining the output of into the inspect String
|
15
|
-
# @attr kargs [Hash] options to be sent to {#object}
|
8
|
+
# :self (default) -- Means: Only interrogate self. Don't visit neighbors.
|
9
|
+
# <custom> -- Anything else that makes sense for {#object} to key on
|
10
|
+
# @attr formatter [ObjectInspector::BaseFormatter] the formatter object type
|
11
|
+
# to use for formatting the inspect String
|
12
|
+
# @attr kargs [Hash] options to be sent to {#object} via the
|
13
|
+
# {ObjectInspector::ObjectInterrogator} when calling the `inspect_*` methods
|
16
14
|
class Inspector
|
17
15
|
attr_reader :object,
|
18
16
|
:scope,
|
19
17
|
:formatter_klass,
|
20
18
|
:kargs
|
21
19
|
|
22
|
-
# The prefix for all methods called on {#object} for inspect
|
23
|
-
# details/strings.
|
24
|
-
def self.object_inspect_method_prefix
|
25
|
-
"inspect".freeze
|
26
|
-
end
|
27
|
-
|
28
20
|
# Shortcuts the instantiation -> {#to_s} flow that would normally be
|
29
21
|
# required to use ObjectInspector::Inspector.
|
30
22
|
#
|
@@ -40,12 +32,7 @@ module ObjectInspector
|
|
40
32
|
**kargs)
|
41
33
|
@object = object
|
42
34
|
@formatter_klass = formatter
|
43
|
-
@scope =
|
44
|
-
if ObjectInspector.use_string_inquirers?
|
45
|
-
scope.to_s.inquiry
|
46
|
-
else
|
47
|
-
scope.to_sym
|
48
|
-
end
|
35
|
+
@scope = Conversions.Scope(scope)
|
49
36
|
@kargs = kargs
|
50
37
|
end
|
51
38
|
|
@@ -56,7 +43,7 @@ module ObjectInspector
|
|
56
43
|
formatter.call
|
57
44
|
end
|
58
45
|
|
59
|
-
# Generate the inspect String for
|
46
|
+
# Generate the inspect String for the wrapped object, if present.
|
60
47
|
#
|
61
48
|
# @return [String] if {#object_is_a_wrapper}
|
62
49
|
# @return [NilClass] if not {#object_is_a_wrapper}
|
@@ -110,7 +97,7 @@ module ObjectInspector
|
|
110
97
|
end
|
111
98
|
|
112
99
|
# @return [String] if `key` is found in {#kargs} or if {#object} responds to
|
113
|
-
# `#{
|
100
|
+
# `#{object_inspet_method_name}` (e.g. `inspect_flags`)
|
114
101
|
# @return [NilClass] if not found in {#kargs} or {#object}
|
115
102
|
def value(key:)
|
116
103
|
return_value =
|
@@ -141,11 +128,13 @@ module ObjectInspector
|
|
141
128
|
# Attempt to call `inspect_*` on {#object} based on the passed in `name`.
|
142
129
|
#
|
143
130
|
# @return [String] if {#object} responds to
|
144
|
-
# `#{
|
131
|
+
# `#{object_inspet_method_name}` (e.g. `inspect_flags`)
|
145
132
|
# @return [NilClass] if not found on {#object}
|
146
|
-
def interrogate_object_inspect_method(
|
133
|
+
def interrogate_object_inspect_method(
|
134
|
+
name,
|
135
|
+
prefix: ObjectInspector.configuration.inspect_method_prefix)
|
147
136
|
interrogate_object(
|
148
|
-
method_name:
|
137
|
+
method_name: object_inspet_method_name(name, prefix: prefix),
|
149
138
|
kargs: object_method_keyword_arguments)
|
150
139
|
end
|
151
140
|
|
@@ -159,12 +148,10 @@ module ObjectInspector
|
|
159
148
|
interrogator.call
|
160
149
|
end
|
161
150
|
|
162
|
-
def
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
def object_inspect_method_prefix
|
167
|
-
self.class.object_inspect_method_prefix
|
151
|
+
def object_inspet_method_name(
|
152
|
+
name,
|
153
|
+
prefix: ObjectInspector.configuration.inspect_method_prefix)
|
154
|
+
"#{prefix}_#{name}"
|
168
155
|
end
|
169
156
|
|
170
157
|
def object_method_keyword_arguments
|
@@ -22,13 +22,21 @@ module ObjectInspector
|
|
22
22
|
def call
|
23
23
|
return unless object_responds_to_method_name?
|
24
24
|
|
25
|
+
if object.method(method_name).arity != 0
|
26
|
+
call_with_kargs
|
27
|
+
else
|
28
|
+
object.send(method_name)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def call_with_kargs
|
25
35
|
object.send(method_name, **kargs)
|
26
36
|
rescue ArgumentError
|
27
37
|
object.send(method_name)
|
28
38
|
end
|
29
39
|
|
30
|
-
private
|
31
|
-
|
32
40
|
def object_responds_to_method_name?(include_private: true)
|
33
41
|
object.respond_to?(method_name, include_private)
|
34
42
|
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module ObjectInspector
|
2
|
+
# ObjectInspector::Scope defines a predicate method that matches {#name} and
|
3
|
+
# responds with `true`. This is a prettier way to test for a given type of
|
4
|
+
# "scope" within objects.
|
5
|
+
#
|
6
|
+
# @see ActiveSupport::StringInquirer
|
7
|
+
# http://api.rubyonrails.org/classes/ActiveSupport/StringInquirer.html
|
8
|
+
#
|
9
|
+
# @attr names [Array<#to_s>]
|
10
|
+
class Scope
|
11
|
+
attr_reader :names
|
12
|
+
|
13
|
+
def initialize(names = %w[self])
|
14
|
+
@names = Array(names).map { |name| String(name) }
|
15
|
+
end
|
16
|
+
|
17
|
+
# Join the passed-in flags with the passed in separator.
|
18
|
+
#
|
19
|
+
# @param items [Array<#to_s>]
|
20
|
+
# @param separator [#to_s] (ObjectInspector.configuration.flags_separator)
|
21
|
+
def join_flags(flags,
|
22
|
+
separator: ObjectInspector.configuration.flags_separator)
|
23
|
+
Array(flags).join(separator)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Join the passed-in items with the passed in separator.
|
27
|
+
#
|
28
|
+
# @param items [Array<#to_s>]
|
29
|
+
# @param separator [#to_s] (ObjectInspector.configuration.info_separator)
|
30
|
+
def join_info(items,
|
31
|
+
separator: ObjectInspector.configuration.info_separator)
|
32
|
+
Array(items).join(separator)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def method_missing(method_name, *args, &block)
|
38
|
+
if method_name[-1] == "?"
|
39
|
+
scope_name = method_name[0..-2]
|
40
|
+
evaluate_match(scope_name, &block)
|
41
|
+
else
|
42
|
+
super
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def evaluate_match(scope_name, &block)
|
47
|
+
is_a_match = match?(scope_name)
|
48
|
+
|
49
|
+
if block
|
50
|
+
evaluate_block_if(is_a_match, &block)
|
51
|
+
else
|
52
|
+
is_a_match
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def evaluate_block_if(condition, &block)
|
57
|
+
if condition
|
58
|
+
block.call
|
59
|
+
else
|
60
|
+
ObjectInspector.configuration.out_of_scope_placeholder
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def match?(scope_name)
|
65
|
+
any_names_match?(scope_name) ||
|
66
|
+
wild_card_scope?
|
67
|
+
end
|
68
|
+
|
69
|
+
def wild_card_scope?
|
70
|
+
@is_wild_card_scope ||=
|
71
|
+
any_names_match?(ObjectInspector.configuration.wild_card_scope)
|
72
|
+
end
|
73
|
+
|
74
|
+
def any_names_match?(other_name)
|
75
|
+
@names.any? { |name| name == other_name }
|
76
|
+
end
|
77
|
+
|
78
|
+
def respond_to_missing?(method_name, include_private = false)
|
79
|
+
method_name[-1] == "?" || super
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/lib/object_inspector.rb
CHANGED
@@ -1,19 +1,63 @@
|
|
1
1
|
# ObjectInspector is the base namespace for all modules/classes related to the
|
2
2
|
# object_inspector gem.
|
3
3
|
module ObjectInspector
|
4
|
-
|
4
|
+
class << self
|
5
|
+
attr_writer :configuration
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.configuration
|
9
|
+
@configuration ||= Configuration.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.configure
|
13
|
+
yield(configuration)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.reset_configuration
|
17
|
+
@configuration = Configuration.new
|
18
|
+
end
|
19
|
+
|
20
|
+
class Configuration
|
21
|
+
attr_reader :wild_card_scope,
|
22
|
+
:out_of_scope_placeholder,
|
23
|
+
:flags_separator,
|
24
|
+
:info_separator,
|
25
|
+
:inspect_method_prefix
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
@wild_card_scope = "all".freeze
|
29
|
+
@out_of_scope_placeholder = "*".freeze
|
30
|
+
@flags_separator = " / ".freeze
|
31
|
+
@info_separator = " | ".freeze
|
32
|
+
@inspect_method_prefix = "inspect".freeze
|
33
|
+
end
|
34
|
+
|
35
|
+
def wild_card_scope=(value)
|
36
|
+
@wild_card_scope = value.to_s.freeze
|
37
|
+
end
|
38
|
+
|
39
|
+
def out_of_scope_placeholder=(value)
|
40
|
+
@out_of_scope_placeholder = value.to_s.freeze
|
41
|
+
end
|
42
|
+
|
43
|
+
def flags_separator=(value)
|
44
|
+
@flags_separator = value.to_s.freeze
|
45
|
+
end
|
46
|
+
|
47
|
+
def info_separator=(value)
|
48
|
+
@info_separator = value.to_s.freeze
|
49
|
+
end
|
5
50
|
|
6
|
-
|
7
|
-
|
8
|
-
@@use_string_inquirers = !!defined?(ActiveSupport::StringInquirer)
|
9
|
-
else
|
10
|
-
@@use_string_inquirers
|
51
|
+
def inspect_method_prefix=(value)
|
52
|
+
@inspect_method_prefix = value.to_s.freeze
|
11
53
|
end
|
12
54
|
end
|
13
55
|
end
|
14
56
|
|
15
57
|
require "object_inspector/version"
|
58
|
+
require "object_inspector/conversions"
|
16
59
|
require "object_inspector/inspector"
|
60
|
+
require "object_inspector/scope"
|
17
61
|
require "object_inspector/inspectors_helper"
|
18
62
|
require "object_inspector/object_interrogator"
|
19
63
|
require "object_inspector/formatters/base_formatter"
|
data/object_inspector.gemspec
CHANGED
@@ -33,11 +33,11 @@ Gem::Specification.new do |spec|
|
|
33
33
|
spec.add_development_dependency "bundler", "~> 1.16"
|
34
34
|
spec.add_development_dependency "rake", "~> 10.0"
|
35
35
|
spec.add_development_dependency "minitest", "~> 5.0"
|
36
|
+
spec.add_development_dependency "minitest-reporters", "~> 1.2"
|
36
37
|
spec.add_development_dependency "simplecov", "~> 0.16"
|
37
38
|
spec.add_development_dependency "byebug", "~> 10.0"
|
38
39
|
spec.add_development_dependency "pry", "~> 0.11"
|
39
40
|
spec.add_development_dependency "pry-byebug", "~> 3.6"
|
40
41
|
spec.add_development_dependency "benchmark-ips", "~> 2.7"
|
41
|
-
spec.add_development_dependency "
|
42
|
-
# spec.add_development_dependency "object_identifier", "~> 0.1" # Add when new version is released
|
42
|
+
spec.add_development_dependency "object_identifier", "~> 0.1"
|
43
43
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: object_inspector
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Paul Dobbins
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-04-
|
11
|
+
date: 2018-04-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '5.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest-reporters
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.2'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.2'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: simplecov
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -123,19 +137,19 @@ dependencies:
|
|
123
137
|
- !ruby/object:Gem::Version
|
124
138
|
version: '2.7'
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
140
|
+
name: object_identifier
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
128
142
|
requirements:
|
129
143
|
- - "~>"
|
130
144
|
- !ruby/object:Gem::Version
|
131
|
-
version: '1
|
145
|
+
version: '0.1'
|
132
146
|
type: :development
|
133
147
|
prerelease: false
|
134
148
|
version_requirements: !ruby/object:Gem::Requirement
|
135
149
|
requirements:
|
136
150
|
- - "~>"
|
137
151
|
- !ruby/object:Gem::Version
|
138
|
-
version: '1
|
152
|
+
version: '0.1'
|
139
153
|
description: ObjectInspector takes Object#inspect to the next level. Specify any combination
|
140
154
|
of identification attributes, flags, info, and/or a name along with an optional
|
141
155
|
self-definable scope option to represent an object in the console, in logging, etc.
|
@@ -156,12 +170,14 @@ files:
|
|
156
170
|
- bin/console
|
157
171
|
- bin/setup
|
158
172
|
- lib/object_inspector.rb
|
173
|
+
- lib/object_inspector/conversions.rb
|
159
174
|
- lib/object_inspector/formatters/base_formatter.rb
|
160
175
|
- lib/object_inspector/formatters/combining_formatter.rb
|
161
176
|
- lib/object_inspector/formatters/templating_formatter.rb
|
162
177
|
- lib/object_inspector/inspector.rb
|
163
178
|
- lib/object_inspector/inspectors_helper.rb
|
164
179
|
- lib/object_inspector/object_interrogator.rb
|
180
|
+
- lib/object_inspector/scope.rb
|
165
181
|
- lib/object_inspector/version.rb
|
166
182
|
- object_inspector.gemspec
|
167
183
|
- scripts/benchmarking/formatters.rb
|