object_identifier 0.6.0 → 0.7.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: 77c88ad5dd6256732f3cb586a72a2a6eb4c0c36e9042af8be0176599ba16d2d2
4
- data.tar.gz: 69874ab0c4790cc824e664394327132fac01c2ac4873b85b42c50792367ea1f9
3
+ metadata.gz: f93a767a479c1b5fccb0203eb79707479970876206c1325e567afe0792032d58
4
+ data.tar.gz: 3c6508fa051abfce2c19001783e98658b9e183f8725e871044a67b5185042bf8
5
5
  SHA512:
6
- metadata.gz: 0f2a040a4fbf0becb441abe51af4d2dc1bd74b2f4b4f33a29ddbe0e68df38600c54c44e3d1b989d99e921d5a41b62d8ca4dac488ecfe6e7e123c299f91951af5
7
- data.tar.gz: 57f3ed43f09b46f84d3982a36c4822b1ae86d659ed9f6ccbf928b939257e29ab2d0bd4891d702b43f37825b410baa90063945f59f0f08cde8ad061b52662dfc1
6
+ metadata.gz: 3861571fbe466a526f9c10fe4c840ee51c7124998cf1009c81a9667c070cf1999362fa501b7030da795612b16ec81ff2f436a41613fd1256db614ecbecb46b34
7
+ data.tar.gz: 9c8505f55368a9cb64e0d8bcee68f2b5de7f0a4346a227d75d8d93465072da0d027b888789a6da90aef86867399546ac27c1a63eb945d6778050a6df46bd8bb8
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2022 Paul DobbinSchmaltz
3
+ Copyright (c) 2023 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
@@ -38,17 +38,16 @@ Or install it yourself as:
38
38
  ## Compatibility
39
39
 
40
40
  Tested MRI Ruby Versions:
41
- * 2.4 (not recently tested)
42
- * 2.5 (not recently tested)
43
- * 2.6 (not recently tested)
44
41
  * 2.7
42
+ * 3.0
45
43
  * 3.1
46
44
  * 3.2
47
45
 
46
+ Object Identifier has no other dependencies.
48
47
 
49
48
  ## Configuration
50
49
 
51
- Global/default values for ObjectIdentifier can be configured via the ObjectIdentifier::Configuration object.
50
+ Global/default values for Object Identifier can be configured via the ObjectIdentifier::Configuration object.
52
51
 
53
52
  _Note: In a Rails app, the following would go in e.g. `config/initializers/object_identifier.rb`_
54
53
 
@@ -165,19 +164,19 @@ OpenStruct.new(my_value: my_value_object).identify(:my_value)
165
164
 
166
165
  ## Supporting Gems
167
166
 
168
- ObjectIdentifier works great with the [ObjectInspector](https://github.com/pdobb/object_inspector) gem.
167
+ Object Identifier works great with the [Object Inspector](https://github.com/pdobb/object_inspector) gem.
169
168
 
170
169
 
171
170
  ### Benchmarking Formatters
172
171
 
173
- Performance of Formatters can be tested by playing the [Formatters Benchmarking Scripts](https://github.com/pdobb/object_identifier/blob/master/scripts/benchmarking/formatters.rb) in the pry console for this gem.
172
+ Performance of Formatters can be tested by playing the [Formatters Benchmarking Scripts](https://github.com/pdobb/object_identifier/blob/master/script/benchmarking/formatters.rb) in the pry console for this gem.
174
173
 
175
174
  Custom Formatters may be similarly gauged for comparison by adding them to the `custom_formatter_klasses` array before playing the script.
176
175
 
177
176
  ```ruby
178
177
  custom_formatter_klasses = [MyCustomFormatter]
179
178
 
180
- play scripts/benchmarking/formatters.rb
179
+ play script/benchmarking/formatters.rb
181
180
  # ObjectIdentifier::StringFormatter
182
181
  # 58.478k (± 0.8%) i/s - 295.776k in 5.058178s
183
182
  # MyCustomFormatter
@@ -187,11 +186,21 @@ play scripts/benchmarking/formatters.rb
187
186
 
188
187
  ## Development
189
188
 
190
- 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.
189
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. Or, run `rake` to run the tests plus linters as well as `yard` (to confirm proper YARD documentation practices). You can also run `bin/console` for an interactive prompt that will allow you to experiment.
191
190
 
192
191
  To install this gem onto your local machine, run `bundle exec rake install`.
193
192
 
194
- 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).
193
+ To release a new version, update the version number in `version.rb`, bump the latest ruby target versions etc. with `rake bump`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
194
+
195
+
196
+ ### Documentation
197
+
198
+ [YARD documentation](https://yardoc.org/index.html) can be generated and viewed live:
199
+ 1. Install YARD: `gem install yard`
200
+ 2. Run the YARD server: `yard server --reload`
201
+ 3. Open the live documentation site: `open http://localhost:8808`
202
+
203
+ While the YARD server is running, documentation in the live site will be auto-updated on source code save (and site reload).
195
204
 
196
205
 
197
206
  ## 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, **kargs)
43
- ObjectIdentifier.(self, *args, **kargs)
42
+ def identify(*args, **kwargs)
43
+ ObjectIdentifier.(self, *args, **kwargs)
44
44
  end
45
45
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ # ObjectIdentifier::ArrayWrap mirrors the implementation of Rails'
4
+ # Array.wrap method. This allows us to get around objects that respond to
5
+ # `to_a` (such as Struct) and, instead, either utilize `to_ary` or just
6
+ # actually wrap the object in an Array ourselves.
7
+ class ObjectIdentifier::ArrayWrap
8
+ # :reek:NilCheck
9
+ # :reek:ManualDispatch
10
+
11
+ # Dispatch "Array Wrapping" logic on the given `object`.
12
+ #
13
+ # @param object The object(s) to attempt to Array wrap.
14
+ def self.call(object)
15
+ if object.nil?
16
+ []
17
+ elsif object.respond_to?(:to_ary)
18
+ object.to_ary || [object]
19
+ else
20
+ [object]
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ # ObjectIdentifier is the top-level namespace/module for this gem.
4
+ module ObjectIdentifier
5
+ # Default Configuration Accessors
6
+
7
+ # The default formatter class to use ({ObjectIdentifier::StringFormatter}).
8
+ def self.default_formatter_class
9
+ configuration.formatter_class
10
+ end
11
+
12
+ # The default attributes to include on object inspections.
13
+ def self.default_attributes
14
+ configuration.default_attributes
15
+ end
16
+
17
+ # Custom Configuration Getters/Setters
18
+
19
+ # Accessor for the {ObjectIdentifier::Configuration} object.
20
+ def self.configuration
21
+ @configuration ||= ObjectIdentifier::Configuration.new
22
+ end
23
+
24
+ # @yieldparam configuration [ObjectIdentifier::Configuration]
25
+ def self.configure
26
+ yield(configuration)
27
+ end
28
+
29
+ # Reset the current configuration settings memoized by
30
+ # {ObjectIdentifier.configuration}.
31
+ def self.reset_configuration
32
+ @configuration = ObjectIdentifier::Configuration.new
33
+ end
34
+
35
+ # ObjectIdentifier::Configuration stores the default configuration options for
36
+ # the ObjectIdentifier gem. Modification of attributes is possible at any
37
+ # time, and values will persist for the duration of the running process.
38
+ class Configuration
39
+ attr_reader :formatter_class,
40
+ :default_attributes
41
+
42
+ def initialize
43
+ @formatter_class = ObjectIdentifier::StringFormatter
44
+ @default_attributes = %i[id]
45
+ end
46
+
47
+ def formatter_class=(value)
48
+ unless value.is_a?(Class)
49
+ raise TypeError, "Formatter must be a Class constant"
50
+ end
51
+
52
+ @formatter_class = value
53
+ end
54
+
55
+ def default_attributes=(value)
56
+ @default_attributes = value.to_a.map!(&:to_sym)
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ # ObjectIdentifier::BaseFormatter is an abstract base class for formatters.
4
+ class ObjectIdentifier::BaseFormatter
5
+ attr_reader :objects,
6
+ :parameters
7
+
8
+ # A shortcut for calling `new(...).call`.
9
+ def self.call(...)
10
+ new(...).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 parameters [ObjectIdentifier::Parameters]
16
+ def initialize(objects, parameters: ObjectIdentifier::Parameters.build)
17
+ @objects = ObjectIdentifier::ArrayWrap.(objects)
18
+ @parameters = parameters
19
+ end
20
+
21
+ def call
22
+ raise NotImplementedError
23
+ end
24
+ end
@@ -2,54 +2,41 @@
2
2
 
3
3
  # ObjectIdentifier::StringFormatter builds a String to identify the
4
4
  # given object(s).
5
- class ObjectIdentifier::StringFormatter
5
+ class ObjectIdentifier::StringFormatter < ObjectIdentifier::BaseFormatter
6
+ # The String to output when {#objects} is empty.
6
7
  NO_OBJECTS_INDICATOR = "[no objects]"
7
8
 
8
- def self.call(objects, parameters = ObjectIdentifier.buid_parameters)
9
- new(objects, parameters).call
10
- end
11
-
12
- # @param objects [Object, [Object, ...]] the object(s) to be interrogated for
13
- # String values to be added to the output String
14
- # @param parameters [ObjectIdentifier::Parameters]
15
- def initialize(objects, parameters = ObjectIdentifier.buid_parameters)
16
- @objects = ObjectIdentifier::ArrayWrap.(objects)
17
- @parameters = parameters
18
- end
19
-
20
9
  # Output the self-identifying string for the given object(s). Will either
21
10
  # return a single object representation or a list of object
22
11
  # representations, based on the number of objects we're identifying.
23
12
  #
24
- # @return [String] a string that identifies the object(s)
13
+ # @return [String] A string that identifies the object(s).
25
14
  def call
26
- if @objects.none?
15
+ if objects.none?
27
16
  NO_OBJECTS_INDICATOR
28
- elsif @objects.one?
29
- format_single_object
30
- else # @objects.size > 1
31
- format_multiple_objects
17
+ elsif objects.one?
18
+ format_item
19
+ else # objects.size > 1
20
+ format_collection
32
21
  end
33
22
  end
34
23
 
35
24
  private
36
25
 
37
- def format_single_object(object = @objects.first)
38
- SingleObject.(object, @parameters)
26
+ def format_collection
27
+ Collection.new(objects, parameters).call
39
28
  end
40
29
 
41
- def format_multiple_objects
42
- Collection.(@objects, @parameters)
30
+ def format_item(object = objects.first)
31
+ Item.new(object, parameters).call
43
32
  end
44
33
 
45
34
  # ObjectIdentifier::StringFormatter::Collection formats a collection-specific
46
35
  # identification String, which will also necessarily be composed of
47
- # {ObjectIdentifier::StringFormatter::SingleObject} identification Strings.
36
+ # {ObjectIdentifier::StringFormatter::Item} identification Strings.
48
37
  class Collection
49
- # @return [String] the self-identifying String for the passed in object.
50
- def self.call(*args)
51
- new(*args).call
52
- end
38
+ attr_reader :objects,
39
+ :parameters
53
40
 
54
41
  # @param objects [Object, [Object, ...]] the object(s) to be interrogated
55
42
  # for String values to be added to the output String
@@ -59,21 +46,28 @@ class ObjectIdentifier::StringFormatter
59
46
  @parameters = parameters
60
47
  end
61
48
 
49
+ # Build a comma-separated list of formatted item Strings representing the
50
+ # given objects.
51
+ #
52
+ # @return [String]
62
53
  def call
63
- output_strings =
64
- @objects.first(limit).map { |obj| format_single_object(obj) }
65
- output_strings << "... (#{truncated_objects_count} more)" if truncated?
66
- output_strings.join(", ")
54
+ parts = objects.first(limit).map { |obj| format_item(obj) }
55
+ parts << "... (#{truncated_objects_count} more)" if truncated?
56
+ parts.join(", ")
67
57
  end
68
58
 
69
59
  private
70
60
 
71
- def format_single_object(object = @objects.first)
72
- SingleObject.(object, @parameters)
61
+ def format_item(object)
62
+ Item.new(object, parameters).call
73
63
  end
74
64
 
75
65
  def limit
76
- @parameters.limit { objects_count }
66
+ parameters.limit { objects_count }
67
+ end
68
+
69
+ def truncated?
70
+ truncated_objects_count.positive?
77
71
  end
78
72
 
79
73
  def truncated_objects_count
@@ -81,31 +75,25 @@ class ObjectIdentifier::StringFormatter
81
75
  end
82
76
 
83
77
  def objects_count
84
- @objects_count ||= @objects.size
85
- end
86
-
87
- def truncated?
88
- truncated_objects_count.positive?
78
+ @objects_count ||= objects.size
89
79
  end
90
80
  end
91
81
 
92
- # ObjectIdentifier::StringFormatter::SingleObject formats a
93
- # single-object-specific identification String.
94
- class SingleObject
95
- # @return [String] the self-identifying String for the passed in object.
96
- def self.call(*args)
97
- new(*args).call
98
- end
82
+ # ObjectIdentifier::StringFormatter::Item formats a single-object-specific
83
+ # identification String.
84
+ class Item
85
+ attr_reader :object,
86
+ :parameters
99
87
 
100
- # @param object [Object] the object to be interrogated for String values to
101
- # be added to the output String
88
+ # @param object [Object] The object to be interrogated for String values to
89
+ # be added to the output String.
102
90
  # @param parameters [ObjectIdentifier::Parameters]
103
91
  def initialize(object, parameters)
104
92
  @object = object
105
93
  @parameters = parameters
106
94
  end
107
95
 
108
- # @return [String] the self-identifying String for {@object}.
96
+ # @return [String] The self-identifying String for {#object}.
109
97
  def call
110
98
  return NO_OBJECTS_INDICATOR if blank?
111
99
 
@@ -114,23 +102,23 @@ class ObjectIdentifier::StringFormatter
114
102
 
115
103
  private
116
104
 
117
- # Simple version of Rails' Object#blank? method.
118
105
  # :reek:NilCheck
106
+
107
+ # Simple version of Rails' Object#blank? method.
119
108
  def blank?
120
- @object.nil? || @object == [] || @object == {}
109
+ object.nil? || object == [] || object == {}
121
110
  end
122
111
 
123
112
  def class_name
124
- @parameters.klass { @object.class.name }
113
+ parameters.klass { object.class.name }
125
114
  end
126
115
 
127
116
  def formatted_attributes
128
- return if attributes_hash.empty?
129
-
130
117
  attributes_hash.map(&attributes_formatter).join(", ")
131
118
  end
132
119
 
133
120
  # :reek:DuplicateMethodCall
121
+
134
122
  def attributes_formatter
135
123
  @attributes_formatter ||=
136
124
  if attributes_hash.one?
@@ -140,21 +128,22 @@ class ObjectIdentifier::StringFormatter
140
128
  end
141
129
  end
142
130
 
143
- # @return [Hash]
144
131
  # :reek:ManualDispatch
132
+
133
+ # @return [Hash]
145
134
  def attributes_hash
146
135
  @attributes_hash ||=
147
136
  attributes.each_with_object({}) { |key, acc|
148
- if @object.respond_to?(key, :include_private)
149
- acc[key] = @object.__send__(key)
137
+ if object.respond_to?(key, :include_private)
138
+ acc[key] = object.__send__(key)
150
139
  elsif key.to_s.start_with?("@")
151
- acc[key] = @object.instance_variable_get(key)
140
+ acc[key] = object.instance_variable_get(key)
152
141
  end
153
142
  }
154
143
  end
155
144
 
156
145
  def attributes
157
- @parameters.attributes
146
+ parameters.attributes
158
147
  end
159
148
  end
160
149
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ # ObjectIdentifier is the top-level namespace/module for this gem.
4
+ module ObjectIdentifier
5
+ # :reek:LongParameterList
6
+
7
+ # ObjectIdentifier.call is the main entry point for use of this gem. In
8
+ # typical usage, however, this method will almost exclusively just be called
9
+ # by {Object#identify}, as defined in lib/core_ext/object.rb.
10
+ def self.call(
11
+ objects,
12
+ *attributes,
13
+ formatter_class: default_formatter_class,
14
+ **formatter_options)
15
+
16
+ parameters =
17
+ ObjectIdentifier::Parameters.build(
18
+ attributes: attributes,
19
+ formatter_options: formatter_options)
20
+
21
+ formatter_class.(objects, parameters: parameters)
22
+ end
23
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ # ObjectIdentifier::Parameters encapsulates the attributes list and
4
+ # formatter options that may be needed for custom formatting during object
5
+ # identification.
6
+ class ObjectIdentifier::Parameters
7
+ # This String to display if `formatter_options[:klass]` isn't present.
8
+ KLASS_NOT_GIVEN = "NOT_GIVEN"
9
+
10
+ attr_reader :attributes
11
+
12
+ # Factory method for building an {ObjectIdentifier::Parameters} object. Uses
13
+ # ObjectIdentifier.default_attributes if the given `attributes` array is
14
+ # empty.
15
+ def self.build(attributes: [], formatter_options: {})
16
+ attrs = ObjectIdentifier::ArrayWrap.(attributes)
17
+ attrs = ObjectIdentifier.default_attributes if attrs.empty?
18
+ attrs.flatten!
19
+
20
+ new(
21
+ attributes: attrs,
22
+ formatter_options: formatter_options.to_h)
23
+ end
24
+
25
+ # @param attributes [Array, *args] A list of method calls to interrogate the
26
+ # given object(s) with.
27
+ # @option formatter_options[:limit] [Integer, nil] A given limit on the number
28
+ # of objects to interrogate.
29
+ # @option formatter_options[:klass] [#to_s] A preferred type name for
30
+ # identifying the given object(s) as.
31
+ def initialize(
32
+ attributes: [],
33
+ formatter_options: {})
34
+ @attributes = attributes
35
+ @limit = formatter_options.fetch(:limit, nil)
36
+ @klass = formatter_options.fetch(:klass, KLASS_NOT_GIVEN)
37
+ end
38
+
39
+ # NOTE: Expects a block if a value wasn't supplied on initialization.
40
+ def limit
41
+ @limit || (yield if block_given?)
42
+ end
43
+
44
+ # NOTE: Expects a block if a value wasn't supplied on initialization.
45
+ def klass
46
+ if klass_given?
47
+ @klass.to_s
48
+ elsif block_given?
49
+ yield.to_s
50
+ else
51
+ nil
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def klass_given?
58
+ @klass != KLASS_NOT_GIVEN
59
+ end
60
+ end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ObjectIdentifier
4
- VERSION = "0.6.0"
4
+ # The current ObjectIdentifier gem version.
5
+ VERSION = "0.7.0"
5
6
  end
@@ -1,148 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # ObjectIdentifier is the base namespace for all modules/classes related to the
4
- # object_identifier gem.
3
+ # ObjectIdentifier is the top-level namespace/module for this gem.
5
4
  module ObjectIdentifier
6
- # ObjectIdentifier.call is the main entry point for use of this gem. In
7
- # typical usage, however, this method will almost exclusively just be called
8
- # by {Object#identify}, as defined in lib/core_ext/object.rb.
9
- # :reek:LongParameterList
10
- def self.call(
11
- objects,
12
- *attributes,
13
- formatter_class: default_formatter_class,
14
- **formatter_options)
15
-
16
- parameters =
17
- buid_parameters(
18
- attributes: attributes,
19
- formatter_options: formatter_options)
20
-
21
- formatter_class.(objects, parameters)
22
- end
23
-
24
- # Factory method for building an {ObjectIdentifier::Parameters} object.
25
- def self.buid_parameters(attributes: [], formatter_options: {})
26
- attrs = ObjectIdentifier::ArrayWrap.(attributes)
27
- attrs = default_attributes if attrs.empty?
28
- attrs.flatten!
29
-
30
- Parameters.new(
31
- attributes: attrs,
32
- formatter_options: formatter_options.to_h)
33
- end
34
-
35
- def self.default_formatter_class
36
- configuration.formatter_class
37
- end
38
-
39
- def self.default_attributes
40
- configuration.default_attributes
41
- end
42
-
43
- def self.configuration
44
- @configuration ||= Configuration.new
45
- end
46
-
47
- def self.configure
48
- yield(configuration)
49
- end
50
-
51
- def self.reset_configuration
52
- @configuration = Configuration.new
53
- end
54
-
55
- # ObjectIdentifier::Configuration stores the default configuration options for
56
- # the ObjectIdentifier gem. Modification of attributes is possible at any
57
- # time, and values will persist for the duration of the running process.
58
- class Configuration
59
- attr_reader :formatter_class,
60
- :default_attributes
61
-
62
- def initialize
63
- @formatter_class = ObjectIdentifier::StringFormatter
64
- @default_attributes = %i[id]
65
- end
66
-
67
- def formatter_class=(value)
68
- unless value.is_a?(Class)
69
- raise TypeError, "Formatter must be a Class constant"
70
- end
71
-
72
- @formatter_class = value
73
- end
74
-
75
- def default_attributes=(value)
76
- @default_attributes = value.to_a.map!(&:to_sym)
77
- end
78
- end
79
-
80
- # ObjectIdentifier::Parameters encapsulates the attributes list and
81
- # formatter options that may be needed for custom formatting during object
82
- # identification.
83
- class Parameters
84
- KLASS_NOT_GIVEN = "NOT_GIVEN"
85
-
86
- attr_reader :attributes
87
-
88
- # @param attributes [Array, *args] a list of method calls to interrogate the
89
- # given object(s) with
90
- # @param formatter_options[:limit] [Integer, nil] (nil) a given limit on the
91
- # number of objects to interrogate
92
- # @param formatter_options[:klass] [#to_s] a preferred type name for
93
- # identifying the given object(s) as
94
- def initialize(
95
- attributes: [],
96
- formatter_options: {})
97
- @attributes = attributes
98
- @limit = formatter_options.fetch(:limit, nil)
99
- @klass = formatter_options.fetch(:klass, KLASS_NOT_GIVEN)
100
- end
101
-
102
- # NOTE: Expects a block if a value wasn't supplied on initialization.
103
- def limit
104
- @limit || (yield if block_given?)
105
- end
5
+ end
106
6
 
107
- # NOTE: Expects a block if a value wasn't supplied on initialization.
108
- def klass
109
- if klass_given?
110
- @klass.to_s
111
- elsif block_given?
112
- yield.to_s
113
- else
114
- nil
115
- end
116
- end
7
+ require "object_identifier/version"
8
+ require "object_identifier/configuration"
9
+ require "object_identifier/object_identifier"
10
+ require "object_identifier/array_wrap"
11
+ require "object_identifier/parameters"
117
12
 
118
- private
13
+ # FORMATTERS
119
14
 
120
- def klass_given?
121
- @klass != KLASS_NOT_GIVEN
122
- end
123
- end
15
+ require "object_identifier/formatters/base_formatter"
16
+ require "object_identifier/formatters/string_formatter"
124
17
 
125
- # ObjectIdentifier::ArrayWrap mirrors the implementation of Rails'
126
- # {Array.wrap} method. This allows us to get around objects that respond to
127
- # `to_a` (such as Struct) and, instead, either utilize `to_ary` or just
128
- # actually wrap the object in an Array ourselves.
129
- class ArrayWrap
130
- # :reek:NilCheck
131
- # :reek:ManualDispatch
132
- def self.call(object)
133
- if object.nil?
134
- []
135
- elsif object.respond_to?(:to_ary)
136
- object.to_ary || [object]
137
- else
138
- [object]
139
- end
140
- end
141
- end
142
- end
18
+ # CORE EXTENSIONS
143
19
 
144
- require "object_identifier/version"
145
- require "object_identifier/formatters/string_formatter"
146
20
  require "core_ext/object"
147
21
  require "core_ext/string"
148
22
  require "core_ext/symbol"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: object_identifier
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul DobbinSchmaltz
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-01-09 00:00:00.000000000 Z
11
+ date: 2023-11-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: benchmark-ips
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pdobb-style
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: pry
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -151,7 +165,7 @@ dependencies:
151
165
  - !ruby/object:Gem::Version
152
166
  version: '0'
153
167
  - !ruby/object:Gem::Dependency
154
- name: rubocop
168
+ name: simplecov
155
169
  requirement: !ruby/object:Gem::Requirement
156
170
  requirements:
157
171
  - - ">="
@@ -165,7 +179,7 @@ dependencies:
165
179
  - !ruby/object:Gem::Version
166
180
  version: '0'
167
181
  - !ruby/object:Gem::Dependency
168
- name: simplecov
182
+ name: solargraph
169
183
  requirement: !ruby/object:Gem::Requirement
170
184
  requirements:
171
185
  - - ">="
@@ -187,32 +201,28 @@ executables: []
187
201
  extensions: []
188
202
  extra_rdoc_files: []
189
203
  files:
190
- - ".github/workflows/ci.yml"
191
- - ".gitignore"
192
- - ".reek.yml"
193
- - ".rubocop"
194
- - ".rubocop.yml"
195
- - CHANGELOG.md
196
- - Gemfile
197
- - Gemfile.lock
198
204
  - LICENSE.txt
199
205
  - README.md
200
- - Rakefile
201
- - bin/console
202
- - bin/setup
203
206
  - lib/core_ext/big_decimal.rb
204
207
  - lib/core_ext/object.rb
205
208
  - lib/core_ext/string.rb
206
209
  - lib/core_ext/symbol.rb
207
210
  - lib/object_identifier.rb
211
+ - lib/object_identifier/array_wrap.rb
212
+ - lib/object_identifier/configuration.rb
213
+ - lib/object_identifier/formatters/base_formatter.rb
208
214
  - lib/object_identifier/formatters/string_formatter.rb
215
+ - lib/object_identifier/object_identifier.rb
216
+ - lib/object_identifier/parameters.rb
209
217
  - lib/object_identifier/version.rb
210
- - object_identifier.gemspec
211
- - scripts/benchmarking/formatters.rb
212
218
  homepage: https://github.com/pdobb/object_identifier
213
219
  licenses:
214
220
  - MIT
215
221
  metadata:
222
+ bug_tracker_uri: https://github.com/pdobb/object_identifier/issues
223
+ changelog_uri: https://github.com/pdobb/object_identifier/releases
224
+ source_code_uri: https://github.com/pdobb/object_identifier
225
+ homepage_uri: https://github.com/pdobb/object_identifier
216
226
  rubygems_mfa_required: 'true'
217
227
  post_install_message:
218
228
  rdoc_options: []
@@ -222,15 +232,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
222
232
  requirements:
223
233
  - - ">="
224
234
  - !ruby/object:Gem::Version
225
- version: 2.4.0
235
+ version: '2.7'
226
236
  required_rubygems_version: !ruby/object:Gem::Requirement
227
237
  requirements:
228
238
  - - ">="
229
239
  - !ruby/object:Gem::Version
230
240
  version: '0'
231
241
  requirements: []
232
- rubygems_version: 3.4.1
242
+ rubygems_version: 3.4.10
233
243
  signing_key:
234
244
  specification_version: 4
235
- summary: ObjectIdentifier identifies an object by its class name and attributes.
245
+ summary: Object Identifier identifies an object by its class name and attributes.
236
246
  test_files: []
@@ -1,38 +0,0 @@
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/.gitignore DELETED
@@ -1,11 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /_yardoc/
4
- /coverage/
5
- /doc/
6
- /pkg/
7
- /spec/reports/
8
- /tmp/
9
- .byebug_history
10
- *.gem
11
- .DS_Store
data/.reek.yml DELETED
@@ -1,11 +0,0 @@
1
- directories:
2
- "test":
3
- IrresponsibleModule:
4
- enabled: false
5
- UtilityFunction:
6
- enabled: false
7
- "scripts":
8
- IrresponsibleModule:
9
- enabled: false
10
- UtilityFunction:
11
- enabled: false
data/.rubocop DELETED
@@ -1,4 +0,0 @@
1
- --display-cop-names
2
- --display-style-guide
3
- --extra-details
4
- --format=fuubar
data/.rubocop.yml DELETED
@@ -1,127 +0,0 @@
1
- AllCops:
2
- UseCache: true
3
- DisplayCopNames: true
4
- DisplayStyleGuide: true
5
- ExtraDetails: false
6
- TargetRubyVersion: 2.4.0
7
- NewCops: enable
8
-
9
- Layout/DotPosition:
10
- EnforcedStyle: trailing
11
-
12
- Layout/EndOfLine:
13
- EnforcedStyle: lf
14
-
15
- Layout/FirstArgumentIndentation:
16
- EnforcedStyle: consistent_relative_to_receiver
17
-
18
- Layout/FirstArrayElementIndentation:
19
- EnforcedStyle: consistent
20
-
21
- Layout/FirstHashElementIndentation:
22
- EnforcedStyle: consistent
23
-
24
- Layout/FirstParameterIndentation:
25
- Enabled: false # Revisit if more settings become available.
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
-
39
- Layout/MultilineMethodCallBraceLayout:
40
- EnforcedStyle: same_line
41
-
42
- Layout/MultilineMethodCallIndentation:
43
- EnforcedStyle: indented_relative_to_receiver
44
-
45
- Layout/MultilineMethodDefinitionBraceLayout:
46
- EnforcedStyle: same_line
47
-
48
- Layout/MultilineOperationIndentation:
49
- Enabled: false # Waiting for e.g. `indented_relative_to_receiver`.
50
-
51
- Lint/AmbiguousOperator:
52
- Enabled: false # Conflicts with other rules.
53
-
54
- Lint/AmbiguousRegexpLiteral:
55
- Enabled: false # Conflicts with other rules.
56
-
57
- Lint/OrAssignmentToConstant:
58
- Exclude:
59
- - "scripts/**/*"
60
-
61
- Lint/Void:
62
- CheckForMethodsWithNoSideEffects: true
63
-
64
- Metrics/BlockLength:
65
- AllowedMethods:
66
- - describe
67
- - context
68
- - ips # Benchmarking
69
-
70
- Metrics/ClassLength:
71
- Exclude:
72
- - "test/**/*"
73
-
74
- Naming/MethodParameterName:
75
- AllowedNames:
76
- - a
77
- - b
78
-
79
- Style/Alias:
80
- EnforcedStyle: prefer_alias_method
81
-
82
- Style/BlockDelimiters:
83
- Enabled: false # Reconsider later.
84
-
85
- Style/ClassAndModuleChildren:
86
- AutoCorrect: true
87
- EnforcedStyle: compact
88
-
89
- Style/EmptyElse:
90
- # It"s helpful to show intent by including a comment in an else block.
91
- Enabled: false
92
-
93
- Style/EmptyMethod:
94
- EnforcedStyle: expanded
95
-
96
- Style/ExpandPathArguments:
97
- Exclude:
98
- - "object_inspector.gemspec"
99
-
100
- Style/FormatString:
101
- Enabled: false # % notation with an Array just reads better sometimes.
102
-
103
- Style/Lambda:
104
- EnforcedStyle: literal
105
-
106
- Style/LambdaCall:
107
- Enabled: false # Allow ServiceObject.(*). Only use on classes, not instances.
108
-
109
- Style/OpenStructUse:
110
- Exclude:
111
- - "test/**/*"
112
-
113
- Style/RegexpLiteral:
114
- EnforcedStyle: mixed
115
-
116
- Style/RescueStandardError:
117
- EnforcedStyle: implicit
118
-
119
- Style/SingleLineMethods:
120
- Exclude:
121
- - "test/**/*_test.rb"
122
-
123
- Style/StringLiterals:
124
- EnforcedStyle: double_quotes
125
-
126
- Style/StringLiteralsInInterpolation:
127
- EnforcedStyle: double_quotes
data/CHANGELOG.md DELETED
@@ -1,36 +0,0 @@
1
- ### 0.6.0 - 2023-01-09
2
- - Internal refactoring for more Object-Oriented goodness.
3
-
4
- #### BREAKING
5
- - Refactor `ObjectIdentifier::Identifier` to just `ObjectIdentifier`. This has no effect on instance method usage (e.g. `<my_object>.identify(...)`). But if any manual invocations were made (e.g. `ObjectIdentifier::Identifier.call(...)`) then they will need to be updated to `ObjectIdentifier.call(...)` (or just `ObjectIdentifier.(...)`, per your own style guide).
6
-
7
- ### 0.5.0 - 2023-01-04
8
- - Add support for defining customer Formatters.
9
- - Add ObjectInspector::Configuration#formatter_class setting for overriding the default Formatter. See the README for more.
10
- - Add a benchmarking script for comparing performance of formatters. See the README for more.
11
-
12
- ### 0.4.1 - 2022-12-30
13
- - Make compatible with Ruby 3.2 (and likely Ruby 3.0 and 3.1 as well).
14
- - Update development dependencies.
15
-
16
- ### 0.4.0 - 2020-09-01
17
- - [#4](https://github.com/pdobb/object_identifier/pull/4) Only show attribute names if identifying more than one attribute.
18
- - Update development dependencies.
19
-
20
- #### BREAKING
21
- - Drop support for Ruby 2.3.
22
-
23
- ### 0.3.0 - 2019-06-27
24
- - Fix identification of objects that implement `to_a`, such as Struct.
25
-
26
- ### 0.2.1 - 2019-02-24
27
- - Add ability to identify instance vars.
28
-
29
- ### 0.1.0 - 2018-04-14
30
- - Revamp gem.
31
- - Update gem dependencies.
32
- - Now returns "[no objects]" even if given a :klass option.
33
-
34
-
35
- ### 0.0.6 - 2016-02-06
36
- - Fix: identify method now supports private & protected methods.
data/Gemfile DELETED
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- source "https://rubygems.org"
4
-
5
- git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
-
7
- # Specify your gem's dependencies in object_identifier.gemspec
8
- gemspec
data/Gemfile.lock DELETED
@@ -1,83 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- object_identifier (0.6.0)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- ansi (1.5.0)
10
- ast (2.4.2)
11
- benchmark-ips (2.10.0)
12
- builder (3.2.4)
13
- byebug (11.1.3)
14
- coderay (1.1.3)
15
- docile (1.4.0)
16
- json (2.6.3)
17
- kwalify (0.7.2)
18
- method_source (1.0.0)
19
- minitest (5.17.0)
20
- minitest-reporters (1.5.0)
21
- ansi
22
- builder
23
- minitest (>= 5.0)
24
- ruby-progressbar
25
- much-stub (0.1.10)
26
- parallel (1.22.1)
27
- parser (3.1.3.0)
28
- ast (~> 2.4.1)
29
- pry (0.14.1)
30
- coderay (~> 1.1)
31
- method_source (~> 1.0)
32
- pry-byebug (3.10.1)
33
- byebug (~> 11.0)
34
- pry (>= 0.13, < 0.15)
35
- rainbow (3.1.1)
36
- rake (13.0.6)
37
- reek (6.1.3)
38
- kwalify (~> 0.7.0)
39
- parser (~> 3.1.0)
40
- rainbow (>= 2.0, < 4.0)
41
- regexp_parser (2.6.1)
42
- rexml (3.2.5)
43
- rubocop (1.42.0)
44
- json (~> 2.3)
45
- parallel (~> 1.10)
46
- parser (>= 3.1.2.1)
47
- rainbow (>= 2.2.2, < 4.0)
48
- regexp_parser (>= 1.8, < 3.0)
49
- rexml (>= 3.2.5, < 4.0)
50
- rubocop-ast (>= 1.24.1, < 2.0)
51
- ruby-progressbar (~> 1.7)
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)
57
- docile (~> 1.1)
58
- simplecov-html (~> 0.11)
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)
63
-
64
- PLATFORMS
65
- ruby
66
-
67
- DEPENDENCIES
68
- benchmark-ips
69
- bundler
70
- byebug
71
- minitest
72
- minitest-reporters
73
- much-stub
74
- object_identifier!
75
- pry
76
- pry-byebug
77
- rake
78
- reek
79
- rubocop
80
- simplecov
81
-
82
- BUNDLED WITH
83
- 2.4.1
data/Rakefile DELETED
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "bundler/gem_tasks"
4
- require "rake/testtask"
5
-
6
- Rake::TestTask.new(:test) do |t|
7
- t.libs << "test"
8
- t.libs << "lib"
9
- t.test_files = FileList["test/**/*_test.rb"]
10
- end
11
-
12
- task default: :test
data/bin/console DELETED
@@ -1,16 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require "bundler/setup"
5
- require "object_identifier"
6
- require "ostruct"
7
-
8
- # You can add fixtures and/or initialization code here to make experimenting
9
- # with your gem easier. You can also use a different console, if you like.
10
-
11
- # (If you use this, don't forget to add pry to your Gemfile!)
12
- require "pry"
13
- Pry.start
14
-
15
- # require "irb"
16
- # IRB.start(__FILE__)
data/bin/setup DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- lib = File.expand_path("lib", __dir__)
4
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
- require "object_identifier/version"
6
-
7
- Gem::Specification.new do |spec|
8
- spec.name = "object_identifier"
9
- spec.version = ObjectIdentifier::VERSION
10
- spec.authors = ["Paul DobbinSchmaltz"]
11
- spec.email = ["p.dobbinschmaltz@icloud.com"]
12
- spec.required_ruby_version = ">= 2.4.0"
13
- spec.metadata = { "rubygems_mfa_required" => "true" }
14
-
15
- spec.summary = "ObjectIdentifier identifies an object by its class name and attributes."
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."
17
- spec.homepage = "https://github.com/pdobb/object_identifier"
18
- spec.license = "MIT"
19
-
20
- # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
21
- # to allow pushing to a single host or delete this section to allow pushing to any host.
22
- # if spec.respond_to?(:metadata)
23
- # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
24
- # else
25
- # raise "RubyGems 2.0 or newer is required to protect against " \
26
- # "public gem pushes."
27
- # end
28
-
29
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
30
- f.match(%r{^(test|spec|features)/})
31
- end
32
- spec.bindir = "exe"
33
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
34
- spec.require_paths = ["lib"]
35
-
36
- spec.add_development_dependency "benchmark-ips"
37
- spec.add_development_dependency "bundler"
38
- spec.add_development_dependency "byebug"
39
- spec.add_development_dependency "minitest"
40
- spec.add_development_dependency "minitest-reporters"
41
- spec.add_development_dependency "much-stub"
42
- spec.add_development_dependency "pry"
43
- spec.add_development_dependency "pry-byebug"
44
- spec.add_development_dependency "rake"
45
- spec.add_development_dependency "reek"
46
- spec.add_development_dependency "rubocop"
47
- spec.add_development_dependency "simplecov"
48
- end
@@ -1,83 +0,0 @@
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
- def parameterize(attributes = [], **formatter_options)
24
- ObjectIdentifier.buid_parameters(
25
- attributes: attributes,
26
- formatter_options: formatter_options)
27
- end
28
-
29
- puts "== Averaged ============================================================="
30
- Benchmark.ips { |x|
31
- formatter_klasses.each do |formatter_klass|
32
- x.report(formatter_klass) {
33
- formatter_klass.new(objects[0]).call
34
- formatter_klass.new(objects[0], parameterize(%i[id name])).call
35
- formatter_klass.new(objects[0], parameterize(klass: "CustomClass")).call
36
- formatter_klass.new(objects[0], parameterize(%i[id name], klass: "CustomClass")).call
37
- formatter_klass.new(objects, parameterize(limit: 2)).call
38
- formatter_klass.new(objects, parameterize(%i[id name], klass: "CustomClass", limit: 2)).call
39
- }
40
- end
41
-
42
- x.compare!
43
- }
44
- puts "== Done"
45
-
46
- puts "== Individualized ======================================================="
47
- Benchmark.ips { |x|
48
- # rubocop:disable Style/CombinableLoops
49
- formatter_klasses.each do |formatter_klass|
50
- x.report("#{formatter_klass} - Default Attributes") {
51
- formatter_klass.new(objects[0]).call
52
- }
53
- end
54
- formatter_klasses.each do |formatter_klass|
55
- x.report("#{formatter_klass} - Custom Attributes") {
56
- formatter_klass.new(objects[0], parameterize(%i[id name])).call
57
- }
58
- end
59
- formatter_klasses.each do |formatter_klass|
60
- x.report("#{formatter_klass} - Custom Class") {
61
- formatter_klass.new(objects[0], parameterize(klass: "CustomClass")).call
62
- }
63
- end
64
- formatter_klasses.each do |formatter_klass|
65
- x.report("#{formatter_klass} - Custom Attributes & Custom Class") {
66
- formatter_klass.new(objects[0], parameterize(%i[id name], klass: "CustomClass")).call
67
- }
68
- end
69
- formatter_klasses.each do |formatter_klass|
70
- x.report("#{formatter_klass} - Limit 2") {
71
- formatter_klass.new(objects, parameterize(limit: 2)).call
72
- }
73
- end
74
- formatter_klasses.each do |formatter_klass|
75
- x.report("#{formatter_klass} - Custom Attributes & Custom Class & Limit 2") {
76
- formatter_klass.new(objects, parameterize(%i[id name], klass: "CustomClass", limit: 2)).call
77
- }
78
- end
79
- # rubocop:enable Style/CombinableLoops
80
-
81
- x.compare!
82
- }
83
- puts "== Done"