inspectable 0.6.0 → 1.0.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
- checksums.yaml.gz.sig +0 -0
- data/README.adoc +108 -16
- data/inspectable.gemspec +2 -2
- data/lib/inspectable/builder.rb +7 -1
- data/lib/inspectable/registry.rb +2 -2
- data/lib/inspectable/rspec/matchers/match_inspection.rb +28 -0
- data/lib/inspectable/sanitizers/{dater.rb → data.rb} +6 -2
- data/lib/inspectable/sanitizers/{structer.rb → struct.rb} +6 -2
- data/lib/inspectable/sanitizers/{classer.rb → type.rb} +6 -4
- data/lib/inspectable/transformers/redactor.rb +5 -1
- data/lib/inspectable/transformers/typer.rb +12 -0
- data/lib/inspectable.rb +7 -7
- data.tar.gz.sig +0 -0
- metadata +8 -7
- metadata.gz.sig +0 -0
- data/lib/inspectable/transformers/classifier.rb +0 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f4a4c3c388c5294c596d5fa7a6a4bf4959ce29cbfae40563fcd4d3e3464d800e
|
|
4
|
+
data.tar.gz: 15475b71448155390f1ca1f374daea21d9efaed0ea8b27b763eea97fdcd35cf3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 69c70eb5c696419513d64b18008a1880318e0b1fb31f42d27282a380d8ba6ae9119f5f3a8adc2ebcf4ee5c8256638d3bc1297bc313362054be7e2fc0bd9b0f6a
|
|
7
|
+
data.tar.gz: d6ebb06b52f577f2e2acc85c054d8b918aa5cd0dfdccf8f47ce051afcead6fbea2f7d0159462b1f439fad7d06628ffd3839d8ef0482843f462821bc454bdcd89
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/README.adoc
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
:dry_schema_link: link:https://dry-rb.org/gems/dry-schema[Dry Schema]
|
|
6
6
|
:object_inspection_link: link:https://alchemists.io/articles/ruby_object_inspection[Ruby Object Inspection]
|
|
7
|
+
:rspec_link: link:https://rspec.info[RSpec]
|
|
7
8
|
|
|
8
9
|
= Inspectable
|
|
9
10
|
|
|
@@ -13,9 +14,9 @@ toc::[]
|
|
|
13
14
|
|
|
14
15
|
== Features
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
* Allows you to customize and configure `Object#inspect` with minimal effort.
|
|
18
|
+
* Allows you to exclude instance variables that are too verbose or undesired.
|
|
19
|
+
* Allows you to register reusable transformers for more advanced behavior.
|
|
19
20
|
|
|
20
21
|
== Requirements
|
|
21
22
|
|
|
@@ -125,46 +126,47 @@ Demo.new.inspect
|
|
|
125
126
|
|
|
126
127
|
=== Transformers
|
|
127
128
|
|
|
128
|
-
This gem includes a few
|
|
129
|
+
This gem includes a few built-in transformers that can help you hide sensitive information or reduce verbosity. To view them, use:
|
|
129
130
|
|
|
130
131
|
[source,ruby]
|
|
131
132
|
----
|
|
132
133
|
Inspectable.transformers
|
|
134
|
+
|
|
133
135
|
# {
|
|
134
|
-
#
|
|
135
|
-
#
|
|
136
|
+
# redact: Inspectable::Transformers::Redactor,
|
|
137
|
+
# type: Inspectable::Transformers::Typer
|
|
136
138
|
# }
|
|
137
139
|
----
|
|
138
140
|
|
|
139
141
|
Each is explained below.
|
|
140
142
|
|
|
141
|
-
====
|
|
142
|
-
|
|
143
|
-
This is a simple transformer that always asks for the class of the instance variable's value.
|
|
143
|
+
==== Redactor
|
|
144
144
|
|
|
145
|
-
This transformer is most helpful for
|
|
145
|
+
This transformer's sole purpose is to hide sensitive information and is most helpful for obscuring credentials, passwords, and secrets in general. When your instance variable's value is not `nil`, you'll see `"[REDACTED]"` as the value. Otherwise, if your instance variable's value is `nil`, you'll see `nil` instead.
|
|
146
146
|
|
|
147
147
|
To use, supply the instance variable you want to transform as the key and the transformer's key (symbol) as the value. Example:
|
|
148
148
|
|
|
149
149
|
[source,ruby]
|
|
150
150
|
----
|
|
151
|
-
include Inspectable[demo: :
|
|
151
|
+
include Inspectable[demo: :redact]
|
|
152
152
|
----
|
|
153
153
|
|
|
154
|
-
====
|
|
154
|
+
==== Typer
|
|
155
155
|
|
|
156
|
-
This transformer
|
|
156
|
+
This transformer always computes the instance variable's type.
|
|
157
|
+
|
|
158
|
+
This transformer is most helpful for objects, like {dry_schema_link}, that are extremely verbose. With this transformer, you can see the type of schema without all of the additional details. This transformer is also handy when you only want type information in general.
|
|
157
159
|
|
|
158
160
|
To use, supply the instance variable you want to transform as the key and the transformer's key (symbol) as the value. Example:
|
|
159
161
|
|
|
160
162
|
[source,ruby]
|
|
161
163
|
----
|
|
162
|
-
include Inspectable[demo: :
|
|
164
|
+
include Inspectable[demo: :type]
|
|
163
165
|
----
|
|
164
166
|
|
|
165
167
|
==== Overrides
|
|
166
168
|
|
|
167
|
-
Should you not like default transformer behavior, you can override an existing transformer with your own. For example, maybe you'd like the `Redactor`
|
|
169
|
+
Should you not like default transformer behavior, you can override an existing transformer with your own. For example, maybe you'd like the `Redactor` transformer to use `"[FILTERED]"` instead of `"[REDACTED]"`. Here's how you do that:
|
|
168
170
|
|
|
169
171
|
[source,ruby]
|
|
170
172
|
----
|
|
@@ -175,7 +177,7 @@ The above will override default behavior with your own functionality.
|
|
|
175
177
|
|
|
176
178
|
==== Custom
|
|
177
179
|
|
|
178
|
-
You can add as many transformers as you like by using the `.add_transformer` method.
|
|
180
|
+
You can add as many transformers as you like by using the `.add_transformer` method. Here are the guidelines for customization:
|
|
179
181
|
|
|
180
182
|
* Use only a string or symbol for the first argument (a symbol is preferred). This allows you to quickly identify and use your transformer when applying custom inspection behavior to your objects.
|
|
181
183
|
* Use a lambda for the second argument. The lambda must accept a value as the first positional parameter. How you transform the value is up to you but you'll want to adhere to default {object_inspection_link} behavior.
|
|
@@ -191,6 +193,96 @@ The above would strip hexes from the output. Notice the guard to check if the `v
|
|
|
191
193
|
|
|
192
194
|
ℹ️ In most cases, you _must_ send the `#inspect` message to the transformed value. In situations, where you are dealing with a constant, you'll want to avoid sending the `#inspect` message because constants shouldn't be quoted. All of this is important when adhering to default {object_inspection_link} behavior.
|
|
193
195
|
|
|
196
|
+
=== Native
|
|
197
|
+
|
|
198
|
+
As of Ruby 4.0.0, limited native support is provided via the _private_ `instance_variables_to_inspect` instance method. This method is not compatible with this gem because this gem makes `instance_variables_to_inspect` redundant and will fail with a `NoMethodError` exception. Example:
|
|
199
|
+
|
|
200
|
+
[source,ruby]
|
|
201
|
+
----
|
|
202
|
+
Class.new do
|
|
203
|
+
include Inspectable(:name)
|
|
204
|
+
|
|
205
|
+
def initialize name = "test"
|
|
206
|
+
@name = name
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
private
|
|
210
|
+
|
|
211
|
+
def instance_variables_to_inspect = [:@name]
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# undefined method 'Inspectable' for class (NoMethodError)
|
|
215
|
+
----
|
|
216
|
+
|
|
217
|
+
To resolve the above exception, remove `instance_variables_to_inspect` and let this gem handle everything for you.
|
|
218
|
+
|
|
219
|
+
=== RSpec
|
|
220
|
+
|
|
221
|
+
To aid in your testing, you can use the `match_inspection` RSpec matcher by requiring it in your spec helper:
|
|
222
|
+
|
|
223
|
+
[source,ruby]
|
|
224
|
+
----
|
|
225
|
+
# spec_helper.rb
|
|
226
|
+
|
|
227
|
+
require "inspectable/rspec/matchers/match_inspection"
|
|
228
|
+
----
|
|
229
|
+
|
|
230
|
+
Once required, you can use the matcher by supplying the expected attributes as follows:
|
|
231
|
+
|
|
232
|
+
[source,ruby]
|
|
233
|
+
----
|
|
234
|
+
RSpec.describe Demo do
|
|
235
|
+
subject(:demo) { described_class.new }
|
|
236
|
+
|
|
237
|
+
describe "#inspect" do
|
|
238
|
+
it "has inspected attributes" do
|
|
239
|
+
expect(demo.inspect).to match_inspection(label: "Demo", name: :demo)
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
----
|
|
244
|
+
|
|
245
|
+
You can also customize the matcher by providing a `by` hash _before_ any expected attributes consisting of the following attributes:
|
|
246
|
+
|
|
247
|
+
* `prefix`: The prefix of your attribute names. Default: `"@"`.
|
|
248
|
+
* `delimiter`: The delimiter between each attribute name and value. Default: `"="`.
|
|
249
|
+
* `separator`: The separator between each attribute. Default: `", "`.
|
|
250
|
+
|
|
251
|
+
For example, the following is an explicit demonstration of what the matcher implicitly provides for you by default:
|
|
252
|
+
|
|
253
|
+
[source,ruby]
|
|
254
|
+
----
|
|
255
|
+
RSpec.describe Demo do
|
|
256
|
+
subject(:demo) { described_class.new }
|
|
257
|
+
|
|
258
|
+
describe "#inspect" do
|
|
259
|
+
it "has inspected attributes" do
|
|
260
|
+
expect(demo.inspect).to match_inspection(
|
|
261
|
+
by: {prefix: "@", delimiter: "=", separator: ", "},
|
|
262
|
+
label: "Demo",
|
|
263
|
+
name: :demo
|
|
264
|
+
)
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
----
|
|
269
|
+
|
|
270
|
+
In situations where the spec fails, you’ll get a formatted error to help you quickly resolve and fix the issue:
|
|
271
|
+
|
|
272
|
+
----
|
|
273
|
+
expected (using prefix: "@", delimiter: "=", and separator: ", "):
|
|
274
|
+
|
|
275
|
+
"#<Demo:0x00000000000014d0
|
|
276
|
+
@label="Demo",
|
|
277
|
+
@name=:demo
|
|
278
|
+
@email="demo@demo.io"
|
|
279
|
+
|
|
280
|
+
to match:
|
|
281
|
+
|
|
282
|
+
@label="Demo",
|
|
283
|
+
@name=:demo
|
|
284
|
+
----
|
|
285
|
+
|
|
194
286
|
== Development
|
|
195
287
|
|
|
196
288
|
To contribute, run:
|
data/inspectable.gemspec
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Gem::Specification.new do |spec|
|
|
4
4
|
spec.name = "inspectable"
|
|
5
|
-
spec.version = "0.
|
|
5
|
+
spec.version = "1.0.0"
|
|
6
6
|
spec.authors = ["Brooke Kuhlmann"]
|
|
7
7
|
spec.email = ["brooke@alchemists.io"]
|
|
8
8
|
spec.homepage = "https://alchemists.io/projects/inspectable"
|
|
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
|
|
|
22
22
|
spec.signing_key = Gem.default_key_path
|
|
23
23
|
spec.cert_chain = [Gem.default_cert_path]
|
|
24
24
|
|
|
25
|
-
spec.required_ruby_version = ">=
|
|
25
|
+
spec.required_ruby_version = ">= 4.0"
|
|
26
26
|
|
|
27
27
|
spec.extra_rdoc_files = Dir["README*", "LICENSE*"]
|
|
28
28
|
spec.files = Dir["*.gemspec", "lib/**/*"]
|
data/lib/inspectable/builder.rb
CHANGED
|
@@ -15,6 +15,12 @@ module Inspectable
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def included descendant
|
|
18
|
+
descendant.define_singleton_method :method_added do |name|
|
|
19
|
+
return super(name) unless name == :instance_variables_to_inspect
|
|
20
|
+
|
|
21
|
+
fail NoMethodError, "Defining method :instance_variables_to_inspect is disabled."
|
|
22
|
+
end
|
|
23
|
+
|
|
18
24
|
case descendant
|
|
19
25
|
when Class, Struct, Data then super
|
|
20
26
|
else fail TypeError, "Use Class, Struct, or Data."
|
|
@@ -59,7 +65,7 @@ module Inspectable
|
|
|
59
65
|
|
|
60
66
|
def render instance, type
|
|
61
67
|
container.fetch(type) { fail TypeError, "Unknown type. Use Class, Struct, or Data." }
|
|
62
|
-
.then { |
|
|
68
|
+
.then { |sanitizer| sanitizer.call(instance, *excludes, **transformers) }
|
|
63
69
|
end
|
|
64
70
|
end
|
|
65
71
|
end
|
data/lib/inspectable/registry.rb
CHANGED
|
@@ -4,8 +4,8 @@ module Inspectable
|
|
|
4
4
|
# Provides global regsitry for further customization.
|
|
5
5
|
module Registry
|
|
6
6
|
def self.extended descendant
|
|
7
|
-
descendant.add_transformer(:
|
|
8
|
-
.add_transformer
|
|
7
|
+
descendant.add_transformer(:redact, Inspectable::Transformers::Redactor)
|
|
8
|
+
.add_transformer(:type, Inspectable::Transformers::Typer)
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def add_transformer key, function
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec::Matchers.define :match_inspection do |by: {}, **|
|
|
4
|
+
match do |actual|
|
|
5
|
+
defaults = {prefix: "@", delimiter: "=", separator: ", "}
|
|
6
|
+
@prefix, @delimiter, @separator = defaults.merge!(by).values_at(*defaults.keys)
|
|
7
|
+
@content = expected.map { |key, value| "#{@prefix}#{key}#{@delimiter}#{value}" }
|
|
8
|
+
.join @separator
|
|
9
|
+
|
|
10
|
+
actual.match?(/#{@content}/)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
failure_message do |actual|
|
|
14
|
+
using = "using prefix: #{@prefix.inspect}, " \
|
|
15
|
+
"delimiter: #{@delimiter.inspect}, and " \
|
|
16
|
+
"separator: #{@separator.inspect}"
|
|
17
|
+
|
|
18
|
+
<<~MESSAGE
|
|
19
|
+
expected (#{using}):
|
|
20
|
+
|
|
21
|
+
#{actual.inspect.gsub @separator, "#{@separator}\n"}
|
|
22
|
+
|
|
23
|
+
to match:
|
|
24
|
+
|
|
25
|
+
#{@content.gsub @separator, "#{@separator}\n"}
|
|
26
|
+
MESSAGE
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module Inspectable
|
|
4
4
|
module Sanitizers
|
|
5
5
|
# Excludes and transforms data members.
|
|
6
|
-
class
|
|
6
|
+
class Data
|
|
7
7
|
def initialize pattern: "#<data%<class>s %<body>s>", inspector: INSPECTOR
|
|
8
8
|
@pattern = pattern
|
|
9
9
|
@inspector = inspector
|
|
@@ -23,7 +23,11 @@ module Inspectable
|
|
|
23
23
|
def exclude_and_transform instance, excludes, transformers
|
|
24
24
|
(instance.members - excludes).reduce(+"") do |body, member|
|
|
25
25
|
value = instance.public_send member
|
|
26
|
-
|
|
26
|
+
transformer = transformers.fetch member, inspector
|
|
27
|
+
|
|
28
|
+
fail ArgumentError, "Invalid transformer registered for: #{member}." unless transformer
|
|
29
|
+
|
|
30
|
+
body << "#{member}=#{transformer.call value}, "
|
|
27
31
|
end
|
|
28
32
|
end
|
|
29
33
|
end
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module Inspectable
|
|
4
4
|
module Sanitizers
|
|
5
5
|
# Excludes and transforms struct members.
|
|
6
|
-
class
|
|
6
|
+
class Struct
|
|
7
7
|
def initialize pattern: "#<struct%<class>s %<body>s>", inspector: Inspectable::INSPECTOR
|
|
8
8
|
@pattern = pattern
|
|
9
9
|
@inspector = inspector
|
|
@@ -22,7 +22,11 @@ module Inspectable
|
|
|
22
22
|
|
|
23
23
|
def exclude_and_transform instance, excludes, transformers
|
|
24
24
|
(instance.members - excludes).reduce(+"") do |body, member|
|
|
25
|
-
|
|
25
|
+
transformer = transformers.fetch member, inspector
|
|
26
|
+
|
|
27
|
+
fail ArgumentError, "Invalid transformer registered for: #{member}." unless transformer
|
|
28
|
+
|
|
29
|
+
body << "#{member}=#{transformer.call instance[member]}, "
|
|
26
30
|
end
|
|
27
31
|
end
|
|
28
32
|
end
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
module Inspectable
|
|
4
4
|
module Sanitizers
|
|
5
|
-
# Excludes and transforms
|
|
6
|
-
class
|
|
5
|
+
# Excludes and transforms object types.
|
|
6
|
+
class Type
|
|
7
7
|
def initialize pattern: "#<%<class>s:%<id>#018x %<body>s>", inspector: INSPECTOR
|
|
8
8
|
@pattern = pattern
|
|
9
9
|
@inspector = inspector
|
|
@@ -26,9 +26,11 @@ module Inspectable
|
|
|
26
26
|
def exclude_and_transform instance, variables, transformers
|
|
27
27
|
variables.reduce(+"") do |body, variable|
|
|
28
28
|
key = variable.to_s.delete_prefix("@").to_sym
|
|
29
|
-
|
|
29
|
+
transformer = transformers.fetch key, inspector
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
fail ArgumentError, "Invalid transformer registered for: #{key}." unless transformer
|
|
32
|
+
|
|
33
|
+
body << "#{variable}=#{transformer.call instance.instance_variable_get(variable)}, "
|
|
32
34
|
end
|
|
33
35
|
end
|
|
34
36
|
end
|
data/lib/inspectable.rb
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
require "inspectable/builder"
|
|
4
4
|
require "inspectable/registry"
|
|
5
|
-
require "inspectable/sanitizers/
|
|
6
|
-
require "inspectable/sanitizers/
|
|
7
|
-
require "inspectable/sanitizers/
|
|
8
|
-
require "inspectable/transformers/classifier"
|
|
5
|
+
require "inspectable/sanitizers/data"
|
|
6
|
+
require "inspectable/sanitizers/struct"
|
|
7
|
+
require "inspectable/sanitizers/type"
|
|
9
8
|
require "inspectable/transformers/redactor"
|
|
9
|
+
require "inspectable/transformers/typer"
|
|
10
10
|
|
|
11
11
|
# Main namespace.
|
|
12
12
|
module Inspectable
|
|
@@ -16,9 +16,9 @@ module Inspectable
|
|
|
16
16
|
|
|
17
17
|
CONTAINER = {
|
|
18
18
|
registry: self,
|
|
19
|
-
class: Sanitizers::
|
|
20
|
-
data: Sanitizers::
|
|
21
|
-
struct: Sanitizers::
|
|
19
|
+
class: Sanitizers::Type.new,
|
|
20
|
+
data: Sanitizers::Data.new,
|
|
21
|
+
struct: Sanitizers::Struct.new
|
|
22
22
|
}.freeze
|
|
23
23
|
|
|
24
24
|
def self.[](*, **) = Builder.new(*, **)
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: inspectable
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 1.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Brooke Kuhlmann
|
|
@@ -49,11 +49,12 @@ files:
|
|
|
49
49
|
- lib/inspectable.rb
|
|
50
50
|
- lib/inspectable/builder.rb
|
|
51
51
|
- lib/inspectable/registry.rb
|
|
52
|
-
- lib/inspectable/
|
|
53
|
-
- lib/inspectable/sanitizers/
|
|
54
|
-
- lib/inspectable/sanitizers/
|
|
55
|
-
- lib/inspectable/
|
|
52
|
+
- lib/inspectable/rspec/matchers/match_inspection.rb
|
|
53
|
+
- lib/inspectable/sanitizers/data.rb
|
|
54
|
+
- lib/inspectable/sanitizers/struct.rb
|
|
55
|
+
- lib/inspectable/sanitizers/type.rb
|
|
56
56
|
- lib/inspectable/transformers/redactor.rb
|
|
57
|
+
- lib/inspectable/transformers/typer.rb
|
|
57
58
|
homepage: https://alchemists.io/projects/inspectable
|
|
58
59
|
licenses:
|
|
59
60
|
- Hippocratic-2.1
|
|
@@ -72,14 +73,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
72
73
|
requirements:
|
|
73
74
|
- - ">="
|
|
74
75
|
- !ruby/object:Gem::Version
|
|
75
|
-
version: '
|
|
76
|
+
version: '4.0'
|
|
76
77
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
77
78
|
requirements:
|
|
78
79
|
- - ">="
|
|
79
80
|
- !ruby/object:Gem::Version
|
|
80
81
|
version: '0'
|
|
81
82
|
requirements: []
|
|
82
|
-
rubygems_version:
|
|
83
|
+
rubygems_version: 4.0.3
|
|
83
84
|
specification_version: 4
|
|
84
85
|
summary: A customizable object inspector.
|
|
85
86
|
test_files: []
|
metadata.gz.sig
CHANGED
|
Binary file
|