object_inspector 1.1.0 → 1.2.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/README.md +23 -22
- data/lib/object_inspector/inspect_behaviors.rb +22 -2
- data/lib/object_inspector/version.rb +1 -1
- data/lib/object_inspector.rb +57 -2
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b814c9a90935be0339c6bf2ce1e2e0547b5ccb4b59a26feb40d91082cd9c7b2a
|
|
4
|
+
data.tar.gz: 6f024e9206a497fa173a3e7aff23ae9334b1eacd8cacb4559675ae5db5c3aa1f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 41a2fc9fa580c3ce169bfb5dd8b110d5c9d66635d85cde16c689e42ff91354dbbdd042a7bd45f57381c46e04de6938d91310b79f79a64a56dbd53f6d7f81e37b
|
|
7
|
+
data.tar.gz: 9ab9384c13706f95f8a1ced4fdf2d0e2162dbad989a709f226026ff6d0be89844392eaf182044fb62d314eac9a2f645a3bacf1ba351a95821b555960fb8d38fa
|
data/README.md
CHANGED
|
@@ -71,6 +71,7 @@ ObjectInspector.configure do |config|
|
|
|
71
71
|
config.flags_separator = " / "
|
|
72
72
|
config.issues_separator = " | "
|
|
73
73
|
config.info_separator = " | "
|
|
74
|
+
config.error_handler = ->(exception, object:) {}
|
|
74
75
|
end
|
|
75
76
|
```
|
|
76
77
|
|
|
@@ -522,6 +523,24 @@ See examples:
|
|
|
522
523
|
- [ObjectInspector::TemplatingFormatter]
|
|
523
524
|
- [ObjectInspector::CombiningFormatter]
|
|
524
525
|
|
|
526
|
+
## Handling Errors
|
|
527
|
+
|
|
528
|
+
When `#inspect` raises any `StandardError`, Object Inspector falls back to the original `#inspect` method and records the error in `ObjectInspector.last_error`:
|
|
529
|
+
|
|
530
|
+
```ruby
|
|
531
|
+
user = User.select(:id).first
|
|
532
|
+
user.inspect
|
|
533
|
+
# => #<User id: 1>
|
|
534
|
+
|
|
535
|
+
ObjectInspector.last_error
|
|
536
|
+
# => #<ActiveModel::MissingAttributeError: missing attribute: ...>
|
|
537
|
+
puts ObjectInspector.last_error.full_message
|
|
538
|
+
# ...: undefined local variable or method 'asdf' for an instance of Game (NameError)
|
|
539
|
+
# ...
|
|
540
|
+
|
|
541
|
+
ObjectInspector.clear_error
|
|
542
|
+
```
|
|
543
|
+
|
|
525
544
|
## Help
|
|
526
545
|
|
|
527
546
|
### How can I see the original inspect output on ActiveRecord objects?
|
|
@@ -630,33 +649,15 @@ alias oiset set_object_inspector_scope
|
|
|
630
649
|
> [!IMPORTANT]
|
|
631
650
|
> ObjectInspector defaults to `enabled`. However, this implies an increased chance of causing additional queries/processing based on your usage.
|
|
632
651
|
|
|
633
|
-
If your inspect methods reference other ActiveRecord models, you will be introducing Database queries into basic object inspection. While you can control this through careful use of `complex` scopes
|
|
634
|
-
|
|
635
|
-
To set Object inspector to be `disabled` by default, but `enabled` on the Rails console:
|
|
636
|
-
|
|
637
|
-
1. In an initializer, set [ObjectInspector::Configuration] to default to `disabled`:
|
|
652
|
+
If your inspect methods reference other ActiveRecord models, you will be introducing Database queries into basic object inspection. While you can control this through careful use of `complex` scopes, you may wish to default ObjectInspector to be `disabled` by default e.g. in production:
|
|
638
653
|
|
|
639
654
|
```ruby
|
|
640
655
|
# config/initializers/object_inspector.rb
|
|
641
656
|
ObjectInspector.configure do |config|
|
|
642
|
-
config.enabled =
|
|
643
|
-
end
|
|
644
|
-
```
|
|
645
|
-
|
|
646
|
-
2. Enable ObjectInspector via `.irbrc` (or `.pryrc`, or the like):
|
|
647
|
-
|
|
648
|
-
```ruby
|
|
649
|
-
# .irbrc:
|
|
650
|
-
|
|
651
|
-
# ...
|
|
652
|
-
|
|
653
|
-
ObjectInspector.configuration.enable
|
|
654
|
-
# Note: ^ produces output: ` -> ObjectInspector enabled`
|
|
655
|
-
|
|
656
|
-
# OR (silent version):
|
|
657
|
+
config.enabled = !Rails.env.production?
|
|
657
658
|
|
|
658
|
-
|
|
659
|
-
config.enabled =
|
|
659
|
+
# OR:
|
|
660
|
+
config.enabled = Rails.configuration.x.object_inspector.enabled
|
|
660
661
|
end
|
|
661
662
|
```
|
|
662
663
|
|
|
@@ -4,14 +4,25 @@
|
|
|
4
4
|
# the default `#inspect` method for that object to instead call
|
|
5
5
|
# {ObjectInspector::Inspector.inspect}.
|
|
6
6
|
module ObjectInspector::InspectBehaviors
|
|
7
|
+
# :reek:TooManyStatements
|
|
8
|
+
|
|
7
9
|
# Calls {ObjectInspector::Inspector.inspect} on `self`, passing through any
|
|
8
10
|
# keyword arguments.
|
|
9
11
|
#
|
|
12
|
+
# If building the gem inspect String raises a {StandardError}, records the
|
|
13
|
+
# error via {ObjectInspector.record_error} and falls back to the ancestor
|
|
14
|
+
# `#inspect` via `super` (Object / ActiveRecord / etc.).
|
|
15
|
+
#
|
|
10
16
|
# @return [String]
|
|
11
17
|
def inspect(**)
|
|
12
18
|
return super() if ObjectInspector.configuration.disabled?
|
|
13
19
|
|
|
14
|
-
ObjectInspector::Inspector.inspect(self, **)
|
|
20
|
+
ObjectInspector::Inspector.inspect(self, **).tap {
|
|
21
|
+
ObjectInspector.clear_error
|
|
22
|
+
}
|
|
23
|
+
rescue => ex
|
|
24
|
+
ObjectInspector.record_error(ex, object: self)
|
|
25
|
+
super()
|
|
15
26
|
end
|
|
16
27
|
|
|
17
28
|
# Like {#inspect} but:
|
|
@@ -22,9 +33,18 @@ module ObjectInspector::InspectBehaviors
|
|
|
22
33
|
# {#inspect} since the `:all` scope may result in additional queries or extra
|
|
23
34
|
# processing--depending on how the inspect hooks are setup.
|
|
24
35
|
#
|
|
36
|
+
# On {StandardError}, records the error and falls back to {#inspect} (which
|
|
37
|
+
# then falls back to the original ancestor `#inspect` if needed).
|
|
38
|
+
#
|
|
25
39
|
# @return [String]
|
|
26
40
|
def inspect!(**)
|
|
27
|
-
ObjectInspector::Inspector.inspect(self, **, scope: :all)
|
|
41
|
+
ObjectInspector::Inspector.inspect(self, **, scope: :all).tap {
|
|
42
|
+
ObjectInspector.clear_error
|
|
43
|
+
}
|
|
44
|
+
rescue => ex
|
|
45
|
+
ObjectInspector.record_error(ex, object: self)
|
|
46
|
+
|
|
47
|
+
inspect
|
|
28
48
|
end
|
|
29
49
|
|
|
30
50
|
private
|
data/lib/object_inspector.rb
CHANGED
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
# Defines the base namespace for all modules/classes used by the
|
|
4
4
|
# object_inspector gem.
|
|
5
5
|
module ObjectInspector
|
|
6
|
+
LAST_ERROR_THREAD_KEY = :object_inspector_last_error
|
|
7
|
+
private_constant :LAST_ERROR_THREAD_KEY
|
|
8
|
+
|
|
6
9
|
# Accessor for the {ObjectInspector::Configuration} object.
|
|
7
10
|
def self.configuration
|
|
8
11
|
@configuration ||= Configuration.new
|
|
@@ -21,6 +24,40 @@ module ObjectInspector
|
|
|
21
24
|
@configuration = Configuration.new
|
|
22
25
|
end
|
|
23
26
|
|
|
27
|
+
# Remember the given exception--which will have caused inspect to fall back to
|
|
28
|
+
# the original `#inspect`. Stored per-thread/fiber so concurrent use does not
|
|
29
|
+
# clobber it.
|
|
30
|
+
#
|
|
31
|
+
# Calls {Configuration#error_handler} with `exception, object:` after
|
|
32
|
+
# recording.
|
|
33
|
+
#
|
|
34
|
+
# @param exception [Exception]
|
|
35
|
+
# @param object [Object, nil] The object being inspected, when known.
|
|
36
|
+
#
|
|
37
|
+
# @return [Exception]
|
|
38
|
+
def self.record_error(exception, object: nil)
|
|
39
|
+
Thread.current[LAST_ERROR_THREAD_KEY] = exception
|
|
40
|
+
|
|
41
|
+
configuration.error_handler.(exception, object:)
|
|
42
|
+
|
|
43
|
+
exception
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# The most recent exception passed to {record_error} on this thread/fiber.
|
|
47
|
+
# Cleared by {clear_error} (including after a successful gem inspect).
|
|
48
|
+
#
|
|
49
|
+
# @return [Exception, nil]
|
|
50
|
+
def self.last_error
|
|
51
|
+
Thread.current[LAST_ERROR_THREAD_KEY]
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Clear {#last_error} for the current thread/fiber.
|
|
55
|
+
#
|
|
56
|
+
# @return [nil]
|
|
57
|
+
def self.clear_error
|
|
58
|
+
Thread.current[LAST_ERROR_THREAD_KEY] = nil
|
|
59
|
+
end
|
|
60
|
+
|
|
24
61
|
# :reek:TooManyInstanceVariables, :reek:TooManyMethods
|
|
25
62
|
|
|
26
63
|
# ObjectInspector::Configuration stores the default configuration options for
|
|
@@ -36,7 +73,8 @@ module ObjectInspector
|
|
|
36
73
|
:name_separator,
|
|
37
74
|
:flags_separator,
|
|
38
75
|
:issues_separator,
|
|
39
|
-
:info_separator
|
|
76
|
+
:info_separator,
|
|
77
|
+
:error_handler
|
|
40
78
|
|
|
41
79
|
# :reek:LongParameterList, :reek:BooleanParameter
|
|
42
80
|
def initialize( # rubocop:disable Metrics/MethodLength, Metrics/ParameterLists
|
|
@@ -50,7 +88,8 @@ module ObjectInspector
|
|
|
50
88
|
name_separator: " - ",
|
|
51
89
|
flags_separator: " / ",
|
|
52
90
|
issues_separator: " | ",
|
|
53
|
-
info_separator: " | "
|
|
91
|
+
info_separator: " | ",
|
|
92
|
+
error_handler: ->(exception, object:) {}
|
|
54
93
|
)
|
|
55
94
|
@enabled = enabled
|
|
56
95
|
@formatter_class = formatter_class
|
|
@@ -63,6 +102,7 @@ module ObjectInspector
|
|
|
63
102
|
@flags_separator = flags_separator
|
|
64
103
|
@issues_separator = issues_separator
|
|
65
104
|
@info_separator = info_separator
|
|
105
|
+
self.error_handler = error_handler
|
|
66
106
|
end
|
|
67
107
|
|
|
68
108
|
# @param value [Object] Coerced to a Boolean with `!!value`.
|
|
@@ -136,6 +176,21 @@ module ObjectInspector
|
|
|
136
176
|
def info_separator=(value)
|
|
137
177
|
@info_separator = value.to_s.freeze
|
|
138
178
|
end
|
|
179
|
+
|
|
180
|
+
# :reek:ManualDispatch
|
|
181
|
+
|
|
182
|
+
# A callable, invoked by {ObjectInspector.record_error}.
|
|
183
|
+
#
|
|
184
|
+
# Expected signature: `->(exception, object:) { ... }`.
|
|
185
|
+
#
|
|
186
|
+
# @param value [#call]
|
|
187
|
+
def error_handler=(value)
|
|
188
|
+
unless value.respond_to?(:call)
|
|
189
|
+
raise(TypeError, "error_handler must be callable")
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
@error_handler = value
|
|
193
|
+
end
|
|
139
194
|
end
|
|
140
195
|
end
|
|
141
196
|
|