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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9f839f2848c735ffa79fdb9a4cd6200f2965715a02ada73150d21c928af88b69
4
- data.tar.gz: 39f6d038705e0fa23d8c7bf5f919b30a739c908aa87258491249ce9d629fe7ab
3
+ metadata.gz: d50d892f3952f220f43f2d9fc8bcd6392858b8a9e0ceca693130ca22e0565237
4
+ data.tar.gz: 310797e4d5718b4a163a4aef1663b0b8a1bd0e6e3600eeef79f5f5a6e2394f6f
5
5
  SHA512:
6
- metadata.gz: 9d70a034f1cb6c1b81ff71d4d97878fb11e8a46a1491dab16636355af12344c17776c5d638c62f2c33ada6f135fd468759e0a3135330645b29dc0841c36fd36a
7
- data.tar.gz: 2f02e2922f22ac16a1db43952c7c6b049999cbbc7b1bc6e6c5821f61d643e2f210fa0b24379150d27a80ceefd974e7872dd18af29538461712f21446db984eaa
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
- 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.
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` is designed to include all instance variables so this gem is designed to exclude what you don't need. Otherwise, you don't need this gem at all. Take the following, for example:
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
- Continue reading to learn how each of these work and how you can provide your own transformers.
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. This 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.
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 don't like hex digests showing up when inspecting object, you could register a custom transformer for this:
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
- ℹ️ Please note that the value of all transformers will always be sent the `#inspect` message as found with default {object_inspection_link} behavior. This means you don't have to worry about doing this yourself when building custom transformers.
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
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "inspectable"
5
- spec.version = "0.2.0"
5
+ spec.version = "0.3.0"
6
6
  spec.authors = ["Brooke Kuhlmann"]
7
7
  spec.email = ["brooke@alchemists.io"]
8
8
  spec.homepage = "https://alchemists.io/projects/inspectable"
@@ -3,59 +3,63 @@
3
3
  module Inspectable
4
4
  # Provides custom object inspection behavior.
5
5
  class Builder < Module
6
- def initialize *excludes, registry: Inspectable, **transformers
6
+ def initialize *excludes, container: CONTAINER, **transformers
7
7
  super()
8
- @excludes = excludes.map { :"@#{it}" }
9
- @transformers = resolve transformers, registry
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
- private
17
-
18
- attr_reader :excludes, :transformers
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
- def validate
21
- return unless excludes.empty? && transformers.empty?
24
+ private
22
25
 
23
- fail ArgumentError, "Excludes or transformers are required."
24
- end
26
+ attr_reader :excludes, :container, :transformers
25
27
 
26
- def define_inspect body_builder: method(:build_body)
27
- define_method :inspect do
28
- format %(#<%<class>s:%<id>#018x #{body_builder.call(self).chomp ", "}>),
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 build_body instance
35
- exclude_and_transform(instance).reduce(+"") do |body, (variable, value)|
36
- body << "#{variable}=#{value}, "
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 exclude_and_transform instance
41
- (instance.instance_variables - excludes).each.with_object({}) do |variable, attributes|
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
- attributes[variable] = (transform || value).inspect
46
- end
45
+ fail ArgumentError, "Excludes or transformers are required."
47
46
  end
48
47
 
49
- def resolve transformers, registry
50
- transformers.each.with_object({}) do |(key, object), collection|
51
- value = case object
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
- collection[:"@#{key}"] = value
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
@@ -3,6 +3,6 @@
3
3
  module Inspectable
4
4
  module Transformers
5
5
  # Redacts sensitive information.
6
- Redactor = -> value { "[REDACTED]" if value }
6
+ Redactor = -> value { "[REDACTED]".inspect if value }
7
7
  end
8
8
  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.2.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.8
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