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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +36 -0
- data/README.md +9 -1178
- data/lib/sleeping_king_studios/tools/array_tools.rb +166 -87
- data/lib/sleeping_king_studios/tools/assertions.rb +886 -156
- data/lib/sleeping_king_studios/tools/core_tools.rb +47 -13
- data/lib/sleeping_king_studios/tools/hash_tools.rb +137 -35
- data/lib/sleeping_king_studios/tools/integer_tools.rb +56 -40
- data/lib/sleeping_king_studios/tools/object_tools.rb +213 -71
- data/lib/sleeping_king_studios/tools/string_tools.rb +161 -54
- data/lib/sleeping_king_studios/tools/toolbelt.rb +47 -14
- data/lib/sleeping_king_studios/tools/toolbox/constant_map.rb +29 -10
- data/lib/sleeping_king_studios/tools/toolbox/inflector/rules.rb +23 -24
- data/lib/sleeping_king_studios/tools/toolbox/inflector.rb +35 -25
- data/lib/sleeping_king_studios/tools/toolbox/mixin.rb +83 -11
- data/lib/sleeping_king_studios/tools/toolbox/semantic_version.rb +25 -15
- data/lib/sleeping_king_studios/tools/toolbox/subclass.rb +4 -4
- data/lib/sleeping_king_studios/tools/toolbox.rb +1 -3
- data/lib/sleeping_king_studios/tools/version.rb +3 -3
- metadata +6 -136
- data/DEVELOPMENT.md +0 -17
@@ -23,38 +23,85 @@ module SleepingKingStudios::Tools
|
|
23
23
|
:try
|
24
24
|
end
|
25
25
|
|
26
|
-
#
|
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
|
-
#
|
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]
|
32
|
-
# @param [Array]
|
33
|
-
#
|
34
|
-
# @param [
|
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
|
41
|
+
# @return the result of calling the proc or lambda with the given
|
38
42
|
# receiver and any additional arguments or block.
|
39
|
-
|
40
|
-
|
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.
|
51
|
-
#
|
52
|
-
# returns a new
|
53
|
-
# returns
|
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
|
-
# @
|
71
|
+
# @see ArrayTools#deep_copy
|
56
72
|
#
|
57
|
-
# @
|
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.
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
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]
|
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
|
91
|
-
#
|
92
|
-
# method
|
93
|
-
#
|
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
|
-
# @
|
96
|
-
#
|
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
|
-
# @
|
99
|
-
#
|
100
|
-
|
101
|
-
|
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]
|
195
|
+
# @param obj [Object] the object for which an eigenclass is required.
|
116
196
|
#
|
117
|
-
# @return [Class]
|
118
|
-
def eigenclass(
|
119
|
-
|
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
|
-
#
|
124
|
-
#
|
125
|
-
#
|
126
|
-
#
|
127
|
-
#
|
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
|
-
# @
|
217
|
+
# @return [Boolean] true if the object is immutable, otherwise false.
|
130
218
|
#
|
131
|
-
# @
|
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?
|
254
|
+
ArrayTools.immutable?(obj)
|
138
255
|
when ->(_) { HashTools.hash?(obj) }
|
139
|
-
HashTools.immutable?
|
256
|
+
HashTools.immutable?(obj)
|
140
257
|
else
|
141
258
|
obj.frozen?
|
142
259
|
end
|
143
260
|
end
|
144
261
|
|
145
|
-
#
|
262
|
+
# Checks if the object is mutable.
|
146
263
|
#
|
147
|
-
# @param obj [Object]
|
264
|
+
# @param obj [Object] the object to test.
|
148
265
|
#
|
149
|
-
# @return [Boolean]
|
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.
|
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
|
-
#
|
275
|
+
# This should return false only for objects that have an alternate
|
276
|
+
# inheritance chain from BasicObject, such as a Proxy.
|
161
277
|
#
|
162
|
-
# @
|
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
|
-
#
|
170
|
-
#
|
171
|
-
#
|
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
|
-
# @
|
174
|
-
|
175
|
-
|
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
|
322
|
+
return nil unless obj.respond_to?(method_name)
|
178
323
|
|
179
|
-
|
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]
|
28
|
-
#
|
29
|
-
#
|
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]
|
39
|
+
# @param str [String] the string to convert.
|
42
40
|
#
|
43
|
-
# @return [String]
|
41
|
+
# @return [String] the converted string.
|
44
42
|
#
|
45
|
-
# @see
|
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!
|
52
|
+
str = require_string!(str)
|
48
53
|
|
49
54
|
inflector.camelize(str)
|
50
55
|
end
|
51
56
|
|
52
|
-
# Performs
|
53
|
-
#
|
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
|
-
# @
|
56
|
-
# @param commands [Array<String, Symbol>] The string operations to apply.
|
65
|
+
# @return [String] the processed string.
|
57
66
|
#
|
58
|
-
# @
|
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!
|
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
|
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]
|
69
|
-
# @param count [Integer]
|
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]
|
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!
|
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
|
80
|
-
#
|
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
|
-
# @
|
112
|
+
# @yieldparam line [String] the current line.
|
113
|
+
# @yieldparam index [Integer] the index of the current line.
|
83
114
|
#
|
84
|
-
# @
|
85
|
-
# @yieldparam index [Integer] The index of the current line.
|
115
|
+
# @yieldreturn [String] the modified line.
|
86
116
|
#
|
87
|
-
# @return [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!
|
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.
|
97
|
-
#
|
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
|
-
# @
|
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
|
108
|
-
# defined rules and known irregular/uncountable words.
|
166
|
+
# Takes a word in singular form and returns the plural form.
|
109
167
|
#
|
110
|
-
#
|
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
|
-
# @
|
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!
|
182
|
+
str = require_string!(args.first)
|
115
183
|
|
116
|
-
inflector.pluralize
|
184
|
+
inflector.pluralize(str)
|
117
185
|
end
|
118
186
|
|
119
|
-
# Determines whether or not the given word is in singular form.
|
120
|
-
#
|
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
|
-
# @
|
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
|
-
#
|
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
|
-
# @
|
222
|
+
# @example
|
223
|
+
# StringTools.singularize 'lights'
|
224
|
+
# #=> 'light'
|
134
225
|
def singularize(str)
|
135
|
-
require_string!
|
226
|
+
require_string!(str)
|
136
227
|
|
137
|
-
inflector.singularize
|
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]
|
233
|
+
# @param str [Object] the object to test.
|
143
234
|
#
|
144
|
-
# @return [Boolean]
|
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
|
150
|
-
#
|
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
|
-
# @
|
256
|
+
# @see SleepingKingStudios::Tools::Toolbox::Inflector#underscore.
|
153
257
|
#
|
154
|
-
# @
|
258
|
+
# @example
|
259
|
+
# StringTools#underscore 'Bifrost'
|
260
|
+
# #=> 'bifrost'
|
155
261
|
#
|
156
|
-
#
|
262
|
+
# StringTools#underscore 'FenrisWolf'
|
263
|
+
# #=> 'fenris_wolf'
|
157
264
|
def underscore(str)
|
158
|
-
str = require_string!
|
265
|
+
str = require_string!(str)
|
159
266
|
|
160
267
|
inflector.underscore(str)
|
161
268
|
end
|