sleeping_king_studios-tools 0.7.0 → 1.0.2

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