sleeping_king_studios-tools 0.7.0 → 1.0.2

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.
Files changed (29) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +54 -3
  3. data/CODE_OF_CONDUCT.md +132 -0
  4. data/DEVELOPMENT.md +7 -16
  5. data/LICENSE +1 -1
  6. data/README.md +71 -145
  7. data/lib/sleeping_king_studios/tools.rb +12 -6
  8. data/lib/sleeping_king_studios/tools/array_tools.rb +86 -58
  9. data/lib/sleeping_king_studios/tools/base.rb +20 -0
  10. data/lib/sleeping_king_studios/tools/core_tools.rb +78 -19
  11. data/lib/sleeping_king_studios/tools/hash_tools.rb +69 -42
  12. data/lib/sleeping_king_studios/tools/integer_tools.rb +97 -55
  13. data/lib/sleeping_king_studios/tools/object_tools.rb +75 -52
  14. data/lib/sleeping_king_studios/tools/string_tools.rb +69 -96
  15. data/lib/sleeping_king_studios/tools/toolbelt.rb +44 -23
  16. data/lib/sleeping_king_studios/tools/toolbox.rb +2 -2
  17. data/lib/sleeping_king_studios/tools/toolbox/constant_map.rb +75 -74
  18. data/lib/sleeping_king_studios/tools/toolbox/inflector.rb +124 -0
  19. data/lib/sleeping_king_studios/tools/toolbox/inflector/rules.rb +173 -0
  20. data/lib/sleeping_king_studios/tools/toolbox/mixin.rb +11 -11
  21. data/lib/sleeping_king_studios/tools/toolbox/semantic_version.rb +15 -14
  22. data/lib/sleeping_king_studios/tools/version.rb +14 -10
  23. metadata +106 -35
  24. data/lib/sleeping_king_studios/tools/all.rb +0 -5
  25. data/lib/sleeping_king_studios/tools/enumerable_tools.rb +0 -8
  26. data/lib/sleeping_king_studios/tools/semantic_version.rb +0 -15
  27. data/lib/sleeping_king_studios/tools/string_tools/plural_inflector.rb +0 -185
  28. data/lib/sleeping_king_studios/tools/toolbox/configuration.rb +0 -207
  29. data/lib/sleeping_king_studios/tools/toolbox/delegator.rb +0 -175
@@ -1,19 +1,63 @@
1
- # lib/sleeping_king_studios/tools/integer_tools.rb
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'sleeping_king_studios/tools'
4
- require 'sleeping_king_studios/tools/string_tools'
5
4
 
6
5
  module SleepingKingStudios::Tools
7
6
  # Tools for working with integers.
8
- module IntegerTools
9
- extend self
10
-
7
+ class IntegerTools < SleepingKingStudios::Tools::Base
11
8
  # Minimum integer value that can be converted to a roman numeral.
12
9
  ROMANIZE_MIN = 1
13
10
 
14
11
  # Maximum integer value that can be converted to a roman numeral.
15
12
  ROMANIZE_MAX = 4999
16
13
 
14
+ ROMANIZE_NUMERALS = [
15
+ %w[I V X].freeze,
16
+ %w[X L C].freeze,
17
+ %w[C D M].freeze,
18
+ ['M', 'MMM', ''].freeze
19
+ ].freeze
20
+ private_constant :ROMANIZE_NUMERALS
21
+
22
+ ROMANIZE_RULES = [
23
+ '',
24
+ '1',
25
+ '11',
26
+ '111',
27
+ '15',
28
+ '5',
29
+ '51',
30
+ '511',
31
+ '5111',
32
+ '1a',
33
+ 'a'
34
+ ].freeze
35
+ private_constant :ROMANIZE_RULES
36
+
37
+ ROMANIZE_RULES_ADDITIVE = [
38
+ '',
39
+ '1',
40
+ '11',
41
+ '111',
42
+ '1111',
43
+ '5',
44
+ '51',
45
+ '511',
46
+ '5111',
47
+ '51111',
48
+ 'a'
49
+ ].freeze
50
+ private_constant :ROMANIZE_RULES_ADDITIVE
51
+
52
+ class << self
53
+ def_delegators :instance,
54
+ :count_digits,
55
+ :digits,
56
+ :integer?,
57
+ :pluralize,
58
+ :romanize
59
+ end
60
+
17
61
  # Returns the number of digits in the given integer when represented in the
18
62
  # specified base. Ignores minus sign for negative numbers.
19
63
  #
@@ -38,9 +82,9 @@ module SleepingKingStudios::Tools
38
82
  # Defaults to 10.
39
83
  #
40
84
  # @return [Integer] The number of digits.
41
- def count_digits integer, base: 10
42
- digits(integer.abs, :base => base).count
43
- end # method count_digits
85
+ def count_digits(integer, base: 10)
86
+ digits(integer.abs, base: base).count
87
+ end
44
88
 
45
89
  # Decomposes the given integer into its digits when represented in the
46
90
  # given base.
@@ -63,18 +107,18 @@ module SleepingKingStudios::Tools
63
107
  #
64
108
  # @return [Array<String>] The digits of the decomposed integer,
65
109
  # represented as a bigendian array of strings.
66
- def digits integer, base: 10
110
+ def digits(integer, base: 10)
67
111
  integer.to_s(base).split('')
68
- end # method digits
112
+ end
69
113
 
70
114
  # Returns true if the object is an Integer.
71
115
  #
72
116
  # @param int [Object] The object to test.
73
117
  #
74
118
  # @return [Boolean] True if the object is an Integer, otherwise false.
75
- def integer? int
76
- Integer === int
77
- end # method integer?
119
+ def integer?(int)
120
+ int.is_a?(Integer)
121
+ end
78
122
 
79
123
  # Returns the singular or the plural value, depending on the provided
80
124
  # item count.
@@ -89,11 +133,11 @@ module SleepingKingStudios::Tools
89
133
  #
90
134
  # @return [String] The single form if count == 1; otherwise the plural
91
135
  # form.
92
- def pluralize count, single, plural = nil
136
+ def pluralize(count, single, plural = nil)
93
137
  plural ||= StringTools.pluralize(single)
94
138
 
95
- 1 == count ? single : plural
96
- end # method pluralize
139
+ count == 1 ? single : plural
140
+ end
97
141
 
98
142
  # Represents an integer between 1 and 4999 (inclusive) as a Roman numeral.
99
143
  #
@@ -114,42 +158,40 @@ module SleepingKingStudios::Tools
114
158
  # @return [String] The representation of the integer as a Roman numeral.
115
159
  #
116
160
  # @raise [RangeError] If the integer is less than 1 or greater than 4999.
117
- def romanize integer, additive: false
118
- # Validate input value.
119
- unless (ROMANIZE_MIN..ROMANIZE_MAX).include? integer
120
- raise RangeError.new "integer to romanize must be within range #{ROMANIZE_MIN} to #{ROMANIZE_MAX}"
121
- end # unless
122
-
123
- # Define conversion rules.
124
- rules = [
125
- '',
126
- '%one',
127
- '%one%one',
128
- '%one%one%one',
129
- additive ? '%one%one%one%one' : '%one%five',
130
- '%five',
131
- '%five%one',
132
- '%five%one%one',
133
- '%five%one%one%one',
134
- additive ? '%five%one%one%one%one' : '%one%ten',
135
- '%ten'
136
- ] # end array
137
-
138
- # Define numeral values.
139
- numerals = [
140
- %w(I V X),
141
- %w(X L C),
142
- %w(C D M),
143
- ['M', 'MMM', '']
144
- ] # end array numerals
145
-
146
- # Generate string representation.
147
- digits(integer).reverse.map.with_index do |digit, index|
148
- rules[digit.to_i]
149
- .gsub('%one', numerals[index][0])
150
- .gsub('%five', numerals[index][1])
151
- .gsub('%ten', numerals[index][2])
152
- end.reverse.join ''
153
- end # method romanize
154
- end # module
155
- end # module
161
+ def romanize(integer, additive: false)
162
+ check_romanize_range(integer)
163
+
164
+ digits(integer)
165
+ .reverse
166
+ .map
167
+ .with_index do |digit, index|
168
+ romanize_digit(additive: additive, digit: digit.to_i, tens: index)
169
+ end
170
+ .reverse
171
+ .join
172
+ end
173
+
174
+ private
175
+
176
+ def check_romanize_range(integer)
177
+ return if (ROMANIZE_MIN..ROMANIZE_MAX).include?(integer)
178
+
179
+ error_message =
180
+ "integer to romanize must be within range #{ROMANIZE_MIN} to" \
181
+ " #{ROMANIZE_MAX}"
182
+
183
+ raise RangeError, error_message, caller(1..-1)
184
+ end
185
+
186
+ def romanize_digit(additive:, digit:, tens:)
187
+ rules = (additive ? ROMANIZE_RULES_ADDITIVE : ROMANIZE_RULES)
188
+ rule = rules[digit]
189
+ numerals = ROMANIZE_NUMERALS[tens]
190
+
191
+ rule
192
+ .gsub('1', numerals[0])
193
+ .gsub('5', numerals[1])
194
+ .gsub('a', numerals[2])
195
+ end
196
+ end
197
+ end
@@ -1,16 +1,32 @@
1
- # lib/sleeping_king_studios/tools/object_tools.rb
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'sleeping_king_studios/tools'
4
4
 
5
5
  module SleepingKingStudios::Tools
6
6
  # Low-level tools for working with objects.
7
- module ObjectTools
8
- extend self
7
+ class ObjectTools < SleepingKingStudios::Tools::Base
8
+ TEMPORARY_METHOD_NAME =
9
+ '__sleeping_king_studios_tools_apply_%i__'
10
+ private_constant :TEMPORARY_METHOD_NAME
11
+
12
+ class << self
13
+ def_delegators :instance,
14
+ :apply,
15
+ :deep_dup,
16
+ :deep_freeze,
17
+ :dig,
18
+ :eigenclass,
19
+ :immutable?,
20
+ :metaclass,
21
+ :mutable?,
22
+ :object?,
23
+ :try
24
+ end
9
25
 
10
26
  # Takes a proc or lambda and invokes it with the given object as
11
27
  # receiver, with any additional arguments or block provided.
12
28
  #
13
- # @param [Object] base The receiver. The proc will be called in the
29
+ # @param [Object] receiver The receiver. The proc will be called in the
14
30
  # context of this object.
15
31
  # @param [Proc] proc The proc or lambda to call.
16
32
  # @param [Array] args Optional. Additional arguments to pass in to the
@@ -20,20 +36,16 @@ module SleepingKingStudios::Tools
20
36
  #
21
37
  # @return The result of calling the proc or lambda with the given
22
38
  # receiver and any additional arguments or block.
23
- def apply base, proc, *args, &block
24
- return base.instance_exec *args, &proc unless block_given?
39
+ def apply(receiver, proc, *args, &block)
40
+ return receiver.instance_exec(*args, &proc) unless block_given?
25
41
 
26
- temporary_method_name = :__sleeping_king_studios_tools_object_tools_temporary_method_for_applying_proc__
42
+ method_name =
43
+ Kernel.format(TEMPORARY_METHOD_NAME, Thread.current.object_id)
27
44
 
28
- metaclass = class << base; self; end
29
- metaclass.send :define_method, temporary_method_name, &proc
30
-
31
- begin
32
- base.send temporary_method_name, *args, &block
33
- ensure
34
- metaclass.send :remove_method, temporary_method_name if temporary_method_name && defined?(temporary_method_name)
45
+ with_temporary_method(receiver, method_name, proc) do
46
+ receiver.send(method_name, *args, &block)
35
47
  end
36
- end # method apply
48
+ end
37
49
 
38
50
  # Creates a deep copy of the object. If the object is an Array, returns a
39
51
  # new Array with deep copies of each array item. If the object is a Hash,
@@ -43,7 +55,7 @@ module SleepingKingStudios::Tools
43
55
  # @param [Object] obj The object to copy.
44
56
  #
45
57
  # @return The copy of the object.
46
- def deep_dup obj
58
+ def deep_dup(obj)
47
59
  case obj
48
60
  when FalseClass, Integer, Float, NilClass, Symbol, TrueClass
49
61
  obj
@@ -53,8 +65,8 @@ module SleepingKingStudios::Tools
53
65
  HashTools.deep_dup obj
54
66
  else
55
67
  obj.respond_to?(:deep_dup) ? obj.deep_dup : obj.dup
56
- end # case
57
- end # method deep_dup
68
+ end
69
+ end
58
70
 
59
71
  # Performs a deep freeze of the object. If the object is an Array, freezes
60
72
  # the array and performs a deep freeze on each array item. If the object is
@@ -62,7 +74,7 @@ module SleepingKingStudios::Tools
62
74
  # value. Otherwise, calls Object#freeze.
63
75
  #
64
76
  # @param [Object] obj The object to freeze.
65
- def deep_freeze obj
77
+ def deep_freeze(obj)
66
78
  case obj
67
79
  when FalseClass, Integer, Float, NilClass, Symbol, TrueClass
68
80
  # Object is inherently immutable; do nothing here.
@@ -72,34 +84,41 @@ module SleepingKingStudios::Tools
72
84
  HashTools.deep_freeze obj
73
85
  else
74
86
  obj.respond_to?(:deep_freeze) ? obj.deep_freeze : obj.freeze
75
- end # case
76
- end # method deep_freeze
87
+ end
88
+ end
77
89
 
78
90
  # Accesses deeply nested attributes by calling the first named method on the
79
91
  # given object, and each subsequent method on the result of the previous
80
92
  # method call. If the object does not respond to the method name, nil is
81
93
  # returned instead of calling the method.
82
94
  #
83
- # @param [Object] obj The object to dig.
95
+ # @param [Object] object The object to dig.
84
96
  # @param [Array] method_names The names of the methods to call.
85
97
  #
86
98
  # @return [Object] The result of the last method call, or nil if the last
87
99
  # object does not respond to the last method.
88
- def dig object, *method_names
100
+ def dig(object, *method_names)
89
101
  method_names.reduce(object) do |memo, method_name|
90
102
  memo.respond_to?(method_name) ? memo.send(method_name) : nil
91
- end # reduce
92
- end # method object
103
+ end
104
+ end
105
+
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.
93
112
 
94
113
  # Returns the object's eigenclass.
95
114
  #
96
115
  # @param [Object] object The object for which an eigenclass is required.
97
116
  #
98
- # @return [Class] The object's eigenclass.
99
- def eigenclass object
100
- class << object; self; end
101
- end # method eigenclass
102
- alias_method :metaclass, :eigenclass
117
+ # @return [Class] The object's singleton class.
118
+ def eigenclass(object)
119
+ object.singleton_class
120
+ end
121
+ alias metaclass eigenclass
103
122
 
104
123
  # Returns true if the object is immutable. Values of nil, false, and true
105
124
  # are always immutable, as are instances of Numeric and Symbol. Arrays are
@@ -110,7 +129,7 @@ module SleepingKingStudios::Tools
110
129
  # @param obj [Object] The object to test.
111
130
  #
112
131
  # @return [Boolean] True if the object is immutable, otherwise false.
113
- def immutable? obj
132
+ def immutable?(obj)
114
133
  case obj
115
134
  when NilClass, FalseClass, TrueClass, Numeric, Symbol
116
135
  true
@@ -120,8 +139,8 @@ module SleepingKingStudios::Tools
120
139
  HashTools.immutable? obj
121
140
  else
122
141
  obj.frozen?
123
- end # case
124
- end # method immutable?
142
+ end
143
+ end
125
144
 
126
145
  # Returns true if the object is mutable.
127
146
  #
@@ -130,9 +149,9 @@ module SleepingKingStudios::Tools
130
149
  # @return [Boolean] True if the object is mutable, otherwise false.
131
150
  #
132
151
  # @see #immutable?
133
- def mutable? obj
152
+ def mutable?(obj)
134
153
  !immutable?(obj)
135
- end # method mutable?
154
+ end
136
155
 
137
156
  # Returns true if the object is an Object. This should return true only for
138
157
  # objects that have an alternate inheritance chain from BasicObject, such as
@@ -141,9 +160,9 @@ module SleepingKingStudios::Tools
141
160
  # @param obj [Object] The object to test.
142
161
  #
143
162
  # @return [Boolean] True if the object is an Object, otherwise false.
144
- def object? obj
145
- Object === obj
146
- end # method object?
163
+ def object?(obj)
164
+ Object.instance_method(:is_a?).bind(obj).call(Object)
165
+ end
147
166
 
148
167
  # As #send, but returns nil if the object does not respond to the method.
149
168
  #
@@ -151,23 +170,27 @@ module SleepingKingStudios::Tools
151
170
  # @param [String, Symbol] method_name The name of the method to call.
152
171
  # @param [Array] args The arguments to the message.
153
172
  #
154
- # @see active_support/core_ext/object/try.rb
155
- def try object, method_name, *args
156
- if object.nil?
157
- return object.respond_to?(method_name) ?
158
- object.send(method_name, *args) :
159
- nil
160
- end # if
161
-
162
- # Delegate to ActiveSupport::CoreExt::Object#try.
173
+ # @see ActiveSupport::CoreExt::Object#try.
174
+ def try(object, method_name, *args)
163
175
  return object.try(method_name, *args) if object.respond_to?(:try)
164
176
 
177
+ return nil unless object.respond_to?(method_name)
178
+
165
179
  object.send method_name, *args
166
- rescue NoMethodError => exception
167
- nil
168
- end # method try
169
- end # module
170
- end # module
180
+ end
181
+
182
+ private
183
+
184
+ def with_temporary_method(receiver, method_name, proc)
185
+ metaclass = class << receiver; self; end
186
+ metaclass.send :define_method, method_name, &proc
187
+
188
+ yield
189
+ ensure
190
+ metaclass.send :remove_method, method_name
191
+ end
192
+ end
193
+ end
171
194
 
172
195
  require 'sleeping_king_studios/tools/array_tools'
173
196
  require 'sleeping_king_studios/tools/hash_tools'
@@ -1,14 +1,40 @@
1
- # lib/sleeping_king_studios/tools/string_tools.rb
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'sleeping_king_studios/tools'
4
- require 'sleeping_king_studios/tools/object_tools'
4
+ require 'sleeping_king_studios/tools/toolbox/inflector'
5
5
 
6
6
  module SleepingKingStudios::Tools
7
7
  # Tools for working with strings.
8
- module StringTools
9
- extend self
10
-
11
- autoload :PluralInflector, 'sleeping_king_studios/tools/string_tools/plural_inflector'
8
+ class StringTools < SleepingKingStudios::Tools::Base
9
+ class << self
10
+ def_delegators :instance,
11
+ :camelize,
12
+ :chain,
13
+ :define_irregular_word,
14
+ :define_plural_rule,
15
+ :define_singular_rule,
16
+ :define_uncountable_word,
17
+ :indent,
18
+ :map_lines,
19
+ :plural?,
20
+ :pluralize,
21
+ :singular?,
22
+ :singularize,
23
+ :string?,
24
+ :underscore
25
+ end
26
+
27
+ # @param inflector [Object] An object that conforms to the interface used
28
+ # by SleepingKingStudios::Tools::Toolbox::Inflector, such as
29
+ # ActiveSupport::Inflector .
30
+ def initialize(inflector: nil)
31
+ super()
32
+
33
+ @inflector =
34
+ inflector || SleepingKingStudios::Tools::Toolbox::Inflector.new
35
+ end
36
+
37
+ attr_reader :inflector
12
38
 
13
39
  # Converts a lowercase, underscore-separated string to CamelCase.
14
40
  #
@@ -17,13 +43,11 @@ module SleepingKingStudios::Tools
17
43
  # @return [String] The converted string.
18
44
  #
19
45
  # @see ActiveSupport::Inflector#camelize.
20
- def camelize str
46
+ def camelize(str)
21
47
  str = require_string! str
22
48
 
23
- str = str.dup
24
- str.gsub!(/(\b|[_-])([a-z])/) { |match| $2.upcase }
25
- str
26
- end # method camelize
49
+ inflector.camelize(str)
50
+ end
27
51
 
28
52
  # Performs multiple string tools operations in sequence, starting with the
29
53
  # given string and passing the result of each operation to the next.
@@ -32,31 +56,11 @@ module SleepingKingStudios::Tools
32
56
  # @param commands [Array<String, Symbol>] The string operations to apply.
33
57
  #
34
58
  # @return [String] The processed string.
35
- def chain str, *commands
59
+ def chain(str, *commands)
36
60
  str = require_string! str
37
61
 
38
62
  commands.reduce(str) { |memo, command| send(command, memo) }
39
- end # method chain
40
-
41
- # (see PluralInflector#define_irregular_word)
42
- def define_irregular_word singular, plural
43
- plural_inflector.define_irregular_word singular, plural
44
- end # method define_irregular_word
45
-
46
- # (see PluralInflector#define_plural_rule)
47
- def define_plural_rule match, replace
48
- plural_inflector.define_plural_rule match, replace
49
- end # method define_plural_rule
50
-
51
- # (see PluralInflector#define_singular_rule)
52
- def define_singular_rule match, replace
53
- plural_inflector.define_singular_rule match, replace
54
- end # method define_singular_rule
55
-
56
- # (see PluralInflector#define_uncountable_word)
57
- def define_uncountable_word word
58
- plural_inflector.define_uncountable_word word
59
- end # method define_uncountable_word
63
+ end
60
64
 
61
65
  # Adds the specified number of spaces to the start of each line of the
62
66
  # string. Defaults to 2 spaces.
@@ -65,12 +69,12 @@ module SleepingKingStudios::Tools
65
69
  # @param count [Integer] The number of spaces to add.
66
70
  #
67
71
  # @return [String] The indented string.
68
- def indent str, count = 2
72
+ def indent(str, count = 2)
69
73
  str = require_string! str
70
- pre = " " * count
74
+ pre = ' ' * count
71
75
 
72
76
  map_lines(str) { |line| "#{pre}#{line}" }
73
- end # method indent
77
+ end
74
78
 
75
79
  # Yields each line of the string to the provided block and combines the
76
80
  # results into a new multiline string.
@@ -81,23 +85,23 @@ module SleepingKingStudios::Tools
81
85
  # @yieldparam index [Integer] The index of the current line.
82
86
  #
83
87
  # @return [String] The mapped string.
84
- def map_lines str
88
+ def map_lines(str)
85
89
  str = require_string! str
86
90
 
87
- str.each_line.with_index.reduce('') do |memo, (line, index)|
91
+ str.each_line.with_index.reduce(+'') do |memo, (line, index)|
88
92
  memo << yield(line, index)
89
- end # each_line
90
- end # method map_lines
93
+ end
94
+ end
91
95
 
92
96
  # Determines whether or not the given word is in plural form. If calling
93
97
  # #pluralize(word) is equal to word, the word is considered plural.
94
98
  #
95
99
  # @return [Boolean] True if the word is in plural form, otherwise false.
96
- def plural? word
100
+ def plural?(word)
97
101
  word = require_string!(word)
98
102
 
99
103
  word == pluralize(word)
100
- end # method plural?
104
+ end
101
105
 
102
106
  # @overload pluralize(str)
103
107
  # Takes a word in singular form and returns the plural form, based on the
@@ -106,63 +110,41 @@ module SleepingKingStudios::Tools
106
110
  # @param str [String] The word to pluralize.
107
111
  #
108
112
  # @return [String] The pluralized word.
109
- #
110
- # @overload pluralize(count, single, plural)
111
- # @deprecated This functionality is deprecated as of version 0.4.0 and
112
- # will be removed in a future version. Use IntegerTools#pluralize
113
- # instead.
114
- #
115
- # Returns the singular or the plural value, depending on the provided
116
- # item count.
117
- #
118
- # @example
119
- # "There are four #{StringTools.pluralize 4, 'light', 'lights'}!"
120
- # #=> 'There are four lights!'
121
- #
122
- # @param [Integer] count The number of items.
123
- # @param [String] single The singular form of the word or phrase.
124
- # @param [String] plural The plural form of the word or phrase.
125
- #
126
- # @return [String] The single form if count == 1; otherwise the plural
127
- # form.
128
- def pluralize *args
129
- if args.count == 3
130
- CoreTools.deprecate 'StringTools#pluralize with 3 arguments',
131
- :message => 'Use IntegerTools#pluralize instead.'
132
-
133
- return IntegerTools.pluralize(*args)
134
- end # if
135
-
113
+ def pluralize(*args)
136
114
  str = require_string! args.first
137
115
 
138
- plural_inflector.pluralize str
139
- end # method pluralize
116
+ inflector.pluralize str
117
+ end
140
118
 
141
119
  # Determines whether or not the given word is in singular form. If calling
142
120
  # #singularize(word) is equal to word, the word is considered singular.
143
121
  #
144
122
  # @return [Boolean] True if the word is in singular form, otherwise false.
145
- def singular? word
123
+ def singular?(word)
146
124
  word = require_string!(word)
147
125
 
148
126
  word == singularize(word)
149
- end # method singular?
127
+ end
150
128
 
151
- # (see PluralInflector#singularize)
152
- def singularize str
129
+ # Transforms the word to a singular, lowercase form.
130
+ #
131
+ # @param str [String] The word to transform.
132
+ #
133
+ # @return [String] The word in singular form.
134
+ def singularize(str)
153
135
  require_string! str
154
136
 
155
- plural_inflector.singularize str
156
- end # method singularize
137
+ inflector.singularize str
138
+ end
157
139
 
158
140
  # Returns true if the object is a String.
159
141
  #
160
142
  # @param str [Object] The object to test.
161
143
  #
162
144
  # @return [Boolean] True if the object is a String, otherwise false.
163
- def string? str
164
- String === str
165
- end # method string?
145
+ def string?(str)
146
+ str.is_a?(String)
147
+ end
166
148
 
167
149
  # Converts a mixed-case string expression to a lowercase, underscore
168
150
  # separated string.
@@ -172,29 +154,20 @@ module SleepingKingStudios::Tools
172
154
  # @return [String] The converted string.
173
155
  #
174
156
  # @see ActiveSupport::Inflector#underscore.
175
- def underscore str
157
+ def underscore(str)
176
158
  str = require_string! str
177
159
 
178
- str = str.dup
179
- str.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
180
- str.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
181
- str.tr!("-", "_")
182
- str.downcase!
183
- str
184
- end # method underscore
160
+ inflector.underscore(str)
161
+ end
185
162
 
186
163
  private
187
164
 
188
- def plural_inflector
189
- @plural_inflector ||= PluralInflector.new
190
- end # method plural_inflector
191
-
192
- def require_string! value
165
+ def require_string!(value)
193
166
  return value if string?(value)
194
167
 
195
168
  return value.to_s if value.is_a?(Symbol)
196
169
 
197
170
  raise ArgumentError, 'argument must be a string', caller[1..-1]
198
- end # method require_array
199
- end # module
200
- end # module
171
+ end
172
+ end
173
+ end