object_identifier 0.4.1 → 0.5.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: c0a0e09332282b492a3c9e83f9ab59a319a421c9ed3e83c2bfa87f6bfe20e6bd
4
- data.tar.gz: 7b27cf091a8ecfd1c747fb75918f4b88aabd725dba3221489021aa2f5d24138a
3
+ metadata.gz: 4553678db77484aa04ce8bf00e3238310bb253632fb8867cae4e948a35bfda6c
4
+ data.tar.gz: afae645239815d3a9a011b56892127eccbf0dbc9558fc59ed6d7c15349fdbbe7
5
5
  SHA512:
6
- metadata.gz: 6b1150c07800795094a4f15e475ba180187c51e248f0a5cfb385030b9720c4b2e3000692974f89eecc211b223778159b3041b358957265ae7e2e55b2835f8e47
7
- data.tar.gz: 75b8bc577271cfe6b8a58ec5ec8a7d65c1e308aee3dfef8481e65869ac4e749ff9725f7f0d4fa752b391638c0e4b0003cafd2cd91ff352514fa03301df7931e8
6
+ metadata.gz: 639af898d48d62cfdf69c325986fab12147ddad81219b0e60557a9e52288597d5dddd3f4473ac94df3bbfd5ade304bb55c3f1a49b9918f4c959941ba4899f773
7
+ data.tar.gz: 9f715f65e2afa4ac783db81cd8cab09b137b206dae15d4b05e757dc2d0c82e04848dbd2551e02b8a7c6127aed3b5cb5257c920e8d79f027cf42d1b61ae238679
@@ -0,0 +1,38 @@
1
+ # This workflow uses actions that are not certified by GitHub.
2
+ # They are provided by a third-party and are governed by
3
+ # separate terms of service, privacy policy, and support
4
+ # documentation.
5
+ # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
6
+ # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
7
+
8
+ name: Ruby
9
+
10
+ on:
11
+ push:
12
+ branches: [ "master" ]
13
+ pull_request:
14
+ branches: [ "master" ]
15
+
16
+ permissions:
17
+ contents: read
18
+
19
+ jobs:
20
+ test:
21
+ runs-on: ubuntu-latest
22
+ strategy:
23
+ matrix:
24
+ ruby-version: ['2.7', '3.0', '3.1', '3.2']
25
+
26
+ steps:
27
+ - uses: actions/checkout@v3
28
+ - name: Set up Ruby
29
+ # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
30
+ # change this to (see https://github.com/ruby/setup-ruby#versioning):
31
+ # uses: ruby/setup-ruby@v1
32
+ uses: ruby/setup-ruby@ee2113536afb7f793eed4ce60e8d3b26db912da4 # v1.127.0
33
+ with:
34
+ ruby-version: ${{ matrix.ruby-version }}
35
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
36
+
37
+ - name: Run tests
38
+ run: bundle exec rake
data/.rubocop.yml CHANGED
@@ -24,6 +24,18 @@ Layout/FirstHashElementIndentation:
24
24
  Layout/FirstParameterIndentation:
25
25
  Enabled: false # Revisit if more settings become available.
26
26
 
27
+ Layout/LineContinuationSpacing:
28
+ EnforcedStyle: no_space
29
+
30
+ Layout/LineEndStringConcatenationIndentation:
31
+ EnforcedStyle: aligned
32
+
33
+ Layout/LineLength:
34
+ Max: 80
35
+ Exclude:
36
+ - "object_identifier.gemspec"
37
+ - "scripts/benchmarking/**/*"
38
+
27
39
  Layout/MultilineMethodCallBraceLayout:
28
40
  EnforcedStyle: same_line
29
41
 
@@ -42,11 +54,15 @@ Lint/AmbiguousOperator:
42
54
  Lint/AmbiguousRegexpLiteral:
43
55
  Enabled: false # Conflicts with other rules.
44
56
 
57
+ Lint/OrAssignmentToConstant:
58
+ Exclude:
59
+ - "scripts/**/*"
60
+
45
61
  Lint/Void:
46
62
  CheckForMethodsWithNoSideEffects: true
47
63
 
48
64
  Metrics/BlockLength:
49
- ExcludedMethods:
65
+ AllowedMethods:
50
66
  - describe
51
67
  - context
52
68
  - ips # Benchmarking
@@ -55,11 +71,6 @@ Metrics/ClassLength:
55
71
  Exclude:
56
72
  - "test/**/*"
57
73
 
58
- Metrics/LineLength:
59
- Max: 80
60
- Exclude:
61
- - "object_identifier.gemspec"
62
-
63
74
  Naming/MethodParameterName:
64
75
  AllowedNames:
65
76
  - a
@@ -71,6 +82,10 @@ Style/Alias:
71
82
  Style/BlockDelimiters:
72
83
  Enabled: false # Reconsider later.
73
84
 
85
+ Style/ClassAndModuleChildren:
86
+ AutoCorrect: true
87
+ EnforcedStyle: compact
88
+
74
89
  Style/EmptyElse:
75
90
  # It"s helpful to show intent by including a comment in an else block.
76
91
  Enabled: false
@@ -88,6 +103,13 @@ Style/FormatString:
88
103
  Style/Lambda:
89
104
  EnforcedStyle: literal
90
105
 
106
+ Style/LambdaCall:
107
+ Enabled: false # Allow ServiceObject.(*). Only use on classes, not instances.
108
+
109
+ Style/OpenStructUse:
110
+ Exclude:
111
+ - "test/**/*"
112
+
91
113
  Style/RegexpLiteral:
92
114
  EnforcedStyle: mixed
93
115
 
data/CHANGELOG.md CHANGED
@@ -1,4 +1,9 @@
1
- ### 0.4.1 - 2022-12-?
1
+ ### 0.5.0 - 2023-01-04
2
+ - Add support for defining customer Formatters.
3
+ - Add ObjectInspector::Configuration#formatter_class setting for overriding the default Formatter. See the README for more.
4
+ - Add a benchmarking script for comparing performance of formatters. See the README for more.
5
+
6
+ ### 0.4.1 - 2022-12-30
2
7
  - Make compatible with Ruby 3.2 (and likely Ruby 3.0 and 3.1 as well).
3
8
  - Update development dependencies.
4
9
 
data/Gemfile.lock CHANGED
@@ -1,13 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- object_identifier (0.4.1)
4
+ object_identifier (0.5.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
9
  ansi (1.5.0)
10
10
  ast (2.4.2)
11
+ benchmark-ips (2.10.0)
11
12
  builder (3.2.4)
12
13
  byebug (11.1.3)
13
14
  coderay (1.1.3)
@@ -15,12 +16,13 @@ GEM
15
16
  json (2.6.3)
16
17
  kwalify (0.7.2)
17
18
  method_source (1.0.0)
18
- minitest (5.16.3)
19
+ minitest (5.17.0)
19
20
  minitest-reporters (1.5.0)
20
21
  ansi
21
22
  builder
22
23
  minitest (>= 5.0)
23
24
  ruby-progressbar
25
+ much-stub (0.1.10)
24
26
  parallel (1.22.1)
25
27
  parser (3.1.3.0)
26
28
  ast (~> 2.4.1)
@@ -38,14 +40,14 @@ GEM
38
40
  rainbow (>= 2.0, < 4.0)
39
41
  regexp_parser (2.6.1)
40
42
  rexml (3.2.5)
41
- rubocop (1.41.1)
43
+ rubocop (1.42.0)
42
44
  json (~> 2.3)
43
45
  parallel (~> 1.10)
44
46
  parser (>= 3.1.2.1)
45
47
  rainbow (>= 2.2.2, < 4.0)
46
48
  regexp_parser (>= 1.8, < 3.0)
47
49
  rexml (>= 3.2.5, < 4.0)
48
- rubocop-ast (>= 1.23.0, < 2.0)
50
+ rubocop-ast (>= 1.24.1, < 2.0)
49
51
  ruby-progressbar (~> 1.7)
50
52
  unicode-display_width (>= 1.4.0, < 3.0)
51
53
  rubocop-ast (1.24.1)
@@ -63,10 +65,12 @@ PLATFORMS
63
65
  ruby
64
66
 
65
67
  DEPENDENCIES
68
+ benchmark-ips
66
69
  bundler
67
70
  byebug
68
71
  minitest
69
72
  minitest-reporters
73
+ much-stub
70
74
  object_identifier!
71
75
  pry
72
76
  pry-byebug
data/README.md CHANGED
@@ -1,7 +1,6 @@
1
1
  # Object Identifier
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/object_identifier.svg)](https://badge.fury.io/rb/object_identifier)
4
- [![Test Coverage](https://api.codeclimate.com/v1/badges/0b737a72d16ec755c1ff/test_coverage)](https://codeclimate.com/github/pdobb/object_identifier/test_coverage)
5
4
  [![Maintainability](https://api.codeclimate.com/v1/badges/0b737a72d16ec755c1ff/maintainability)](https://codeclimate.com/github/pdobb/object_identifier/maintainability)
6
5
 
7
6
  Object Identifier allows quick, easy, and uniform identification of an object by inspecting its class name and outputting any desirable attributes/methods. It is great for logging, sending descriptive notification messages, etc.
@@ -45,6 +44,21 @@ Tested MRI Ruby Versions:
45
44
  * 2.6.6
46
45
 
47
46
 
47
+ ## Configuration
48
+
49
+ Global/default values for ObjectIdentifier can be configured via the ObjectIdentifier::Configuration object.
50
+
51
+ _Note: In a Rails app, the following would go in e.g. `config/initializers/object_identifier.rb`_
52
+
53
+ ```ruby
54
+ # Default values are shown.
55
+ ObjectIdentifier.configure do |config|
56
+ config.formatter_class = ObjectIdentifier::StringFormatter
57
+ config.default_attributes = %i[id]
58
+ end
59
+ ```
60
+
61
+
48
62
  ## Usage
49
63
 
50
64
  ### Defaults
@@ -152,6 +166,23 @@ OpenStruct.new(my_value: my_value_object).identify(:my_value)
152
166
  ObjectIdentifier works great with the [ObjectInspector](https://github.com/pdobb/object_inspector) gem.
153
167
 
154
168
 
169
+ ### Benchmarking Formatters
170
+
171
+ Performance of Formatters can be tested by playing the [Formatters Benchmarking Scripts](https://github.com/pdobb/object_identifier/tree/master/scripts/benchmarking) in the pry console for this gem.
172
+
173
+ Custom Formatters may be similarly gauged for comparison by adding them to the `custom_formatter_klasses` array before playing the script.
174
+
175
+ ```ruby
176
+ custom_formatter_klasses = [MyCustomFormatter]
177
+
178
+ play scripts/benchmarking/formatters.rb
179
+ # ObjectIdentifier::StringFormatter
180
+ # 58.478k (± 0.8%) i/s - 295.776k in 5.058178s
181
+ # MyCustomFormatter
182
+ # ...
183
+ ```
184
+
185
+
155
186
  ## Development
156
187
 
157
188
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -40,6 +40,6 @@ class Object
40
40
  # (1..10).to_a.identify(:to_f, limit: 2)
41
41
  # # => "Integer[to_f:1.0], Integer[to_f:2.0], ... (8 more)"
42
42
  def identify(*args, **kargs)
43
- ObjectIdentifier::Identifier.identify(self, *args, **kargs)
43
+ ObjectIdentifier::Identifier.(self, *args, **kargs)
44
44
  end
45
45
  end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ # ObjectIdentifier::StringFormatter builds a String to identify the
4
+ # given object(s).
5
+ class ObjectIdentifier::StringFormatter
6
+ NO_OBJECTS_INDICATOR = "[no objects]"
7
+ KLASS_NOT_GIVEN = "NOT_GIVEN"
8
+
9
+ def self.call(objects, *attributes, **kargs)
10
+ new(objects, *attributes, **kargs).call
11
+ end
12
+
13
+ # @param objects [Object, [Object, ...]] the object(s) to be interrogated for
14
+ # String values to be added to the output String
15
+ # @param attributes [Array, *args] a list of method calls to interrogate the
16
+ # given object(s) with
17
+ # @param limit [Integer, nil] a given limit on the number of objects to
18
+ # interrogate
19
+ # @param klass [String, Symbol] a preferred type name for identifying the
20
+ # given object(s) as
21
+ def initialize(
22
+ objects,
23
+ attributes = ObjectIdentifier::Identifier.default_attributes,
24
+ limit: nil,
25
+ klass: KLASS_NOT_GIVEN)
26
+ @objects = ObjectIdentifier::ArrayWrap.(objects)
27
+ @attributes = ObjectIdentifier::ArrayWrap.(attributes)
28
+ @limit = (limit || @objects.size).to_i
29
+ @klass = klass.to_s
30
+ end
31
+
32
+ # Output the self-identifying string for the given object(s). Will either
33
+ # return a single object representation or a list of object
34
+ # representations, based on the number of objects we're identifying.
35
+ #
36
+ # @return [String] a string that identifies the object(s)
37
+ def call
38
+ return NO_OBJECTS_INDICATOR if @objects.empty?
39
+
40
+ output_strings = @objects.first(@limit).map { |obj| format(obj) }
41
+ output_strings << "... (#{truncated_objects_count} more)" if truncated?
42
+ output_strings.join(", ")
43
+ end
44
+
45
+ private
46
+
47
+ def format(object)
48
+ return NO_OBJECTS_INDICATOR if blank?(object)
49
+
50
+ "#{class_name(object)}[#{format_attributes(evaluate_attributes(object))}]"
51
+ end
52
+
53
+ # Simple version of Rails' Object#blank? method.
54
+ def blank?(object)
55
+ object.nil? || object == [] || object == {}
56
+ end
57
+
58
+ def class_name(object)
59
+ klass_given? ? @klass : object.class.name
60
+ end
61
+
62
+ def klass_given?
63
+ @klass != KLASS_NOT_GIVEN
64
+ end
65
+
66
+ def format_attributes(attributes_hash)
67
+ return if attributes_hash.empty?
68
+
69
+ attributes_formatter = determine_attributes_formatter(attributes_hash)
70
+ attributes_hash.map(&attributes_formatter).join(", ")
71
+ end
72
+
73
+ def determine_attributes_formatter(attributes_hash)
74
+ if attributes_hash.one?
75
+ ->(_key, value) { value.inspect_lit }
76
+ else
77
+ ->(key, value) { "#{key}:#{value.inspect_lit}" }
78
+ end
79
+ end
80
+
81
+ # @return [Hash]
82
+ def evaluate_attributes(object)
83
+ @attributes.each_with_object({}) { |key, acc|
84
+ if object.respond_to?(key, :include_private)
85
+ acc[key] = object.send(key)
86
+ elsif key.to_s.start_with?("@")
87
+ acc[key] = object.instance_variable_get(key)
88
+ end
89
+ }
90
+ end
91
+
92
+ def truncated_objects_count
93
+ @truncated_objects_count ||= objects_count - @limit
94
+ end
95
+
96
+ def objects_count
97
+ @objects_count ||= @objects.size
98
+ end
99
+
100
+ def truncated?
101
+ truncated_objects_count.positive?
102
+ end
103
+ end
@@ -1,161 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module ObjectIdentifier
4
- # ObjectIdentifier::Identifier manages construction of the inspect String.
5
- class Identifier
6
- NO_OBJECTS_INDICATOR = "[no objects]"
7
-
8
- # Class method for constructing a self-identifying string for any given
9
- # object or collection of objects.
10
- #
11
- # @overload self.identify(obj, *args)
12
- # @param obj [Object] the object to identify
13
- # @param args [*] (optional) a list of arguments to identify for this
14
- # object or for each object in this collection
15
- # @overload self.identify(obj, *args, options)
16
- # @param obj [Object] the object to identify
17
- # @param args [*] (optional) (default :id) a list of arguments to identify
18
- # for this object
19
- # @param [Hash] options the options for building a customized
20
- # self-identifier
21
- # @option options [String, nil] :klass object class name override
22
- # @option options [Integer] :limit maximum number of objects to display
23
- # from a collection
24
- #
25
- # @return [String] a self-identifying string like `Class[id:1, name:'temp']`
26
- #
27
- # @example
28
- # ObjectIdentifier::Identifier.identify(
29
- # OpenStruct.new(a: 1, b: '2', c: :"3"), :a, :b, :c)
30
- # # => "OpenStruct[a:1, b:\"2\", c::\"3\"]"
31
- #
32
- # ObjectIdentifier::Identifier.identify(1, :to_s)
33
- # # => "Integer[to_s:\"1\"]"
34
- # ObjectIdentifier::Identifier.identify(nil)
35
- # # => "[no objects]"
36
- #
37
- # ObjectIdentifier::Identifier.identify(%w(1 2), :to_i, :to_f)
38
- # # => "String[to_i:1, to_f:1.0], String[to_i:2, to_f:2.0]"
39
- #
40
- # ObjectIdentifier::Identifier.identify((1..10).to_a, :to_f, limit: 2)
41
- # # => "Integer[to_f:1.0], Integer[to_f:2.0], ... (8 more)"
42
- def self.identify(*args, **kargs)
43
- new(*args, **kargs).to_s
44
- end
45
-
46
- def initialize(objects, *args, limit: nil, klass: :not_given)
47
- @objects = ArrayWrap.call(objects)
48
- @attributes = args.empty? ? [:id] : args
49
- @limit = (limit || @objects.size).to_i
50
- @klass = klass
51
- end
52
-
53
- # Output the self-identifying string for an instance of
54
- # ObjectIdentifier::Identifier. Will either return a single object
55
- # representation or a list of object representations, based on the number of
56
- # objects we're identifying.
57
- #
58
- # @return [String] a string representing the object or list of objects
59
- def to_s
60
- if many?
61
- format_multiple_objects
62
- else
63
- format_single_object
64
- end
65
- end
66
-
67
- private
68
-
69
- def format_multiple_objects
70
- objects =
71
- @objects.first(@limit).map { |obj| format(obj) }
72
-
73
- objects << "... (#{truncated_objects_count} more)" if truncated?
74
-
75
- objects.join(", ")
76
- end
77
-
78
- def format_single_object
79
- object = @objects.first if @objects.respond_to?(:first)
80
-
81
- format(object)
82
- end
83
-
84
- def format(object)
85
- return NO_OBJECTS_INDICATOR if blank?(object)
86
-
87
- "#{class_name(object)}[#{format_attributes(evaluate_attributes(object))}]"
88
- end
89
-
90
- def format_attributes(attributes_hash)
91
- return if attributes_hash.empty?
92
-
93
- attributes_hash.
94
- map(&format_attributes_map_block(attributes_hash)).
95
- join(", ")
96
- end
97
-
98
- def format_attributes_map_block(attributes_hash)
99
- if attributes_hash.one?
100
- ->(_key, value) { value.inspect_lit }
101
- else
102
- ->(key, value) { "#{key}:#{value.inspect_lit}" }
103
- end
104
- end
105
-
106
- # @return [Hash]
107
- def evaluate_attributes(object)
108
- @attributes.each_with_object({}) { |key, acc|
109
- if object.respond_to?(key, :include_private)
110
- acc[key] = object.send(key)
111
- elsif key.to_s.start_with?("@")
112
- acc[key] = object.instance_variable_get(key)
113
- end
114
- }
115
- end
116
-
117
- def class_name(object)
118
- klass_given? ? @klass : object.class.name
119
- end
120
-
121
- def truncated_objects_count
122
- objects_count - @limit
123
- end
124
-
125
- def objects_count
126
- @objects_count ||= @objects.size
127
- end
128
-
129
- def klass_given?
130
- @klass != :not_given
131
- end
132
-
133
- def blank?(object)
134
- object.nil? || object == [] || object == {}
135
- end
136
-
137
- def many?
138
- objects_count > 1
139
- end
3
+ # ObjectIdentifier::Identifier manages construction of identification outputs
4
+ # using the passed in formatter_class.
5
+ class ObjectIdentifier::Identifier
6
+ # NOTE: `kargs` may be specific to the Formatter being called.
7
+ def self.call(
8
+ objects,
9
+ *attributes,
10
+ formatter_class: default_formatter_class,
11
+ **formatter_options)
12
+ formatter_class.(objects, *attributes, **formatter_options)
13
+ end
140
14
 
141
- def truncated?
142
- truncated_objects_count.positive?
143
- end
15
+ def self.default_formatter_class
16
+ ObjectIdentifier.configuration.formatter_class
17
+ end
144
18
 
145
- # ObjectIdentifier::Identifier::ArrayWrap mirrors the implementation of
146
- # Rails' {Array.wrap} method. This allows us to get around objects that
147
- # respond to `to_a` (such as Struct) and, instead, utilize either `to_ary`
148
- # or just actually wrapping the object in an Array.
149
- class ArrayWrap
150
- def self.call(object)
151
- if object.nil?
152
- []
153
- elsif object.respond_to?(:to_ary)
154
- object.to_ary || [object]
155
- else
156
- [object]
157
- end
158
- end
159
- end
19
+ def self.default_attributes
20
+ ObjectIdentifier.configuration.default_attributes
160
21
  end
161
22
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ObjectIdentifier
4
- VERSION = "0.4.1"
4
+ VERSION = "0.5.0"
5
5
  end
@@ -3,10 +3,63 @@
3
3
  # ObjectIdentifier is the base namespace for all modules/classes related to the
4
4
  # object_identifier gem.
5
5
  module ObjectIdentifier
6
+ # ObjectIdentifier::ArrayWrap mirrors the implementation of Rails'
7
+ # {Array.wrap} method. This allows us to get around objects that respond to
8
+ # `to_a` (such as Struct) and, instead, either utilize `to_ary` or just
9
+ # actually wrap the object in an Array ourselves.
10
+ class ArrayWrap
11
+ def self.call(object)
12
+ if object.nil?
13
+ []
14
+ elsif object.respond_to?(:to_ary)
15
+ object.to_ary || [object]
16
+ else
17
+ [object]
18
+ end
19
+ end
20
+ end
21
+
22
+ def self.configuration
23
+ @configuration ||= Configuration.new
24
+ end
25
+
26
+ def self.configure
27
+ yield(configuration)
28
+ end
29
+
30
+ def self.reset_configuration
31
+ @configuration = Configuration.new
32
+ end
33
+
34
+ # ObjectIdentifier::Configuration stores the default configuration options for
35
+ # the ObjectIdentifier gem. Modification of attributes is possible at any
36
+ # time, and values will persist for the duration of the running process.
37
+ class Configuration
38
+ attr_reader :formatter_class,
39
+ :default_attributes
40
+
41
+ def initialize
42
+ @formatter_class = ObjectIdentifier::StringFormatter
43
+ @default_attributes = %i[id]
44
+ end
45
+
46
+ def formatter_class=(value)
47
+ unless value.is_a?(Class)
48
+ raise TypeError, "Formatter must be a Class constant"
49
+ end
50
+
51
+ @formatter_class = value
52
+ end
53
+
54
+ def default_attributes=(value)
55
+ @default_attributes = value.to_a.map!(&:to_sym)
56
+ end
57
+ end
6
58
  end
7
59
 
8
60
  require "object_identifier/version"
9
61
  require "object_identifier/identifier"
62
+ require "object_identifier/formatters/string_formatter"
10
63
  require "core_ext/object"
11
64
  require "core_ext/string"
12
65
  require "core_ext/symbol"
@@ -10,6 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.authors = ["Paul DobbinSchmaltz", "Evan Sherwood"]
11
11
  spec.email = ["p.dobbinschmaltz@icloud.com"]
12
12
  spec.required_ruby_version = ">= 2.4.0"
13
+ spec.metadata = { "rubygems_mfa_required" => "true" }
13
14
 
14
15
  spec.summary = "ObjectIdentifier identifies an object by its class name and attributes."
15
16
  spec.description = "Object Identifier allows quick, easy, and uniform identification of an object by inspecting its class name and outputting any desirable attributes/methods. It is great for logging, sending descriptive notification messages, etc."
@@ -32,10 +33,12 @@ Gem::Specification.new do |spec|
32
33
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
33
34
  spec.require_paths = ["lib"]
34
35
 
36
+ spec.add_development_dependency "benchmark-ips"
35
37
  spec.add_development_dependency "bundler"
36
38
  spec.add_development_dependency "byebug"
37
39
  spec.add_development_dependency "minitest"
38
40
  spec.add_development_dependency "minitest-reporters"
41
+ spec.add_development_dependency "much-stub"
39
42
  spec.add_development_dependency "pry"
40
43
  spec.add_development_dependency "pry-byebug"
41
44
  spec.add_development_dependency "rake"
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Play from the pry console with:
4
+ # play scripts/benchmarking/formatters.rb
5
+
6
+ require "benchmark/ips"
7
+
8
+ custom_formatter_klasses ||= []
9
+
10
+ formatter_klasses = [
11
+ ObjectIdentifier::StringFormatter,
12
+ *Array(custom_formatter_klasses)
13
+ ].freeze
14
+
15
+ MyObject ||= Struct.new(:id, :name)
16
+
17
+ objects = [
18
+ MyObject.new(id: 1, name: "NAME1"),
19
+ MyObject.new(id: 2, name: "NAME2"),
20
+ MyObject.new(id: 3, name: "NAME3")
21
+ ].freeze
22
+
23
+ puts "== Averaged ============================================================="
24
+ Benchmark.ips { |x|
25
+ formatter_klasses.each do |formatter_klass|
26
+ x.report(formatter_klass) {
27
+ formatter_klass.new(objects[0]).call
28
+ formatter_klass.new(objects[0], %i[id name]).call
29
+ formatter_klass.new(objects[0], klass: "CustomClass").call
30
+ formatter_klass.new(objects[0], %i[id name], klass: "CustomClass").call
31
+ formatter_klass.new(objects, limit: 2).call
32
+ formatter_klass.new(objects, %i[id name], klass: "CustomClass", limit: 2).call
33
+ }
34
+ end
35
+
36
+ x.compare!
37
+ }
38
+ puts "== Done"
39
+
40
+ puts "== Individualized ======================================================="
41
+ Benchmark.ips { |x|
42
+ # rubocop:disable Style/CombinableLoops
43
+ formatter_klasses.each do |formatter_klass|
44
+ x.report("#{formatter_klass} - Default Attributes") {
45
+ formatter_klass.new(objects[0]).call
46
+ }
47
+ end
48
+ formatter_klasses.each do |formatter_klass|
49
+ x.report("#{formatter_klass} - Custom Attributes") {
50
+ formatter_klass.new(objects[0], %i[id name]).call
51
+ }
52
+ end
53
+ formatter_klasses.each do |formatter_klass|
54
+ x.report("#{formatter_klass} - Custom Class") {
55
+ formatter_klass.new(objects[0], klass: "CustomClass").call
56
+ }
57
+ end
58
+ formatter_klasses.each do |formatter_klass|
59
+ x.report("#{formatter_klass} - Custom Attributes & Custom Class") {
60
+ formatter_klass.new(objects[0], %i[id name], klass: "CustomClass").call
61
+ }
62
+ end
63
+ formatter_klasses.each do |formatter_klass|
64
+ x.report("#{formatter_klass} - Limit 2") {
65
+ formatter_klass.new(objects, limit: 2).call
66
+ }
67
+ end
68
+ formatter_klasses.each do |formatter_klass|
69
+ x.report("#{formatter_klass} - Custom Attributes & Custom Class & Limit 2") {
70
+ formatter_klass.new(objects, %i[id name], klass: "CustomClass", limit: 2).call
71
+ }
72
+ end
73
+ # rubocop:enable Style/CombinableLoops
74
+
75
+ x.compare!
76
+ }
77
+ puts "== Done"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: object_identifier
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul DobbinSchmaltz
@@ -9,8 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2022-12-30 00:00:00.000000000 Z
12
+ date: 2023-01-05 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: benchmark-ips
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
14
28
  - !ruby/object:Gem::Dependency
15
29
  name: bundler
16
30
  requirement: !ruby/object:Gem::Requirement
@@ -67,6 +81,20 @@ dependencies:
67
81
  - - ">="
68
82
  - !ruby/object:Gem::Version
69
83
  version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: much-stub
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
70
98
  - !ruby/object:Gem::Dependency
71
99
  name: pry
72
100
  requirement: !ruby/object:Gem::Requirement
@@ -160,6 +188,7 @@ executables: []
160
188
  extensions: []
161
189
  extra_rdoc_files: []
162
190
  files:
191
+ - ".github/workflows/ci.yml"
163
192
  - ".gitignore"
164
193
  - ".rubocop"
165
194
  - ".rubocop.yml"
@@ -176,13 +205,16 @@ files:
176
205
  - lib/core_ext/string.rb
177
206
  - lib/core_ext/symbol.rb
178
207
  - lib/object_identifier.rb
208
+ - lib/object_identifier/formatters/string_formatter.rb
179
209
  - lib/object_identifier/identifier.rb
180
210
  - lib/object_identifier/version.rb
181
211
  - object_identifier.gemspec
212
+ - scripts/benchmarking/formatters.rb
182
213
  homepage: https://github.com/pdobb/object_identifier
183
214
  licenses:
184
215
  - MIT
185
- metadata: {}
216
+ metadata:
217
+ rubygems_mfa_required: 'true'
186
218
  post_install_message:
187
219
  rdoc_options: []
188
220
  require_paths: