object_identifier 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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"