sleeping_king_studios-tools 1.1.1 → 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,21 +23,30 @@ 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 proc
33
+ # @param proc [Proc] the proc or lambda to call.
34
+ # @param args [Array] optional. Additional arguments to pass in to the proc
33
35
  # or lambda.
34
- # @param [Hash] kwargs Optional. Additional keywords to pass in to the proc
36
+ # @param kwargs [Hash] optional. Additional keywords to pass in to the proc
35
37
  # or lambda.
36
- # @param [block] block Optional. If present, will be passed in to proc or
38
+ # @param block [block] optional. If present, will be passed in to proc or
37
39
  # lambda.
38
40
  #
39
- # @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
40
42
  # receiver and any additional arguments or block.
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.
41
50
  def apply(receiver, proc, *args, **kwargs, &block)
42
51
  return receiver.instance_exec(*args, **kwargs, &proc) unless block_given?
43
52
 
@@ -49,14 +58,50 @@ module SleepingKingStudios::Tools
49
58
  end
50
59
  end
51
60
 
52
- # Creates a deep copy of the object. If the object is an Array, returns a
53
- # new Array with deep copies of each array item. If the object is a Hash,
54
- # returns a new Hash with deep copies of each hash key and value. Otherwise,
55
- # 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.
56
70
  #
57
- # @param [Object] obj The object to copy.
71
+ # @see ArrayTools#deep_copy
58
72
  #
59
- # @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' }
60
105
  def deep_dup(obj)
61
106
  case obj
62
107
  when FalseClass, Integer, Float, NilClass, Symbol, TrueClass
@@ -70,12 +115,46 @@ module SleepingKingStudios::Tools
70
115
  end
71
116
  end
72
117
 
73
- # Performs a deep freeze of the object. If the object is an Array, freezes
74
- # the array and performs a deep freeze on each array item. If the object is
75
- # a hash, freezes the hash and performs a deep freeze on each hash key and
76
- # 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.
77
123
  #
78
- # @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
79
158
  def deep_freeze(obj)
80
159
  case obj
81
160
  when FalseClass, Integer, Float, NilClass, Symbol, TrueClass
@@ -89,96 +168,160 @@ module SleepingKingStudios::Tools
89
168
  end
90
169
  end
91
170
 
92
- # Accesses deeply nested attributes by calling the first named method on the
93
- # given object, and each subsequent method on the result of the previous
94
- # method call. If the object does not respond to the method name, nil is
95
- # 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.
96
180
  #
97
- # @param [Object] object The object to dig.
98
- # @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.
99
183
  #
100
- # @return [Object] The result of the last method call, or nil if the last
101
- # object does not respond to the last method.
102
- def dig(object, *method_names)
103
- 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|
104
189
  memo.respond_to?(method_name) ? memo.send(method_name) : nil
105
190
  end
106
191
  end
107
192
 
108
- # @!method metaclass(object)
109
- # Returns the object's singleton class.
110
- #
111
- # @param [Object] object The object for which an eigenclass is required.
112
- #
113
- # @return [Class] The object's eigenclass.
114
-
115
193
  # Returns the object's eigenclass.
116
194
  #
117
- # @param [Object] object The object for which an eigenclass is required.
195
+ # @param obj [Object] the object for which an eigenclass is required.
118
196
  #
119
- # @return [Class] The object's singleton class.
120
- def eigenclass(object)
121
- object.singleton_class
197
+ # @return [Class] the object's singleton class.
198
+ def eigenclass(obj)
199
+ obj.singleton_class
122
200
  end
123
201
  alias metaclass eigenclass
124
202
 
125
- # Returns true if the object is immutable. Values of nil, false, and true
126
- # are always immutable, as are instances of Numeric and Symbol. Arrays are
127
- # immutable if the array is frozen and each array item is immutable. Hashes
128
- # are immutable if the hash is frozen and each hash key and hash value are
129
- # 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.
130
216
  #
131
- # @param obj [Object] The object to test.
217
+ # @return [Boolean] true if the object is immutable, otherwise false.
132
218
  #
133
- # @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?
134
249
  def immutable?(obj)
135
250
  case obj
136
251
  when NilClass, FalseClass, TrueClass, Numeric, Symbol
137
252
  true
138
253
  when ->(_) { ArrayTools.array?(obj) }
139
- ArrayTools.immutable? obj
254
+ ArrayTools.immutable?(obj)
140
255
  when ->(_) { HashTools.hash?(obj) }
141
- HashTools.immutable? obj
256
+ HashTools.immutable?(obj)
142
257
  else
143
258
  obj.frozen?
144
259
  end
145
260
  end
146
261
 
147
- # Returns true if the object is mutable.
262
+ # Checks if the object is mutable.
148
263
  #
149
- # @param obj [Object] The object to test.
264
+ # @param obj [Object] the object to test.
150
265
  #
151
- # @return [Boolean] True if the object is mutable, otherwise false.
266
+ # @return [Boolean] true if the object is mutable, otherwise false.
152
267
  #
153
268
  # @see #immutable?
154
269
  def mutable?(obj)
155
270
  !immutable?(obj)
156
271
  end
157
272
 
158
- # Returns true if the object is an Object. This should return true only for
159
- # objects that have an alternate inheritance chain from BasicObject, such as
160
- # a Proxy.
273
+ # Returns true if the object is an Object.
161
274
  #
162
- # @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.
163
277
  #
164
- # @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
165
297
  def object?(obj)
166
298
  Object.instance_method(:is_a?).bind(obj).call(Object)
167
299
  end
168
300
 
169
301
  # As #send, but returns nil if the object does not respond to the method.
170
302
  #
171
- # @param [Object] object The receiver of the message.
172
- # @param [String, Symbol] method_name The name of the method to call.
173
- # @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.
174
312
  #
175
- # @see ActiveSupport::CoreExt::Object#try.
176
- def try(object, method_name, *args)
177
- 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)
178
321
 
179
- return nil unless object.respond_to?(method_name)
322
+ return nil unless obj.respond_to?(method_name)
180
323
 
181
- object.send method_name, *args
324
+ obj.send(method_name, *args)
182
325
  end
183
326
 
184
327
  private
@@ -193,6 +336,3 @@ module SleepingKingStudios::Tools
193
336
  end
194
337
  end
195
338
  end
196
-
197
- require 'sleeping_king_studios/tools/array_tools'
198
- 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