inspectable 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
- checksums.yaml.gz.sig +0 -0
- data/README.adoc +8 -8
- data/inspectable.gemspec +1 -1
- data/lib/inspectable/builder.rb +36 -32
- data/lib/inspectable/sanitizers/classer.rb +36 -0
- data/lib/inspectable/sanitizers/dater.rb +31 -0
- data/lib/inspectable/sanitizers/structer.rb +30 -0
- data/lib/inspectable/transformers/redactor.rb +1 -1
- data/lib/inspectable.rb +12 -0
- data.tar.gz.sig +0 -0
- metadata +5 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d50d892f3952f220f43f2d9fc8bcd6392858b8a9e0ceca693130ca22e0565237
|
4
|
+
data.tar.gz: 310797e4d5718b4a163a4aef1663b0b8a1bd0e6e3600eeef79f5f5a6e2394f6f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7970ff2fdcdd799dc27b5ddaa2d60c4b5448446dc12895d755aa36541e412100ba4213bb931d959ddf913291b31c9c0da2e039220502fc547763dbd96ea8c010
|
7
|
+
data.tar.gz: 7f22626efddf742879582386d0732026865377ee2ecf3ef91b2703f52afe8bb88cd1d8c54ba1640c5a2295cc668909157022918dc5ef856583c858d13511d151
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/README.adoc
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
|
8
8
|
= Inspectable
|
9
9
|
|
10
|
-
|
10
|
+
Inspectable is a customizable object inspector which enhances {object_inspection_link} behavior beyond what is provided by default. You can always implement your own `#inspect` method but this becomes tedious when you need to exclude or transform the same instance variables across multiple objects.
|
11
11
|
|
12
12
|
toc::[]
|
13
13
|
|
@@ -56,7 +56,7 @@ require "inspectable"
|
|
56
56
|
|
57
57
|
== Usage
|
58
58
|
|
59
|
-
By default, `Object#inspect`
|
59
|
+
By default, `Object#inspect` includes all instance variables so this gem is designed to exclude what you don't need or transform variables before being inspected. Otherwise, you don't need this gem at all. Take the following, for example:
|
60
60
|
|
61
61
|
[source,ruby]
|
62
62
|
----
|
@@ -136,7 +136,7 @@ Inspectable.transformers
|
|
136
136
|
# }
|
137
137
|
----
|
138
138
|
|
139
|
-
|
139
|
+
Each is explained below.
|
140
140
|
|
141
141
|
==== Classifier
|
142
142
|
|
@@ -153,7 +153,7 @@ include Inspectable[demo: :class]
|
|
153
153
|
|
154
154
|
==== Redactor
|
155
155
|
|
156
|
-
This transformer's sole purpose is to hide sensitive information
|
156
|
+
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.
|
157
157
|
|
158
158
|
To use, supply the instance variable you want to transform as the key and the transformer's key (symbol) as the value. Example:
|
159
159
|
|
@@ -178,18 +178,18 @@ The above will override default behavior with your own functionality.
|
|
178
178
|
You can add as many transformers as you like by using the `.add_transformer` method. Several examples have been presented already but here are the guidelines for customization:
|
179
179
|
|
180
180
|
* 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
|
-
* 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.
|
181
|
+
* 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.
|
182
182
|
|
183
|
-
Let's say you
|
183
|
+
Let's say you need to remove hex values from showing up when inspecting a variable value, you could register a custom transformer for this:
|
184
184
|
|
185
185
|
[source,ruby]
|
186
186
|
----
|
187
|
-
Inspectable.add_transformer :dehexer, -> value { value.sub(/\h+/, "") if value }
|
187
|
+
Inspectable.add_transformer :dehexer, -> value { value.sub(/\h+/, "").inspect if value }
|
188
188
|
----
|
189
189
|
|
190
190
|
The above would strip hexes from the output. Notice the guard to check if the `value` exists before performing the transformation. This is good to have when your value might be `nil` so you don't have exceptions.
|
191
191
|
|
192
|
-
ℹ️
|
192
|
+
ℹ️ 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
193
|
|
194
194
|
== Development
|
195
195
|
|
data/inspectable.gemspec
CHANGED
data/lib/inspectable/builder.rb
CHANGED
@@ -3,59 +3,63 @@
|
|
3
3
|
module Inspectable
|
4
4
|
# Provides custom object inspection behavior.
|
5
5
|
class Builder < Module
|
6
|
-
def initialize *excludes,
|
6
|
+
def initialize *excludes, container: CONTAINER, **transformers
|
7
7
|
super()
|
8
|
-
@excludes = excludes
|
9
|
-
@
|
8
|
+
@excludes = excludes
|
9
|
+
@container = container
|
10
|
+
@transformers = resolve transformers
|
10
11
|
|
11
12
|
validate
|
12
13
|
define_inspect
|
13
14
|
freeze
|
14
15
|
end
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
17
|
+
def included descendant
|
18
|
+
case descendant
|
19
|
+
when Class, Struct, Data then super
|
20
|
+
else fail TypeError, "Use Class, Struct, or Data."
|
21
|
+
end
|
22
|
+
end
|
19
23
|
|
20
|
-
|
21
|
-
return unless excludes.empty? && transformers.empty?
|
24
|
+
private
|
22
25
|
|
23
|
-
|
24
|
-
end
|
26
|
+
attr_reader :excludes, :container, :transformers
|
25
27
|
|
26
|
-
def
|
27
|
-
|
28
|
-
|
29
|
-
class: self.class,
|
30
|
-
id: object_id << 1
|
28
|
+
def resolve transformers
|
29
|
+
transformers.each.with_object({}) do |(variable, object), collection|
|
30
|
+
collection[variable] = acquire object
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
def
|
35
|
-
|
36
|
-
|
34
|
+
def acquire object
|
35
|
+
case object
|
36
|
+
when Proc then object
|
37
|
+
when Symbol then container.fetch(:registry).transformers[object]
|
38
|
+
else fail TypeError, "Invalid transformer: #{object.inspect}. Use Proc or Symbol."
|
37
39
|
end
|
38
40
|
end
|
39
41
|
|
40
|
-
def
|
41
|
-
|
42
|
-
value = instance.instance_variable_get variable
|
43
|
-
transform = transformers[variable].call(value) if transformers.key? variable
|
42
|
+
def validate
|
43
|
+
return unless excludes.empty? && transformers.empty?
|
44
44
|
|
45
|
-
|
46
|
-
end
|
45
|
+
fail ArgumentError, "Excludes or transformers are required."
|
47
46
|
end
|
48
47
|
|
49
|
-
def
|
50
|
-
|
51
|
-
|
52
|
-
when Proc then object
|
53
|
-
when Symbol then registry.transformers[object]
|
54
|
-
else fail TypeError, "Invalid transformer: #{object.inspect}. Use Proc or Symbol."
|
55
|
-
end
|
48
|
+
def define_inspect renderer: method(:render)
|
49
|
+
define_method :inspect do
|
50
|
+
klass = self.class
|
56
51
|
|
57
|
-
|
52
|
+
if klass < Struct then renderer.call self, :struct
|
53
|
+
elsif klass < Data then renderer.call self, :data
|
54
|
+
elsif klass.is_a? Class then renderer.call self, :class
|
55
|
+
else renderer.call self, :unknown
|
56
|
+
end
|
58
57
|
end
|
59
58
|
end
|
59
|
+
|
60
|
+
def render instance, type
|
61
|
+
container.fetch(type) { fail TypeError, "Unknown type. Use Class, Struct, or Data." }
|
62
|
+
.then { |serializer| serializer.call(instance, *excludes, **transformers) }
|
63
|
+
end
|
60
64
|
end
|
61
65
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Inspectable
|
4
|
+
module Sanitizers
|
5
|
+
# Excludes and transforms class instance variables.
|
6
|
+
class Classer
|
7
|
+
def initialize pattern: "#<%<class>s:%<id>#018x %<body>s>", inspector: INSPECTOR
|
8
|
+
@pattern = pattern
|
9
|
+
@inspector = inspector
|
10
|
+
freeze
|
11
|
+
end
|
12
|
+
|
13
|
+
def call instance, *excludes, **transformers
|
14
|
+
variables = instance.instance_variables - excludes.map { :"@#{it}" }
|
15
|
+
|
16
|
+
format pattern,
|
17
|
+
class: instance.class,
|
18
|
+
id: object_id << 1,
|
19
|
+
body: exclude_and_transform(instance, variables, transformers).chomp(", ")
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
attr_reader :pattern, :inspector
|
25
|
+
|
26
|
+
def exclude_and_transform instance, variables, transformers
|
27
|
+
variables.reduce(+"") do |body, variable|
|
28
|
+
key = variable.to_s.delete_prefix("@").to_sym
|
29
|
+
value = instance.instance_variable_get variable
|
30
|
+
|
31
|
+
body << "#{variable}=#{transformers.fetch(key, inspector).call value}, "
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Inspectable
|
4
|
+
module Sanitizers
|
5
|
+
# Excludes and transforms data members.
|
6
|
+
class Dater
|
7
|
+
def initialize pattern: "#<data%<class>s %<body>s>", inspector: INSPECTOR
|
8
|
+
@pattern = pattern
|
9
|
+
@inspector = inspector
|
10
|
+
freeze
|
11
|
+
end
|
12
|
+
|
13
|
+
def call instance, *excludes, **transformers
|
14
|
+
format pattern,
|
15
|
+
class: instance.class.name.then { " #{it}" if it },
|
16
|
+
body: exclude_and_transform(instance, excludes, transformers).chomp(", ")
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
attr_reader :pattern, :inspector
|
22
|
+
|
23
|
+
def exclude_and_transform instance, excludes, transformers
|
24
|
+
(instance.members - excludes).reduce(+"") do |body, member|
|
25
|
+
value = instance.public_send member
|
26
|
+
body << "#{member}=#{transformers.fetch(member, inspector).call value}, "
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Inspectable
|
4
|
+
module Sanitizers
|
5
|
+
# Excludes and transforms struct members.
|
6
|
+
class Structer
|
7
|
+
def initialize pattern: "#<struct%<class>s %<body>s>", inspector: Inspectable::INSPECTOR
|
8
|
+
@pattern = pattern
|
9
|
+
@inspector = inspector
|
10
|
+
freeze
|
11
|
+
end
|
12
|
+
|
13
|
+
def call instance, *excludes, **transformers
|
14
|
+
format pattern,
|
15
|
+
class: instance.class.name.then { " #{it}" if it },
|
16
|
+
body: exclude_and_transform(instance, excludes, transformers).chomp(", ")
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
attr_reader :pattern, :inspector
|
22
|
+
|
23
|
+
def exclude_and_transform instance, excludes, transformers
|
24
|
+
(instance.members - excludes).reduce(+"") do |body, member|
|
25
|
+
body << "#{member}=#{transformers.fetch(member, inspector).call instance[member]}, "
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/inspectable.rb
CHANGED
@@ -2,6 +2,9 @@
|
|
2
2
|
|
3
3
|
require "inspectable/builder"
|
4
4
|
require "inspectable/registry"
|
5
|
+
require "inspectable/sanitizers/classer"
|
6
|
+
require "inspectable/sanitizers/dater"
|
7
|
+
require "inspectable/sanitizers/structer"
|
5
8
|
require "inspectable/transformers/classifier"
|
6
9
|
require "inspectable/transformers/redactor"
|
7
10
|
|
@@ -9,5 +12,14 @@ require "inspectable/transformers/redactor"
|
|
9
12
|
module Inspectable
|
10
13
|
extend Registry
|
11
14
|
|
15
|
+
INSPECTOR = -> value { value.inspect }
|
16
|
+
|
17
|
+
CONTAINER = {
|
18
|
+
registry: self,
|
19
|
+
class: Sanitizers::Classer.new,
|
20
|
+
data: Sanitizers::Dater.new,
|
21
|
+
struct: Sanitizers::Structer.new
|
22
|
+
}.freeze
|
23
|
+
|
12
24
|
def self.[](*, **) = Builder.new(*, **)
|
13
25
|
end
|
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: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brooke Kuhlmann
|
@@ -49,6 +49,9 @@ files:
|
|
49
49
|
- lib/inspectable.rb
|
50
50
|
- lib/inspectable/builder.rb
|
51
51
|
- lib/inspectable/registry.rb
|
52
|
+
- lib/inspectable/sanitizers/classer.rb
|
53
|
+
- lib/inspectable/sanitizers/dater.rb
|
54
|
+
- lib/inspectable/sanitizers/structer.rb
|
52
55
|
- lib/inspectable/transformers/classifier.rb
|
53
56
|
- lib/inspectable/transformers/redactor.rb
|
54
57
|
homepage: https://alchemists.io/projects/inspectable
|
@@ -76,7 +79,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
76
79
|
- !ruby/object:Gem::Version
|
77
80
|
version: '0'
|
78
81
|
requirements: []
|
79
|
-
rubygems_version: 3.6.
|
82
|
+
rubygems_version: 3.6.9
|
80
83
|
specification_version: 4
|
81
84
|
summary: A customizable object inspector.
|
82
85
|
test_files: []
|
metadata.gz.sig
CHANGED
Binary file
|