sleeping_king_studios-tools 1.1.0 → 1.2.0.rc.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.
@@ -23,38 +23,85 @@ module SleepingKingStudios::Tools
23
23
  :try
24
24
  end
25
25
 
26
- # Takes a proc or lambda and invokes it with the given object as
27
- # receiver, with any additional arguments or block provided.
26
+ # Calls a Proc or lambda on the given receiver with the given parameters.
28
27
  #
29
- # @param [Object] receiver The receiver. The proc will be called in the
28
+ # Unlike calling #instance_exec with the block, ObjectTools#apply allows you
29
+ # to specify a block parameter.
30
+ #
31
+ # @param receiver [Object] The receiver. the proc will be called in the
30
32
  # context of this object.
31
- # @param [Proc] proc The proc or lambda to call.
32
- # @param [Array] args Optional. Additional arguments to pass in to the
33
- # proc or lambda.
34
- # @param [block] block Optional. If present, will be passed in to proc or
33
+ # @param proc [Proc] the proc or lambda to call.
34
+ # @param args [Array] optional. Additional arguments to pass in to the proc
35
+ # or lambda.
36
+ # @param kwargs [Hash] optional. Additional keywords to pass in to the proc
37
+ # or lambda.
38
+ # @param block [block] optional. If present, will be passed in to proc or
35
39
  # lambda.
36
40
  #
37
- # @return The result of calling the proc or lambda with the given
41
+ # @return the result of calling the proc or lambda with the given
38
42
  # receiver and any additional arguments or block.
39
- def apply(receiver, proc, *args, &block)
40
- return receiver.instance_exec(*args, &proc) unless block_given?
43
+ #
44
+ # @example
45
+ # my_object = double('object', :to_s => 'A mock object')
46
+ # my_proc = ->() { puts %{#{self.to_s} says "Greetings, programs!"} }
47
+ #
48
+ # ObjectTools.apply my_object, my_proc
49
+ # #=> Writes 'A mock object says "Greetings, programs!"' to STDOUT.
50
+ def apply(receiver, proc, *args, **kwargs, &block)
51
+ return receiver.instance_exec(*args, **kwargs, &proc) unless block_given?
41
52
 
42
53
  method_name =
43
54
  Kernel.format(TEMPORARY_METHOD_NAME, Thread.current.object_id)
44
55
 
45
56
  with_temporary_method(receiver, method_name, proc) do
46
- receiver.send(method_name, *args, &block)
57
+ receiver.send(method_name, *args, **kwargs, &block)
47
58
  end
48
59
  end
49
60
 
50
- # Creates a deep copy of the object. If the object is an Array, returns a
51
- # new Array with deep copies of each array item. If the object is a Hash,
52
- # returns a new Hash with deep copies of each hash key and value. Otherwise,
53
- # returns Object#dup.
61
+ # Creates a deep copy of the object.
62
+ #
63
+ # If the object is an Array, returns a new Array with deep copies of each
64
+ # array item. If the object is a Hash, returns a new Hash with deep copies
65
+ # of each hash key and value. Otherwise, returns Object#dup.
66
+ #
67
+ # @param obj [Object] the object to copy.
68
+ #
69
+ # @return the copy of the object.
54
70
  #
55
- # @param [Object] obj The object to copy.
71
+ # @see ArrayTools#deep_copy
56
72
  #
57
- # @return The copy of the object.
73
+ # @see HashTools#deep_copy
74
+ #
75
+ # @example
76
+ # data = {
77
+ # :songs = [
78
+ # {
79
+ # :name => 'Welcome to the Jungle',
80
+ # :artist => "Guns N' Roses",
81
+ # :album => 'Appetite for Destruction'
82
+ # },
83
+ # {
84
+ # :name => 'Hells Bells',
85
+ # :artist => 'AC/DC',
86
+ # :album => 'Back in Black'
87
+ # },
88
+ # {
89
+ # :name => "Knockin' on Heaven's Door",
90
+ # :artist => 'Bob Dylan',
91
+ # :album => 'Pat Garrett & Billy The Kid'
92
+ # }
93
+ # ]
94
+ # }
95
+ #
96
+ # copy = ObjectTools.deep_dup data
97
+ #
98
+ # copy[:songs] << { :name => 'Sympathy for the Devil', :artist => 'The Rolling Stones', :album => 'Beggars Banquet' }
99
+ # data[:songs].count
100
+ # #=> 3
101
+ #
102
+ # copy[:songs][1][:name] = 'Shoot to Thrill'
103
+ # data[:songs][1]
104
+ # #=> { :name => 'Hells Bells', :artist => 'AC/DC', :album => 'Back in Black' }
58
105
  def deep_dup(obj)
59
106
  case obj
60
107
  when FalseClass, Integer, Float, NilClass, Symbol, TrueClass
@@ -68,12 +115,46 @@ module SleepingKingStudios::Tools
68
115
  end
69
116
  end
70
117
 
71
- # Performs a deep freeze of the object. If the object is an Array, freezes
72
- # the array and performs a deep freeze on each array item. If the object is
73
- # a hash, freezes the hash and performs a deep freeze on each hash key and
74
- # value. Otherwise, calls Object#freeze.
118
+ # Performs a deep freeze of the object.
119
+ #
120
+ # If the object is an Array, freezes the array and performs a deep freeze on
121
+ # each array item. If the object is a hash, freezes the hash and performs a
122
+ # deep freeze on each hash key and value. Otherwise, calls Object#freeze.
75
123
  #
76
- # @param [Object] obj The object to freeze.
124
+ # @param obj [Object] The object to freeze.
125
+ #
126
+ # @return [Object] the frozen object.
127
+ #
128
+ # @example
129
+ # data = {
130
+ # :songs = [
131
+ # {
132
+ # :name => 'Welcome to the Jungle',
133
+ # :artist => "Guns N' Roses",
134
+ # :album => 'Appetite for Destruction'
135
+ # },
136
+ # {
137
+ # :name => 'Hells Bells',
138
+ # :artist => 'AC/DC',
139
+ # :album => 'Back in Black'
140
+ # },
141
+ # {
142
+ # :name => "Knockin' on Heaven's Door",
143
+ # :artist => 'Bob Dylan',
144
+ # :album => 'Pat Garrett & Billy The Kid'
145
+ # }
146
+ # ]
147
+ # }
148
+ # ObjectTools.deep_freeze(data)
149
+ #
150
+ # data.frozen?
151
+ # #=> true
152
+ # data[:songs].frozen?
153
+ # #=> true
154
+ # data[:songs][0].frozen?
155
+ # #=> true
156
+ # data[:songs][0].name.frozen?
157
+ # #=> true
77
158
  def deep_freeze(obj)
78
159
  case obj
79
160
  when FalseClass, Integer, Float, NilClass, Symbol, TrueClass
@@ -87,96 +168,160 @@ module SleepingKingStudios::Tools
87
168
  end
88
169
  end
89
170
 
90
- # Accesses deeply nested attributes by calling the first named method on the
91
- # given object, and each subsequent method on the result of the previous
92
- # method call. If the object does not respond to the method name, nil is
93
- # returned instead of calling the method.
171
+ # Accesses deeply nested attributes on an object.
172
+ #
173
+ # This method calls the first named method on the given object, and then
174
+ # each subsequent method on the result of the previous method call. If the
175
+ # object does not respond to the method name, nil is returned instead of
176
+ # calling the method.
177
+ #
178
+ # @param obj [Object] the object to dig.
179
+ # @param method_names [Array] the names of the methods to call.
94
180
  #
95
- # @param [Object] object The object to dig.
96
- # @param [Array] method_names The names of the methods to call.
181
+ # @return [Object, nil] the result of the last method call, or nil if the
182
+ # last object does not respond to the last method.
97
183
  #
98
- # @return [Object] The result of the last method call, or nil if the last
99
- # object does not respond to the last method.
100
- def dig(object, *method_names)
101
- method_names.reduce(object) do |memo, method_name|
184
+ # @example
185
+ # ObjectTools.dig my_object, :first_method, :second_method, :third_method
186
+ # #=> my_object.first_method.second_method.third_method
187
+ def dig(obj, *method_names)
188
+ method_names.reduce(obj) do |memo, method_name|
102
189
  memo.respond_to?(method_name) ? memo.send(method_name) : nil
103
190
  end
104
191
  end
105
192
 
106
- # @!method metaclass(object)
107
- # Returns the object's singleton class.
108
- #
109
- # @param [Object] object The object for which an eigenclass is required.
110
- #
111
- # @return [Class] The object's eigenclass.
112
-
113
193
  # Returns the object's eigenclass.
114
194
  #
115
- # @param [Object] object The object for which an eigenclass is required.
195
+ # @param obj [Object] the object for which an eigenclass is required.
116
196
  #
117
- # @return [Class] The object's singleton class.
118
- def eigenclass(object)
119
- object.singleton_class
197
+ # @return [Class] the object's singleton class.
198
+ def eigenclass(obj)
199
+ obj.singleton_class
120
200
  end
121
201
  alias metaclass eigenclass
122
202
 
123
- # Returns true if the object is immutable. Values of nil, false, and true
124
- # are always immutable, as are instances of Numeric and Symbol. Arrays are
125
- # immutable if the array is frozen and each array item is immutable. Hashes
126
- # are immutable if the hash is frozen and each hash key and hash value are
127
- # immutable. Otherwise, objects are immutable if they are frozen.
203
+ # Checks if the object is immutable.
204
+ #
205
+ # - nil, false, and true are always immutable, as are instances of Numeric
206
+ # and Symbol.
207
+ # - Strings are immutable if frozen, such as strings defined in a file with
208
+ # a frozen_string_literal pragma.
209
+ # - Arrays are immutable if the array is frozen and each array item is
210
+ # immutable.
211
+ # - Hashes are immutable if the hash is frozen and each hash key and hash
212
+ # value are immutable.
213
+ # - Otherwise, objects are immutable if they are frozen.
214
+ #
215
+ # @param obj [Object] the object to test.
128
216
  #
129
- # @param obj [Object] The object to test.
217
+ # @return [Boolean] true if the object is immutable, otherwise false.
130
218
  #
131
- # @return [Boolean] True if the object is immutable, otherwise false.
219
+ # @example
220
+ # ObjectTools.immutable?(nil)
221
+ # #=> true
222
+ #
223
+ # ObjectTools.immutable?(false)
224
+ # #=> true
225
+ #
226
+ # ObjectTools.immutable?(0)
227
+ # #=> true
228
+ #
229
+ # ObjectTools.immutable?(:hello)
230
+ # #=> true
231
+ #
232
+ # ObjectTools.immutable?('Greetings, programs!')
233
+ # #=> true
234
+ #
235
+ # ObjectTools.immutable?(+'Greetings, programs!')
236
+ # #=> false
237
+ #
238
+ # ObjectTools.immutable?([1, 2, 3])
239
+ # #=> false
240
+ #
241
+ # ObjectTools.immutable?([1, 2, 3].freeze)
242
+ # #=> false
243
+ #
244
+ # @see #mutable?
245
+ #
246
+ # @see ArrayTools#immutable?
247
+ #
248
+ # @see HashTools#immutable?
132
249
  def immutable?(obj)
133
250
  case obj
134
251
  when NilClass, FalseClass, TrueClass, Numeric, Symbol
135
252
  true
136
253
  when ->(_) { ArrayTools.array?(obj) }
137
- ArrayTools.immutable? obj
254
+ ArrayTools.immutable?(obj)
138
255
  when ->(_) { HashTools.hash?(obj) }
139
- HashTools.immutable? obj
256
+ HashTools.immutable?(obj)
140
257
  else
141
258
  obj.frozen?
142
259
  end
143
260
  end
144
261
 
145
- # Returns true if the object is mutable.
262
+ # Checks if the object is mutable.
146
263
  #
147
- # @param obj [Object] The object to test.
264
+ # @param obj [Object] the object to test.
148
265
  #
149
- # @return [Boolean] True if the object is mutable, otherwise false.
266
+ # @return [Boolean] true if the object is mutable, otherwise false.
150
267
  #
151
268
  # @see #immutable?
152
269
  def mutable?(obj)
153
270
  !immutable?(obj)
154
271
  end
155
272
 
156
- # Returns true if the object is an Object. This should return true only for
157
- # objects that have an alternate inheritance chain from BasicObject, such as
158
- # a Proxy.
273
+ # Returns true if the object is an Object.
159
274
  #
160
- # @param obj [Object] The object to test.
275
+ # This should return false only for objects that have an alternate
276
+ # inheritance chain from BasicObject, such as a Proxy.
161
277
  #
162
- # @return [Boolean] True if the object is an Object, otherwise false.
278
+ # @param obj [Object] the object to test.
279
+ #
280
+ # @return [Boolean] true if the object is an Object, otherwise false.
281
+ #
282
+ # @example
283
+ # ObjectTools.object?(nil)
284
+ # #=> true
285
+ #
286
+ # ObjectTools.object?([])
287
+ # #=> true
288
+ #
289
+ # ObjectTools.object?({})
290
+ # #=> true
291
+ #
292
+ # ObjectTools.object?(1)
293
+ # #=> true
294
+ #
295
+ # ObjectTools.object?(BasicObject.new)
296
+ # #=> false
163
297
  def object?(obj)
164
298
  Object.instance_method(:is_a?).bind(obj).call(Object)
165
299
  end
166
300
 
167
301
  # As #send, but returns nil if the object does not respond to the method.
168
302
  #
169
- # @param [Object] object The receiver of the message.
170
- # @param [String, Symbol] method_name The name of the method to call.
171
- # @param [Array] args The arguments to the message.
303
+ # This method relies on #respond_to?, so methods defined with method_missing
304
+ # will not be called.
305
+ #
306
+ # @param obj [Object] the receiver of the message.
307
+ # @param method_name [String, Symbol] the name of the method to call.
308
+ # @param args [Array] the arguments to the message.
309
+ #
310
+ # @return [Object, nil] the return value of the called method, or nil if the
311
+ # object does not respond to the method.
172
312
  #
173
- # @see ActiveSupport::CoreExt::Object#try.
174
- def try(object, method_name, *args)
175
- return object.try(method_name, *args) if object.respond_to?(:try)
313
+ # @example
314
+ # ObjectTools.try(%w(ichi ni san), :count)
315
+ # #=> 3
316
+ #
317
+ # ObjectTools.try(nil, :count)
318
+ # #=> nil
319
+ def try(obj, method_name, *args)
320
+ return obj.try(method_name, *args) if obj.respond_to?(:try)
176
321
 
177
- return nil unless object.respond_to?(method_name)
322
+ return nil unless obj.respond_to?(method_name)
178
323
 
179
- object.send method_name, *args
324
+ obj.send(method_name, *args)
180
325
  end
181
326
 
182
327
  private
@@ -191,6 +336,3 @@ module SleepingKingStudios::Tools
191
336
  end
192
337
  end
193
338
  end
194
-
195
- require 'sleeping_king_studios/tools/array_tools'
196
- require 'sleeping_king_studios/tools/hash_tools'
@@ -10,10 +10,6 @@ module SleepingKingStudios::Tools
10
10
  def_delegators :instance,
11
11
  :camelize,
12
12
  :chain,
13
- :define_irregular_word,
14
- :define_plural_rule,
15
- :define_singular_rule,
16
- :define_uncountable_word,
17
13
  :indent,
18
14
  :map_lines,
19
15
  :plural?,
@@ -24,9 +20,10 @@ module SleepingKingStudios::Tools
24
20
  :underscore
25
21
  end
26
22
 
27
- # @param inflector [Object] An object that conforms to the interface used
28
- # by SleepingKingStudios::Tools::Toolbox::Inflector, such as
29
- # ActiveSupport::Inflector .
23
+ # @param inflector [Object] service object for inflecting strings. The
24
+ # inflector must be an object that conforms to the interface used by
25
+ # by SleepingKingStudios::Tools::Toolbox::Inflector, such as an instance
26
+ # of ActiveSupport::Inflector .
30
27
  def initialize(inflector: nil)
31
28
  super()
32
29
 
@@ -34,69 +31,131 @@ module SleepingKingStudios::Tools
34
31
  inflector || SleepingKingStudios::Tools::Toolbox::Inflector.new
35
32
  end
36
33
 
34
+ # @return [Object] service object for inflecting strings.
37
35
  attr_reader :inflector
38
36
 
39
37
  # Converts a lowercase, underscore-separated string to CamelCase.
40
38
  #
41
- # @param str [String] The string to convert.
39
+ # @param str [String] the string to convert.
42
40
  #
43
- # @return [String] The converted string.
41
+ # @return [String] the converted string.
44
42
  #
45
- # @see ActiveSupport::Inflector#camelize.
43
+ # @see SleepingKingStudios::Tools::Toolbox::Inflector#camelize.
44
+ #
45
+ # @example
46
+ # StringTools#camelize 'valhalla'
47
+ # #=> 'Valhalla'
48
+ #
49
+ # StringTools#camelize 'muspelheimr_and_niflheimr'
50
+ # #=> 'MuspelheimrAndNiflheimr'
46
51
  def camelize(str)
47
- str = require_string! str
52
+ str = require_string!(str)
48
53
 
49
54
  inflector.camelize(str)
50
55
  end
51
56
 
52
- # Performs multiple string tools operations in sequence, starting with the
53
- # given string and passing the result of each operation to the next.
57
+ # Performs a series of operations on the string.
58
+ #
59
+ # Use #chain to call each specified method in the chain in sequence, passing
60
+ # the output of each method to the next method.
61
+ #
62
+ # @param str [String] the string to process.
63
+ # @param commands [Array<String, Symbol>] the string operations to apply.
54
64
  #
55
- # @param str [String] The string to process.
56
- # @param commands [Array<String, Symbol>] The string operations to apply.
65
+ # @return [String] the processed string.
57
66
  #
58
- # @return [String] The processed string.
67
+ # @example
68
+ # # Equivalent to `StringTools.underscore(StringTools.pluralize str)`.
69
+ # StringTools#chain 'ArchivedPeriodical', :underscore, :pluralize
70
+ # # => 'archived_periodicals'
59
71
  def chain(str, *commands)
60
- str = require_string! str
72
+ str = require_string!(str)
61
73
 
62
74
  commands.reduce(str) { |memo, command| send(command, memo) }
63
75
  end
64
76
 
65
- # Adds the specified number of spaces to the start of each line of the
66
- # string. Defaults to 2 spaces.
77
+ # Adds the specified number of spaces to the start of each line.
67
78
  #
68
- # @param str [String] The string to indent.
69
- # @param count [Integer] The number of spaces to add.
79
+ # @param str [String] the string to indent.
80
+ # @param count [Integer] the number of spaces to add. Defaults to 2.
70
81
  #
71
- # @return [String] The indented string.
82
+ # @return [String] the indented string.
83
+ #
84
+ # @example
85
+ # string = 'The Hobbit'
86
+ # StringTools.indent(string)
87
+ # #=> ' The Hobbit'
88
+ #
89
+ # titles = [
90
+ # "The Fellowship of the Ring",
91
+ # "The Two Towers",
92
+ # "The Return of the King"
93
+ # ]
94
+ # string = titles.join "\n"
95
+ # StringTools.indent(string, 4)
96
+ # #=> " The Fellowship of the Ring\n"\
97
+ # " The Two Towers\n"\
98
+ # " The Return of the King"
72
99
  def indent(str, count = 2)
73
- str = require_string! str
100
+ str = require_string!(str)
74
101
  pre = ' ' * count
75
102
 
76
103
  map_lines(str) { |line| "#{pre}#{line}" }
77
104
  end
78
105
 
79
- # Yields each line of the string to the provided block and combines the
80
- # results into a new multiline string.
106
+ # Yields each line to the provided block and combines the results.
107
+ #
108
+ # The results of each line are combined back into a new multi-line string.
109
+ #
110
+ # @param str [String] the string to map.
81
111
  #
82
- # @param str [String] The string to map.
112
+ # @yieldparam line [String] the current line.
113
+ # @yieldparam index [Integer] the index of the current line.
83
114
  #
84
- # @yieldparam line [String] The current line.
85
- # @yieldparam index [Integer] The index of the current line.
115
+ # @yieldreturn [String] the modified line.
86
116
  #
87
- # @return [String] The mapped string.
117
+ # @return [String] the mapped and recombined string.
118
+ #
119
+ # @example
120
+ # string = 'The Hobbit'
121
+ # StringTools.map_lines(string) { |line| " #{line}" }
122
+ # #=> '- The Hobbit'
123
+ #
124
+ # titles = [
125
+ # "The Fellowship of the Ring",
126
+ # "The Two Towers",
127
+ # "The Return of the King"
128
+ # ]
129
+ # string = titles.join "\n"
130
+ # StringTools.map_lines(string) { |line, index| "#{index}. #{line}" }
131
+ # #=> "0. The Fellowship of the Ring\n"\
132
+ # "1. The Two Towers\n"\
133
+ # "2. The Return of the King"
88
134
  def map_lines(str)
89
- str = require_string! str
135
+ str = require_string!(str)
90
136
 
91
137
  str.each_line.with_index.reduce(+'') do |memo, (line, index)|
92
138
  memo << yield(line, index)
93
139
  end
94
140
  end
95
141
 
96
- # Determines whether or not the given word is in plural form. If calling
97
- # #pluralize(word) is equal to word, the word is considered plural.
142
+ # Determines whether or not the given word is in plural form.
143
+ #
144
+ # If calling #pluralize(word) is equal to word, the word is considered
145
+ # plural.
146
+ #
147
+ # @param word [String] the word to check.
148
+ #
149
+ # @return [Boolean] true if the word is in plural form, otherwise false.
150
+ #
151
+ # @example
152
+ # StringTools.plural? 'light'
153
+ # #=> false
154
+ #
155
+ # StringTools.plural? 'lights'
156
+ # #=> true
98
157
  #
99
- # @return [Boolean] True if the word is in plural form, otherwise false.
158
+ # @see #pluralize
100
159
  def plural?(word)
101
160
  word = require_string!(word)
102
161
 
@@ -104,22 +163,44 @@ module SleepingKingStudios::Tools
104
163
  end
105
164
 
106
165
  # @overload pluralize(str)
107
- # Takes a word in singular form and returns the plural form, based on the
108
- # defined rules and known irregular/uncountable words.
166
+ # Takes a word in singular form and returns the plural form.
109
167
  #
110
- # @param str [String] The word to pluralize.
168
+ # This method delegates to the configured inflector, which converts the
169
+ # given word based on the defined rules and known irregular/uncountable
170
+ # words.
111
171
  #
112
- # @return [String] The pluralized word.
172
+ # @param str [String] the word to pluralize.
173
+ #
174
+ # @return [String] the pluralized word.
175
+ #
176
+ # @example
177
+ # StringTools.pluralize 'light'
178
+ # #=> 'lights'
179
+ #
180
+ # @see SleepingKingStudios::Tools::Toolbox::Inflector#pluralize.
113
181
  def pluralize(*args)
114
- str = require_string! args.first
182
+ str = require_string!(args.first)
115
183
 
116
- inflector.pluralize str
184
+ inflector.pluralize(str)
117
185
  end
118
186
 
119
- # Determines whether or not the given word is in singular form. If calling
120
- # #singularize(word) is equal to word, the word is considered singular.
187
+ # Determines whether or not the given word is in singular form.
188
+ #
189
+ # If calling #singularize(word) is equal to word, the word is considered
190
+ # singular.
191
+ #
192
+ # @param word [String] the word to check.
193
+ #
194
+ # @return [Boolean] true if the word is in singular form, otherwise false.
195
+ #
196
+ # @see #singularize
121
197
  #
122
- # @return [Boolean] True if the word is in singular form, otherwise false.
198
+ # @example
199
+ # StringTools.singular? 'light'
200
+ # #=> true
201
+ #
202
+ # StringTools.singular? 'lights'
203
+ # #=> false
123
204
  def singular?(word)
124
205
  word = require_string!(word)
125
206
 
@@ -128,34 +209,60 @@ module SleepingKingStudios::Tools
128
209
 
129
210
  # Transforms the word to a singular, lowercase form.
130
211
  #
131
- # @param str [String] The word to transform.
212
+ # This method delegates to the configured inflector, which converts the
213
+ # given word based on the defined rules and known irregular/uncountable
214
+ # words.
215
+ #
216
+ # @param str [String] the word to transform.
217
+ #
218
+ # @return [String] the word in singular form.
219
+ #
220
+ # @see SleepingKingStudios::Tools::Toolbox::Inflector#singularize.
132
221
  #
133
- # @return [String] The word in singular form.
222
+ # @example
223
+ # StringTools.singularize 'lights'
224
+ # #=> 'light'
134
225
  def singularize(str)
135
- require_string! str
226
+ require_string!(str)
136
227
 
137
- inflector.singularize str
228
+ inflector.singularize(str)
138
229
  end
139
230
 
140
231
  # Returns true if the object is a String.
141
232
  #
142
- # @param str [Object] The object to test.
233
+ # @param str [Object] the object to test.
143
234
  #
144
- # @return [Boolean] True if the object is a String, otherwise false.
235
+ # @return [Boolean] true if the object is a String, otherwise false.
236
+ #
237
+ # @example
238
+ # StringTools.string?(nil)
239
+ # #=> false
240
+ # StringTools.string?([])
241
+ # #=> false
242
+ # StringTools.string?('Greetings, programs!')
243
+ # #=> true
244
+ # StringTools.string?(:greetings_starfighter)
245
+ # #=> false
145
246
  def string?(str)
146
247
  str.is_a?(String)
147
248
  end
148
249
 
149
- # Converts a mixed-case string expression to a lowercase, underscore
150
- # separated string.
250
+ # Converts a mixed-case string to a lowercase, underscore separated string.
251
+ #
252
+ # @param str [String] the string to convert.
253
+ #
254
+ # @return [String] the converted string.
151
255
  #
152
- # @param str [String] The string to convert.
256
+ # @see SleepingKingStudios::Tools::Toolbox::Inflector#underscore.
153
257
  #
154
- # @return [String] The converted string.
258
+ # @example
259
+ # StringTools#underscore 'Bifrost'
260
+ # #=> 'bifrost'
155
261
  #
156
- # @see ActiveSupport::Inflector#underscore.
262
+ # StringTools#underscore 'FenrisWolf'
263
+ # #=> 'fenris_wolf'
157
264
  def underscore(str)
158
- str = require_string! str
265
+ str = require_string!(str)
159
266
 
160
267
  inflector.underscore(str)
161
268
  end