object_identifier 0.4.0 → 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: bbab525606ca826781627ff66be0e57229d14be19e2d19d562f5f73d7b2b7a5d
4
- data.tar.gz: b266c154b7c283721b335d752b40705b3ba9000ad46d0ad8689a1f7654249c54
3
+ metadata.gz: 4553678db77484aa04ce8bf00e3238310bb253632fb8867cae4e948a35bfda6c
4
+ data.tar.gz: afae645239815d3a9a011b56892127eccbf0dbc9558fc59ed6d7c15349fdbbe7
5
5
  SHA512:
6
- metadata.gz: b83e5d96392c489dd19a32d265602161069db563c7bda67a4aa88eb28eca6ea26ffdf3641b52a060482493717c1f652b190b6545547b6ae4cadfa1cee3360451
7
- data.tar.gz: 26f3c65910cd39d01e51af199b57f5a8fee3d1ddbe79f67b69552b0abf9c5f9da9752e8947afa0f663aa53e84f0968940cae59d9735a9f5c3745329ad778839d
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,3 +1,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
7
+ - Make compatible with Ruby 3.2 (and likely Ruby 3.0 and 3.1 as well).
8
+ - Update development dependencies.
9
+
1
10
  ### 0.4.0 - 2020-09-01
2
11
  - [#4](https://github.com/pdobb/object_identifier/pull/4) Only show attribute names if identifying more than one attribute.
3
12
  - Update development dependencies.
data/Gemfile.lock CHANGED
@@ -1,70 +1,76 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- object_identifier (0.4.0)
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
- ast (2.4.1)
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)
14
- docile (1.3.2)
15
+ docile (1.4.0)
16
+ json (2.6.3)
15
17
  kwalify (0.7.2)
16
18
  method_source (1.0.0)
17
- minitest (5.14.2)
18
- minitest-reporters (1.4.2)
19
+ minitest (5.17.0)
20
+ minitest-reporters (1.5.0)
19
21
  ansi
20
22
  builder
21
23
  minitest (>= 5.0)
22
24
  ruby-progressbar
23
- parallel (1.19.2)
24
- parser (2.7.1.4)
25
+ much-stub (0.1.10)
26
+ parallel (1.22.1)
27
+ parser (3.1.3.0)
25
28
  ast (~> 2.4.1)
26
- pry (0.13.1)
29
+ pry (0.14.1)
27
30
  coderay (~> 1.1)
28
31
  method_source (~> 1.0)
29
- pry-byebug (3.9.0)
32
+ pry-byebug (3.10.1)
30
33
  byebug (~> 11.0)
31
- pry (~> 0.13.0)
32
- psych (3.1.0)
33
- rainbow (3.0.0)
34
- rake (13.0.1)
35
- reek (6.0.1)
34
+ pry (>= 0.13, < 0.15)
35
+ rainbow (3.1.1)
36
+ rake (13.0.6)
37
+ reek (6.1.3)
36
38
  kwalify (~> 0.7.0)
37
- parser (>= 2.5.0.0, < 2.8, != 2.5.1.1)
38
- psych (~> 3.1.0)
39
+ parser (~> 3.1.0)
39
40
  rainbow (>= 2.0, < 4.0)
40
- regexp_parser (1.7.1)
41
- rexml (3.2.4)
42
- rubocop (0.90.0)
41
+ regexp_parser (2.6.1)
42
+ rexml (3.2.5)
43
+ rubocop (1.42.0)
44
+ json (~> 2.3)
43
45
  parallel (~> 1.10)
44
- parser (>= 2.7.1.1)
46
+ parser (>= 3.1.2.1)
45
47
  rainbow (>= 2.2.2, < 4.0)
46
- regexp_parser (>= 1.7)
47
- rexml
48
- rubocop-ast (>= 0.3.0, < 1.0)
48
+ regexp_parser (>= 1.8, < 3.0)
49
+ rexml (>= 3.2.5, < 4.0)
50
+ rubocop-ast (>= 1.24.1, < 2.0)
49
51
  ruby-progressbar (~> 1.7)
50
- unicode-display_width (>= 1.4.0, < 2.0)
51
- rubocop-ast (0.3.0)
52
- parser (>= 2.7.1.4)
53
- ruby-progressbar (1.10.1)
54
- simplecov (0.19.0)
52
+ unicode-display_width (>= 1.4.0, < 3.0)
53
+ rubocop-ast (1.24.1)
54
+ parser (>= 3.1.1.0)
55
+ ruby-progressbar (1.11.0)
56
+ simplecov (0.22.0)
55
57
  docile (~> 1.1)
56
58
  simplecov-html (~> 0.11)
57
- simplecov-html (0.12.2)
58
- unicode-display_width (1.7.0)
59
+ simplecov_json_formatter (~> 0.1)
60
+ simplecov-html (0.12.3)
61
+ simplecov_json_formatter (0.1.4)
62
+ unicode-display_width (2.3.0)
59
63
 
60
64
  PLATFORMS
61
65
  ruby
62
66
 
63
67
  DEPENDENCIES
68
+ benchmark-ips
64
69
  bundler
65
70
  byebug
66
71
  minitest
67
72
  minitest-reporters
73
+ much-stub
68
74
  object_identifier!
69
75
  pry
70
76
  pry-byebug
@@ -74,4 +80,4 @@ DEPENDENCIES
74
80
  simplecov
75
81
 
76
82
  BUNDLED WITH
77
- 2.1.4
83
+ 2.4.1
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2018 Paul Dobbins
3
+ Copyright (c) 2022 Paul DobbinSchmaltz
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,8 +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
- [![Build Status](https://travis-ci.org/pdobb/object_identifier.svg?branch=master)](https://travis-ci.org/pdobb/object_identifier)
5
- [![Test Coverage](https://api.codeclimate.com/v1/badges/0b737a72d16ec755c1ff/test_coverage)](https://codeclimate.com/github/pdobb/object_identifier/test_coverage)
6
4
  [![Maintainability](https://api.codeclimate.com/v1/badges/0b737a72d16ec755c1ff/maintainability)](https://codeclimate.com/github/pdobb/object_identifier/maintainability)
7
5
 
8
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.
@@ -40,11 +38,27 @@ Or install it yourself as:
40
38
  ## Compatibility
41
39
 
42
40
  Tested MRI Ruby Versions:
41
+ * 3.2.0
43
42
  * 2.4.9
44
43
  * 2.5.8
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,11 +166,30 @@ 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.
158
189
 
159
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
190
+ To install this gem onto your local machine, run `bundle exec rake install`.
191
+
192
+ To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
160
193
 
161
194
 
162
195
  ## Contributing
@@ -39,7 +39,7 @@ class Object
39
39
  #
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
- def identify(*args)
43
- ObjectIdentifier::Identifier.identify(self, *args)
42
+ def identify(*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(object, *args)
43
- new(object, *args).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.0"
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"
@@ -7,9 +7,10 @@ require "object_identifier/version"
7
7
  Gem::Specification.new do |spec|
8
8
  spec.name = "object_identifier"
9
9
  spec.version = ObjectIdentifier::VERSION
10
- spec.authors = ["Paul Dobbins", "Evan Sherwood"]
11
- spec.email = ["paul.dobbins@icloud.com"]
10
+ spec.authors = ["Paul DobbinSchmaltz", "Evan Sherwood"]
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,16 +1,30 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: object_identifier
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
- - Paul Dobbins
7
+ - Paul DobbinSchmaltz
8
8
  - Evan Sherwood
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2020-09-01 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
@@ -155,15 +183,15 @@ description: Object Identifier allows quick, easy, and uniform identification of
155
183
  object by inspecting its class name and outputting any desirable attributes/methods.
156
184
  It is great for logging, sending descriptive notification messages, etc.
157
185
  email:
158
- - paul.dobbins@icloud.com
186
+ - p.dobbinschmaltz@icloud.com
159
187
  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"
166
- - ".travis.yml"
167
195
  - CHANGELOG.md
168
196
  - Gemfile
169
197
  - Gemfile.lock
@@ -177,13 +205,16 @@ files:
177
205
  - lib/core_ext/string.rb
178
206
  - lib/core_ext/symbol.rb
179
207
  - lib/object_identifier.rb
208
+ - lib/object_identifier/formatters/string_formatter.rb
180
209
  - lib/object_identifier/identifier.rb
181
210
  - lib/object_identifier/version.rb
182
211
  - object_identifier.gemspec
212
+ - scripts/benchmarking/formatters.rb
183
213
  homepage: https://github.com/pdobb/object_identifier
184
214
  licenses:
185
215
  - MIT
186
- metadata: {}
216
+ metadata:
217
+ rubygems_mfa_required: 'true'
187
218
  post_install_message:
188
219
  rdoc_options: []
189
220
  require_paths:
@@ -199,7 +230,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
199
230
  - !ruby/object:Gem::Version
200
231
  version: '0'
201
232
  requirements: []
202
- rubygems_version: 3.1.4
233
+ rubygems_version: 3.4.1
203
234
  signing_key:
204
235
  specification_version: 4
205
236
  summary: ObjectIdentifier identifies an object by its class name and attributes.
data/.travis.yml DELETED
@@ -1,19 +0,0 @@
1
- env:
2
- global:
3
- - CC_TEST_REPORTER_ID=3b57e55dcd3cc40ee073715e7d75fa80ab7b7687cb8a420eac500d27b5cb28db
4
- sudo: false
5
- language: ruby
6
- rvm:
7
- - 2.4.9
8
- - 2.5.8
9
- - 2.6.6
10
- notifications:
11
- email: false
12
- before_install: gem install bundler -v 2.1.4
13
- cache: bundler
14
- before_script:
15
- - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
16
- - chmod +x ./cc-test-reporter
17
- - ./cc-test-reporter before-build
18
- after_script:
19
- - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT