object_inspector 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +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
|
[](https://badge.fury.io/rb/object_inspector)
|
4
|
-
[](https://travis-ci.org/pdobb/object_inspector)
|
5
5
|
[](https://codeclimate.com/github/pdobb/object_inspector/test_coverage)
|
6
6
|
[](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
|