lite-ruby 1.3.2 → 2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/Gemfile.lock +1 -1
- data/README.md +26 -6
- data/docs/HASH.md +13 -0
- data/lib/generators/lite/ruby/install_generator.rb +0 -2
- data/lib/generators/lite/ruby/templates/install.rb +18 -6
- data/lib/lite/ruby.rb +2 -15
- data/lib/lite/ruby/array.rb +218 -220
- data/lib/lite/ruby/boolean.rb +17 -19
- data/lib/lite/ruby/date.rb +13 -20
- data/lib/lite/ruby/enumerable.rb +153 -155
- data/lib/lite/ruby/formats/date_stamps.yml +34 -0
- data/lib/lite/ruby/formats/date_units.yml +42 -0
- data/lib/lite/ruby/formats/integer_roman_numerals.yml +13 -0
- data/lib/lite/ruby/formats/string_transliterations.yml +189 -0
- data/lib/lite/ruby/formats/time_stamps.yml +42 -0
- data/lib/lite/ruby/formats/time_units.yml +28 -0
- data/lib/lite/ruby/hash.rb +313 -301
- data/lib/lite/ruby/helpers/date_time_helper.rb +24 -0
- data/lib/lite/ruby/integer.rb +62 -63
- data/lib/lite/ruby/kernel.rb +19 -21
- data/lib/lite/ruby/monkey_patches.rb +16 -0
- data/lib/lite/ruby/numeric.rb +175 -177
- data/lib/lite/ruby/object.rb +128 -130
- data/lib/lite/ruby/open_struct.rb +17 -19
- data/lib/lite/ruby/range.rb +19 -21
- data/lib/lite/ruby/safe/string.rb +8 -7
- data/lib/lite/ruby/string.rb +348 -384
- data/lib/lite/ruby/struct.rb +7 -9
- data/lib/lite/ruby/time.rb +25 -30
- data/lib/lite/ruby/version.rb +1 -1
- metadata +10 -5
- data/lib/lite/ruby/configuration.rb +0 -38
- data/lib/lite/ruby/helpers/date_helper.rb +0 -107
- data/lib/lite/ruby/helpers/time_helper.rb +0 -86
data/lib/lite/ruby/object.rb
CHANGED
@@ -1,171 +1,169 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
is_a?(Array)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def bool?
|
23
|
-
true? || false?
|
24
|
-
end
|
25
|
-
|
26
|
-
def boolean?
|
27
|
-
val = to_s.downcase
|
28
|
-
TRUE_VALUES.include?(val) || FALSE_VALUES.include?(val)
|
3
|
+
class Object
|
4
|
+
|
5
|
+
FALSE_VALUES = %w[
|
6
|
+
0 f false n no off
|
7
|
+
].freeze
|
8
|
+
TRUE_VALUES = %w[
|
9
|
+
1 t true y yes on
|
10
|
+
].freeze
|
11
|
+
|
12
|
+
# NOTE: There is a clash between the PG gem and the `array?` method.
|
13
|
+
# We only need to skip this on migrations since that action
|
14
|
+
# happens on a seperate runtime.
|
15
|
+
unless defined?(PG) && ARGV.first.to_s.start_with?('db:')
|
16
|
+
def array?
|
17
|
+
is_a?(Array)
|
29
18
|
end
|
19
|
+
end
|
30
20
|
|
31
|
-
|
32
|
-
|
33
|
-
|
21
|
+
def bool?
|
22
|
+
true? || false?
|
23
|
+
end
|
34
24
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
# rubocop:enable Style/YodaCondition
|
25
|
+
def boolean?
|
26
|
+
val = to_s.downcase
|
27
|
+
TRUE_VALUES.include?(val) || FALSE_VALUES.include?(val)
|
28
|
+
end
|
40
29
|
|
41
|
-
|
42
|
-
|
43
|
-
|
30
|
+
def date?
|
31
|
+
is_a?(Date)
|
32
|
+
end
|
44
33
|
|
45
|
-
|
46
|
-
|
47
|
-
|
34
|
+
# rubocop:disable Style/YodaCondition
|
35
|
+
def false?
|
36
|
+
false == self
|
37
|
+
end
|
38
|
+
# rubocop:enable Style/YodaCondition
|
48
39
|
|
49
|
-
|
50
|
-
|
51
|
-
|
40
|
+
def falsey?
|
41
|
+
nil? || FALSE_VALUES.include?(to_s.downcase)
|
42
|
+
end
|
52
43
|
|
53
|
-
|
54
|
-
|
55
|
-
|
44
|
+
def float?
|
45
|
+
is_a?(Float)
|
46
|
+
end
|
56
47
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
end
|
61
|
-
# rubocop:enable Naming/PredicateName
|
48
|
+
def hash?
|
49
|
+
is_a?(Hash)
|
50
|
+
end
|
62
51
|
|
63
|
-
|
64
|
-
|
65
|
-
|
52
|
+
def integer?
|
53
|
+
is_a?(Integer)
|
54
|
+
end
|
66
55
|
|
67
|
-
|
68
|
-
|
69
|
-
|
56
|
+
# rubocop:disable Naming/PredicateName
|
57
|
+
def is_any?(*objects)
|
58
|
+
objects.any? { |obj| is_a?(obj) }
|
59
|
+
end
|
60
|
+
# rubocop:enable Naming/PredicateName
|
70
61
|
|
71
|
-
|
72
|
-
|
73
|
-
|
62
|
+
def numeral?
|
63
|
+
!to_s.match(/\A[+-]?\d+?(\.\d+)?\Z/).nil?
|
64
|
+
end
|
74
65
|
|
75
|
-
|
76
|
-
|
77
|
-
|
66
|
+
def numeric?
|
67
|
+
is_a?(Numeric)
|
68
|
+
end
|
78
69
|
|
79
|
-
|
80
|
-
|
81
|
-
|
70
|
+
def open_struct?
|
71
|
+
is_a?(OpenStruct)
|
72
|
+
end
|
82
73
|
|
83
|
-
|
84
|
-
|
85
|
-
|
74
|
+
def palindrome?
|
75
|
+
to_s == to_s.reverse
|
76
|
+
end
|
86
77
|
|
87
|
-
|
88
|
-
|
89
|
-
|
78
|
+
def range?
|
79
|
+
is_a?(Range)
|
80
|
+
end
|
90
81
|
|
91
|
-
|
92
|
-
|
93
|
-
|
82
|
+
def safe_call(...)
|
83
|
+
try_call(...) || self
|
84
|
+
end
|
94
85
|
|
95
|
-
|
96
|
-
|
97
|
-
|
86
|
+
def safe_send(...)
|
87
|
+
try_send(...) || self
|
88
|
+
end
|
98
89
|
|
99
|
-
|
100
|
-
|
101
|
-
|
90
|
+
def safe_try(...)
|
91
|
+
try(...) || self
|
92
|
+
end
|
102
93
|
|
103
|
-
|
104
|
-
|
105
|
-
|
94
|
+
def salvage(placeholder = '---')
|
95
|
+
blank? ? placeholder : self
|
96
|
+
end
|
106
97
|
|
107
|
-
|
108
|
-
|
109
|
-
|
98
|
+
def salvage_try(method_name = nil, *args, placeholder: '---', &block)
|
99
|
+
try(method_name, *args, &block).salvage(placeholder)
|
100
|
+
end
|
110
101
|
|
111
|
-
|
112
|
-
|
102
|
+
def send_chain(*args)
|
103
|
+
Array(args).inject(self) { |obj, argz| obj.send(*argz) }
|
104
|
+
end
|
113
105
|
|
114
|
-
|
115
|
-
|
106
|
+
def send_chain_if(*args)
|
107
|
+
Array(args).inject(self) { |obj, argz| obj.send_if(*argz) }
|
108
|
+
end
|
116
109
|
|
117
|
-
|
118
|
-
|
119
|
-
end
|
110
|
+
def send_if(key, *args, **kwargs, &block)
|
111
|
+
return self unless respond_to?(key)
|
120
112
|
|
121
|
-
|
122
|
-
|
123
|
-
end
|
113
|
+
send(key, *args, **kwargs, &block)
|
114
|
+
end
|
124
115
|
|
125
|
-
|
126
|
-
|
127
|
-
|
116
|
+
def set?
|
117
|
+
is_a?(Set)
|
118
|
+
end
|
128
119
|
|
129
|
-
|
130
|
-
|
131
|
-
|
120
|
+
def string?
|
121
|
+
is_a?(String)
|
122
|
+
end
|
132
123
|
|
133
|
-
|
134
|
-
|
135
|
-
|
124
|
+
def struct?
|
125
|
+
is_a?(Struct)
|
126
|
+
end
|
136
127
|
|
137
|
-
|
138
|
-
|
139
|
-
|
128
|
+
def symbol?
|
129
|
+
is_a?(Symbol)
|
130
|
+
end
|
140
131
|
|
141
|
-
|
142
|
-
|
132
|
+
def time?
|
133
|
+
is_a?(Time)
|
134
|
+
end
|
143
135
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
end
|
148
|
-
# rubocop:enable Style/YodaCondition
|
136
|
+
def to_bool
|
137
|
+
return true if truthy?
|
138
|
+
return false if falsey?
|
149
139
|
|
150
|
-
|
151
|
-
|
152
|
-
end
|
140
|
+
nil
|
141
|
+
end
|
153
142
|
|
154
|
-
|
155
|
-
|
143
|
+
# rubocop:disable Style/YodaCondition
|
144
|
+
def true?
|
145
|
+
true == self
|
146
|
+
end
|
147
|
+
# rubocop:enable Style/YodaCondition
|
156
148
|
|
157
|
-
|
158
|
-
|
149
|
+
def truthy?
|
150
|
+
TRUE_VALUES.include?(to_s.downcase)
|
151
|
+
end
|
159
152
|
|
160
|
-
|
161
|
-
|
162
|
-
rescue StandardError
|
163
|
-
nil
|
164
|
-
end
|
153
|
+
def try_call(...)
|
154
|
+
return unless respond_to?(:call)
|
165
155
|
|
166
|
-
|
156
|
+
call(...)
|
157
|
+
end
|
167
158
|
|
159
|
+
def try_send(...)
|
160
|
+
send(...)
|
161
|
+
rescue StandardError
|
162
|
+
nil
|
168
163
|
end
|
169
164
|
|
170
|
-
|
165
|
+
alias to_b to_bool
|
166
|
+
|
171
167
|
end
|
168
|
+
|
169
|
+
require 'lite/ruby/safe/object' unless defined?(ActiveSupport)
|
@@ -1,30 +1,28 @@
|
|
1
1
|
# frozen_string_literal: false
|
2
2
|
|
3
|
-
|
4
|
-
require 'ostruct'
|
3
|
+
require 'ostruct' unless defined?(OpenStruct)
|
5
4
|
|
6
|
-
|
5
|
+
class OpenStruct
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
def attributes
|
8
|
+
@table
|
9
|
+
end
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
def replace(args)
|
12
|
+
args.each { |key, val| self[key] = val }
|
13
|
+
end
|
15
14
|
|
16
|
-
|
17
|
-
|
15
|
+
def to_hash(table: true)
|
16
|
+
return attributes unless table
|
18
17
|
|
19
|
-
|
20
|
-
|
18
|
+
{ table: attributes }
|
19
|
+
end
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
def to_json(table: true)
|
22
|
+
to_hash(table: table).to_json
|
23
|
+
end
|
25
24
|
|
26
|
-
|
27
|
-
|
25
|
+
alias as_json to_json
|
26
|
+
alias to_h to_hash
|
28
27
|
|
29
|
-
end
|
30
28
|
end
|
data/lib/lite/ruby/range.rb
CHANGED
@@ -1,32 +1,30 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
class Range
|
3
|
+
class Range
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
def include_with_range?(other)
|
11
|
-
return include?(other) unless other.is_a?(Range)
|
5
|
+
def combine(other)
|
6
|
+
to_a.concat(other.to_a)
|
7
|
+
end
|
12
8
|
|
13
|
-
|
14
|
-
|
15
|
-
end
|
9
|
+
def include_with_range?(other)
|
10
|
+
return include?(other) unless other.is_a?(Range)
|
16
11
|
|
17
|
-
|
18
|
-
|
19
|
-
|
12
|
+
operator = exclude_end? && !other.exclude_end? ? :< : :<=
|
13
|
+
include?(other.first) && other.last.send(operator, last)
|
14
|
+
end
|
20
15
|
|
21
|
-
|
22
|
-
|
23
|
-
|
16
|
+
def sample
|
17
|
+
to_a.sample
|
18
|
+
end
|
24
19
|
|
25
|
-
|
26
|
-
|
27
|
-
|
20
|
+
def shuffle
|
21
|
+
to_a.shuffle
|
22
|
+
end
|
28
23
|
|
24
|
+
def within?(other)
|
25
|
+
cover?(other.first) && cover?(other.last)
|
29
26
|
end
|
30
27
|
|
31
|
-
require 'lite/ruby/safe/range' unless defined?(ActiveSupport)
|
32
28
|
end
|
29
|
+
|
30
|
+
require 'lite/ruby/safe/range' unless defined?(ActiveSupport)
|
@@ -151,16 +151,17 @@ class String
|
|
151
151
|
|
152
152
|
omission = options[:omission] || '...'
|
153
153
|
seperator = options[:separator]
|
154
|
-
|
155
154
|
size_with_room_for_omission = truncate_at - omission.length
|
155
|
+
stop = rindex(seperator || '', size_with_room_for_omission) if seperator
|
156
|
+
"#{self[0, stop || size_with_room_for_omission]}#{omission}"
|
157
|
+
end
|
156
158
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
end
|
159
|
+
def truncate_words(words_count, options = {})
|
160
|
+
sep = options[:separator] || /\s+/
|
161
|
+
sep = Regexp.escape(sep.to_s) unless sep.is_a?(Regexp)
|
162
|
+
return dup unless self =~ /\A((?>.+?#{sep}){#{words_count - 1}}.+?)#{sep}.*/m
|
162
163
|
|
163
|
-
|
164
|
+
$1 + (options[:omission] || '...')
|
164
165
|
end
|
165
166
|
|
166
167
|
def underscore
|
data/lib/lite/ruby/string.rb
CHANGED
@@ -1,485 +1,449 @@
|
|
1
1
|
# frozen_string_literal: false
|
2
2
|
|
3
|
-
|
4
|
-
class String
|
5
|
-
|
6
|
-
TRANSLITERATIONS = {
|
7
|
-
'À' => 'A', 'Á' => 'A', 'Â' => 'A', 'Ã' => 'A', 'Ä' => 'A', 'Å' => 'A', 'Æ' => 'Ae',
|
8
|
-
'Ç' => 'C', 'È' => 'E', 'É' => 'E', 'Ê' => 'E', 'Ë' => 'E', 'Ì' => 'I', 'Í' => 'I',
|
9
|
-
'Î' => 'I', 'Ï' => 'I', 'Ð' => 'D', 'Ñ' => 'N', 'Ò' => 'O', 'Ó' => 'O', 'Ô' => 'O',
|
10
|
-
'Õ' => 'O', 'Ö' => 'O', 'Ø' => 'O', 'Ù' => 'U', 'Ú' => 'U', 'Û' => 'U', 'Ü' => 'U',
|
11
|
-
'Ý' => 'Y', 'Þ' => 'Th', 'ß' => 'ss', 'à' => 'a', 'á' => 'a', 'â' => 'a', 'ã' => 'a',
|
12
|
-
'ä' => 'a', 'å' => 'a', 'æ' => 'ae', 'ç' => 'c', 'è' => 'e', 'é' => 'e', 'ê' => 'e',
|
13
|
-
'ë' => 'e', 'ì' => 'i', 'í' => 'i', 'î' => 'i', 'ï' => 'i', 'ð' => 'd', 'ñ' => 'n',
|
14
|
-
'ò' => 'o', 'ó' => 'o', 'ô' => 'o', 'õ' => 'o', 'ö' => 'o', 'ø' => 'o', 'ù' => 'u',
|
15
|
-
'ú' => 'u', 'û' => 'u', 'ü' => 'u', 'ý' => 'y', 'þ' => 'th', 'ÿ' => 'y', 'Ā' => 'A',
|
16
|
-
'ā' => 'a', 'Ă' => 'A', 'ă' => 'a', 'Ą' => 'A', 'ą' => 'a', 'Ć' => 'C', 'ć' => 'c',
|
17
|
-
'Ĉ' => 'C', 'ĉ' => 'c', 'Ċ' => 'C', 'ċ' => 'c', 'Č' => 'C', 'č' => 'c', 'Ď' => 'D',
|
18
|
-
'ď' => 'd', 'Đ' => 'D', 'đ' => 'd', 'Ē' => 'E', 'ē' => 'e', 'Ĕ' => 'E', 'ĕ' => 'e',
|
19
|
-
'Ė' => 'E', 'ė' => 'e', 'Ę' => 'E', 'ę' => 'e', 'Ě' => 'E', 'ě' => 'e', 'Ĝ' => 'G',
|
20
|
-
'ĝ' => 'g', 'Ğ' => 'G', 'ğ' => 'g', 'Ġ' => 'G', 'ġ' => 'g', 'Ģ' => 'G', 'ģ' => 'g',
|
21
|
-
'Ĥ' => 'H', 'ĥ' => 'h', 'Ħ' => 'H', 'ħ' => 'h', 'Ĩ' => 'I', 'ĩ' => 'i', 'Ī' => 'I',
|
22
|
-
'ī' => 'i', 'Ĭ' => 'I', 'ĭ' => 'i', 'Į' => 'I', 'į' => 'i', 'İ' => 'I', 'ı' => 'i',
|
23
|
-
'IJ' => 'Ij', 'ij' => 'ij', 'Ĵ' => 'J', 'ĵ' => 'j', 'Ķ' => 'K', 'ķ' => 'k', 'ĸ' => 'k',
|
24
|
-
'Ĺ' => 'L', 'ĺ' => 'l', 'Ļ' => 'L', 'ļ' => 'l', 'Ľ' => 'L', 'ľ' => 'l', 'Ŀ' => 'L',
|
25
|
-
'ŀ' => 'l', 'Ł' => 'L', 'ł' => 'l', 'Ń' => 'N', 'ń' => 'n', 'Ņ' => 'N', 'ņ' => 'n',
|
26
|
-
'Ň' => 'N', 'ň' => 'n', 'ʼn' => 'n', 'Ŋ' => 'Ng', 'ŋ' => 'ng', 'Ō' => 'O', 'ō' => 'o',
|
27
|
-
'Ŏ' => 'O', 'ŏ' => 'o', 'Ő' => 'O', 'ő' => 'o', 'Œ' => 'OE', 'œ' => 'oe', 'Ŕ' => 'R',
|
28
|
-
'ŕ' => 'r', 'Ŗ' => 'R', 'ŗ' => 'r', 'Ř' => 'R', 'ř' => 'r', 'Ś' => 'S', 'ś' => 's',
|
29
|
-
'Ŝ' => 'S', 'ŝ' => 's', 'Ş' => 'S', 'ş' => 's', 'Š' => 'S', 'š' => 's', 'Ţ' => 'T',
|
30
|
-
'ţ' => 't', 'Ť' => 'T', 'ť' => 't', 'Ŧ' => 'T', 'ŧ' => 't', 'Ũ' => 'U', 'ũ' => 'u',
|
31
|
-
'Ū' => 'U', 'ū' => 'u', 'Ŭ' => 'U', 'ŭ' => 'u', 'Ů' => 'U', 'ů' => 'u', 'Ű' => 'U',
|
32
|
-
'ű' => 'u', 'Ų' => 'U', 'ų' => 'u', 'Ŵ' => 'W', 'ŵ' => 'w', 'Ŷ' => 'Y', 'ŷ' => 'y',
|
33
|
-
'Ÿ' => 'Y', 'Ź' => 'Z', 'ź' => 'z', 'Ż' => 'Z', 'ż' => 'z', 'Ž' => 'Z', 'ž' => 'z'
|
34
|
-
}.freeze
|
35
|
-
|
36
|
-
def acronym
|
37
|
-
gsub(/(([a-zA-Z0-9])([a-zA-Z0-9])*)./, '\\2') || self
|
38
|
-
end
|
39
|
-
|
40
|
-
def acronym!
|
41
|
-
replace(acronym)
|
42
|
-
end
|
3
|
+
require 'yaml' unless defined?(YAML)
|
43
4
|
|
44
|
-
|
45
|
-
keys.any? { |key| include?(key) }
|
46
|
-
end
|
5
|
+
class String
|
47
6
|
|
48
|
-
|
49
|
-
|
50
|
-
|
7
|
+
TRANSLITERATIONS = YAML.load_file(
|
8
|
+
File.expand_path('formats/string_transliterations.yml', File.dirname(__FILE__))
|
9
|
+
).freeze
|
51
10
|
|
52
|
-
|
53
|
-
|
54
|
-
|
11
|
+
def acronym
|
12
|
+
gsub(/(([a-zA-Z0-9])([a-zA-Z0-9])*)./, '\\2') || self
|
13
|
+
end
|
55
14
|
|
56
|
-
|
57
|
-
|
58
|
-
|
15
|
+
def acronym!
|
16
|
+
replace(acronym)
|
17
|
+
end
|
59
18
|
|
60
|
-
|
61
|
-
|
62
|
-
|
19
|
+
def any?(*keys)
|
20
|
+
keys.any? { |key| include?(key) }
|
21
|
+
end
|
63
22
|
|
64
|
-
|
65
|
-
|
66
|
-
|
23
|
+
def camelize!(first_letter = :upper)
|
24
|
+
replace(camelize(first_letter))
|
25
|
+
end
|
67
26
|
|
68
|
-
|
69
|
-
|
70
|
-
|
27
|
+
def capitalized?
|
28
|
+
capitalize == self
|
29
|
+
end
|
71
30
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
end
|
31
|
+
def classify!
|
32
|
+
replace(classify)
|
33
|
+
end
|
76
34
|
|
77
|
-
|
78
|
-
|
79
|
-
|
35
|
+
def dasherize!
|
36
|
+
replace(dasherize)
|
37
|
+
end
|
80
38
|
|
81
|
-
|
82
|
-
|
39
|
+
def deconstantize!
|
40
|
+
replace(deconstantize)
|
41
|
+
end
|
83
42
|
|
84
|
-
|
85
|
-
|
43
|
+
def dedupe(pattern)
|
44
|
+
dup.dedupe!(pattern)
|
45
|
+
end
|
86
46
|
|
87
|
-
|
88
|
-
|
89
|
-
|
47
|
+
def dedupe!(pattern)
|
48
|
+
pattern.each_char { |char| gsub!(/#{Regexp.escape(char)}{2,}/, char) }
|
49
|
+
self
|
50
|
+
end
|
90
51
|
|
91
|
-
|
92
|
-
|
93
|
-
|
52
|
+
def demodulize!
|
53
|
+
replace(demodulize)
|
54
|
+
end
|
94
55
|
|
95
|
-
|
96
|
-
|
56
|
+
def domain
|
57
|
+
return self unless self =~ %r{^(?:\w+://)?([^/?]+)(?:/|\?|$)}
|
97
58
|
|
98
|
-
|
99
|
-
|
59
|
+
Regexp.last_match(1)
|
60
|
+
end
|
100
61
|
|
101
|
-
|
102
|
-
|
62
|
+
def downcase?
|
63
|
+
downcase == self
|
64
|
+
end
|
103
65
|
|
104
|
-
|
105
|
-
|
106
|
-
|
66
|
+
def each_word(&block)
|
67
|
+
words.each(&block)
|
68
|
+
end
|
107
69
|
|
108
|
-
|
109
|
-
|
110
|
-
end
|
70
|
+
def ellipsize(ellipsize_at, options = {})
|
71
|
+
return self if length <= ellipsize_at
|
111
72
|
|
112
|
-
|
113
|
-
|
114
|
-
end
|
73
|
+
separator = options[:separator] || '...'
|
74
|
+
offset = options[:offset] || 4
|
115
75
|
|
116
|
-
|
117
|
-
|
118
|
-
end
|
76
|
+
"#{self[0, offset]}#{separator}#{self[-offset, offset]}"
|
77
|
+
end
|
119
78
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
srch_index = rindex(pattern)
|
79
|
+
def format(*args)
|
80
|
+
super(self, *args.flatten)
|
81
|
+
end
|
124
82
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
srch_index = srch_index.zero? ? nil : temp_string.rindex(pattern)
|
129
|
-
end
|
83
|
+
def headerize
|
84
|
+
squish.each_word(&:capitalize!).join(' ')
|
85
|
+
end
|
130
86
|
|
131
|
-
|
132
|
-
|
87
|
+
def headerize!
|
88
|
+
replace(headerize)
|
89
|
+
end
|
133
90
|
|
134
|
-
|
135
|
-
|
136
|
-
|
91
|
+
def humanize!(capitalize: true)
|
92
|
+
replace(humanize(capitalize: capitalize))
|
93
|
+
end
|
137
94
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
gsub!(/([a-z\d]*)/i, &:downcase)
|
143
|
-
gsub!(/\A\w/) { |str| capitalize ? str.upcase : str }
|
144
|
-
gsub!(/ id\z/, ' ID') || self
|
145
|
-
end
|
95
|
+
def index_all(pattern)
|
96
|
+
pattern = pattern.to_s if pattern.is_a?(Numeric)
|
97
|
+
arr_indexes = []
|
98
|
+
srch_index = rindex(pattern)
|
146
99
|
|
147
|
-
|
148
|
-
|
100
|
+
while srch_index
|
101
|
+
temp_string = self[0..(srch_index - 1)]
|
102
|
+
arr_indexes << srch_index
|
103
|
+
srch_index = srch_index.zero? ? nil : temp_string.rindex(pattern)
|
149
104
|
end
|
150
105
|
|
151
|
-
|
152
|
-
|
106
|
+
arr_indexes.reverse
|
107
|
+
end
|
153
108
|
|
154
|
-
|
155
|
-
|
156
|
-
|
109
|
+
def labelize(capitalize: true)
|
110
|
+
dup.labelize!(capitalize: capitalize)
|
111
|
+
end
|
157
112
|
|
158
|
-
|
159
|
-
|
160
|
-
|
113
|
+
def labelize!(capitalize: true)
|
114
|
+
underscore!
|
115
|
+
tr!('_', ' ')
|
116
|
+
squish!
|
117
|
+
gsub!(/([a-z\d]*)/i, &:downcase)
|
118
|
+
gsub!(/\A\w/) { |str| capitalize ? str.upcase : str }
|
119
|
+
gsub!(/ id\z/, ' ID') || self
|
120
|
+
end
|
161
121
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
gsub!('/', '__')
|
166
|
-
gsub!('::', '__')
|
167
|
-
downcase! || self
|
168
|
-
end
|
122
|
+
def lchomp(match)
|
123
|
+
dup.lchomp!(match)
|
124
|
+
end
|
169
125
|
|
170
|
-
|
171
|
-
|
172
|
-
end
|
126
|
+
def lchomp!(match)
|
127
|
+
return self unless index(match)
|
173
128
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
gsub!(/(?:_+|-+)([a-z])/) { $1.upcase }
|
178
|
-
gsub!(/(\A|\s)([a-z])/) { $1 + $2.upcase } || self
|
179
|
-
end
|
129
|
+
self[0...match.size] = ''
|
130
|
+
self
|
131
|
+
end
|
180
132
|
|
181
|
-
|
182
|
-
|
183
|
-
|
133
|
+
def methodize
|
134
|
+
dup.methodize!
|
135
|
+
end
|
184
136
|
|
185
|
-
|
186
|
-
|
187
|
-
|
137
|
+
def methodize!
|
138
|
+
gsub!(/([A-Z]+)([A-Z])/, '\1_\2')
|
139
|
+
gsub!(/([a-z])([A-Z])/, '\1_\2')
|
140
|
+
gsub!('/', '__')
|
141
|
+
gsub!('::', '__')
|
142
|
+
downcase! || self
|
143
|
+
end
|
188
144
|
|
189
|
-
|
190
|
-
|
145
|
+
def modulize
|
146
|
+
dup.modulize!
|
147
|
+
end
|
191
148
|
|
192
|
-
|
193
|
-
|
149
|
+
def modulize!
|
150
|
+
gsub!(/__(.?)/) { "::#{$1.upcase}" }
|
151
|
+
gsub!(%r{/(.?)}) { "::#{$1.upcase}" }
|
152
|
+
gsub!(/(?:_+|-+)([a-z])/) { $1.upcase }
|
153
|
+
gsub!(/(\A|\s)([a-z])/) { $1 + $2.upcase } || self
|
154
|
+
end
|
194
155
|
|
195
|
-
|
196
|
-
|
197
|
-
|
156
|
+
def mixedcase?
|
157
|
+
!upcase? && !downcase?
|
158
|
+
end
|
198
159
|
|
199
|
-
|
200
|
-
|
201
|
-
|
160
|
+
def non_possessive
|
161
|
+
dup.non_possessive!
|
162
|
+
end
|
202
163
|
|
203
|
-
|
204
|
-
|
205
|
-
end
|
164
|
+
def non_possessive!
|
165
|
+
return self unless possessive?
|
206
166
|
|
207
|
-
|
208
|
-
|
209
|
-
end
|
167
|
+
chomp!("'s") || chomp!("'") || self
|
168
|
+
end
|
210
169
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
gsub!('__', '/')
|
215
|
-
gsub!('::', '/')
|
216
|
-
gsub!(/\s+/, '')
|
217
|
-
gsub!(/[?%*:|"<>.]+/, '')
|
218
|
-
downcase! || self
|
219
|
-
end
|
170
|
+
def ordinal
|
171
|
+
to_i.ordinal
|
172
|
+
end
|
220
173
|
|
221
|
-
|
222
|
-
|
223
|
-
|
174
|
+
def ordinalize
|
175
|
+
to_i.ordinalize
|
176
|
+
end
|
224
177
|
|
225
|
-
|
226
|
-
|
227
|
-
|
178
|
+
def parameterize!(separator: '-')
|
179
|
+
replace(parameterize(separator: separator))
|
180
|
+
end
|
228
181
|
|
229
|
-
|
230
|
-
|
231
|
-
|
182
|
+
def pathize
|
183
|
+
dup.pathize!
|
184
|
+
end
|
232
185
|
|
233
|
-
|
234
|
-
|
186
|
+
def pathize!
|
187
|
+
gsub!(/([A-Z]+)([A-Z])/, '\1_\2')
|
188
|
+
gsub!(/([a-z])([A-Z])/, '\1_\2')
|
189
|
+
gsub!('__', '/')
|
190
|
+
gsub!('::', '/')
|
191
|
+
gsub!(/\s+/, '')
|
192
|
+
gsub!(/[?%*:|"<>.]+/, '')
|
193
|
+
downcase! || self
|
194
|
+
end
|
235
195
|
|
236
|
-
|
237
|
-
|
238
|
-
|
196
|
+
def pollute(delimiter = '^--^--^')
|
197
|
+
chars.map { |chr| "#{chr}#{delimiter}" }.join
|
198
|
+
end
|
239
199
|
|
240
|
-
|
241
|
-
|
242
|
-
|
200
|
+
def pollute!(delimiter = '^--^--^')
|
201
|
+
replace(pollute(delimiter))
|
202
|
+
end
|
243
203
|
|
244
|
-
|
245
|
-
|
246
|
-
|
204
|
+
def pop
|
205
|
+
self[-1]
|
206
|
+
end
|
247
207
|
|
248
|
-
|
249
|
-
|
250
|
-
end
|
208
|
+
def possessive
|
209
|
+
return self if possessive?
|
251
210
|
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
tmp = amount
|
256
|
-
amount = type
|
257
|
-
type = tmp || :mixed
|
258
|
-
else
|
259
|
-
amount ||= 1
|
260
|
-
end
|
211
|
+
possession = end_with?('s') ? "'" : "'s"
|
212
|
+
"#{self}#{possession}"
|
213
|
+
end
|
261
214
|
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
b = f
|
266
|
-
when '"', 'double', 'd', '2'
|
267
|
-
f = '"' * amount
|
268
|
-
b = f
|
269
|
-
when '`', 'back', 'backtick', 'b', '-1'
|
270
|
-
f = '`' * amount
|
271
|
-
b = f
|
272
|
-
when "`'", 'bracket', 'sb'
|
273
|
-
f = '`' * amount
|
274
|
-
b = "'" * amount
|
275
|
-
when "'\"", 'mixed', 'm', 'Integer'
|
276
|
-
c = (amount.to_f / 2).to_i
|
277
|
-
f = '"' * c
|
278
|
-
b = f
|
279
|
-
|
280
|
-
if amount.odd?
|
281
|
-
f = "'#{f}"
|
282
|
-
b += "'"
|
283
|
-
end
|
284
|
-
else
|
285
|
-
raise ArgumentError, "Invalid quote type: #{type.inspect}"
|
286
|
-
end
|
215
|
+
def possessive!
|
216
|
+
replace(possessive)
|
217
|
+
end
|
287
218
|
|
288
|
-
|
289
|
-
|
290
|
-
|
219
|
+
def possessive?
|
220
|
+
%w['s s'].any? { |pos| end_with?(pos) }
|
221
|
+
end
|
291
222
|
|
292
|
-
|
293
|
-
|
294
|
-
|
223
|
+
def push(string)
|
224
|
+
replace(concat(string))
|
225
|
+
end
|
295
226
|
|
296
|
-
|
297
|
-
|
227
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
228
|
+
def quote(type = :double, amount = nil)
|
229
|
+
if type.is_a?(Integer)
|
230
|
+
tmp = amount
|
231
|
+
amount = type
|
232
|
+
type = tmp || :mixed
|
233
|
+
else
|
234
|
+
amount ||= 1
|
235
|
+
end
|
236
|
+
|
237
|
+
case type.to_s
|
238
|
+
when "'", 'single', 's', '1'
|
239
|
+
f = "'" * amount
|
240
|
+
b = f
|
241
|
+
when '"', 'double', 'd', '2'
|
242
|
+
f = '"' * amount
|
243
|
+
b = f
|
244
|
+
when '`', 'back', 'backtick', 'b', '-1'
|
245
|
+
f = '`' * amount
|
246
|
+
b = f
|
247
|
+
when "`'", 'bracket', 'sb'
|
248
|
+
f = '`' * amount
|
249
|
+
b = "'" * amount
|
250
|
+
when "'\"", 'mixed', 'm', 'Integer'
|
251
|
+
c = (amount.to_f / 2).to_i
|
252
|
+
f = '"' * c
|
253
|
+
b = f
|
254
|
+
|
255
|
+
if amount.odd?
|
256
|
+
f = "'#{f}"
|
257
|
+
b += "'"
|
258
|
+
end
|
259
|
+
else
|
260
|
+
raise ArgumentError, "Invalid quote type: #{type.inspect}"
|
298
261
|
end
|
299
262
|
|
300
|
-
|
301
|
-
|
302
|
-
|
263
|
+
"#{f}#{self}#{b}"
|
264
|
+
end
|
265
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
303
266
|
|
304
|
-
|
305
|
-
|
306
|
-
|
267
|
+
def quote!(type = :double, amount = nil)
|
268
|
+
replace(quote(type, amount))
|
269
|
+
end
|
307
270
|
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
end
|
271
|
+
def remove_tags
|
272
|
+
dup.remove_tags!
|
273
|
+
end
|
312
274
|
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
rescue Encoding::InvalidByteSequenceError
|
317
|
-
force_encoding(target_encoding).scrub!(replacement)
|
318
|
-
rescue Encoding::UndefinedConversionError
|
319
|
-
encode(
|
320
|
-
target_encoding,
|
321
|
-
invalid: :replace,
|
322
|
-
undef: :replace,
|
323
|
-
replace: replacement,
|
324
|
-
UNIVERSAL_NEWLINE_DECORATOR: true
|
325
|
-
)
|
326
|
-
end
|
327
|
-
# rubocop:enable Metrics/MethodLength
|
275
|
+
def remove_tags!
|
276
|
+
gsub!(%r{</?[^>]*>}, '') || self
|
277
|
+
end
|
328
278
|
|
329
|
-
|
330
|
-
|
331
|
-
|
279
|
+
def rotate(amount = 1)
|
280
|
+
dup.rotate!(amount)
|
281
|
+
end
|
332
282
|
|
333
|
-
|
334
|
-
|
335
|
-
|
283
|
+
def rotate!(amount = 1)
|
284
|
+
amount += size if amount.negative?
|
285
|
+
slice!(amount, size - amount) + slice!(0, amount)
|
286
|
+
end
|
336
287
|
|
337
|
-
|
338
|
-
|
339
|
-
|
288
|
+
# rubocop:disable Metrics/MethodLength
|
289
|
+
def safe_encode(target_encoding, replacement = '')
|
290
|
+
encode(target_encoding)
|
291
|
+
rescue Encoding::InvalidByteSequenceError
|
292
|
+
force_encoding(target_encoding).scrub!(replacement)
|
293
|
+
rescue Encoding::UndefinedConversionError
|
294
|
+
encode(
|
295
|
+
target_encoding,
|
296
|
+
invalid: :replace,
|
297
|
+
undef: :replace,
|
298
|
+
replace: replacement,
|
299
|
+
UNIVERSAL_NEWLINE_DECORATOR: true
|
300
|
+
)
|
301
|
+
end
|
302
|
+
# rubocop:enable Metrics/MethodLength
|
340
303
|
|
341
|
-
|
342
|
-
|
343
|
-
|
304
|
+
def safe_encode!(target_encoding, replacement = '')
|
305
|
+
replace(safe_encode(target_encoding, replacement))
|
306
|
+
end
|
344
307
|
|
345
|
-
|
346
|
-
|
308
|
+
def sample(separator = ' ')
|
309
|
+
split(separator).sample
|
310
|
+
end
|
347
311
|
|
348
|
-
|
349
|
-
|
312
|
+
def sample!(separator = ' ')
|
313
|
+
replace(sample(separator))
|
314
|
+
end
|
350
315
|
|
351
|
-
|
352
|
-
|
353
|
-
|
316
|
+
def shift(*patterns)
|
317
|
+
dup.shift!(*patterns)
|
318
|
+
end
|
354
319
|
|
355
|
-
|
356
|
-
|
357
|
-
end
|
320
|
+
def shift!(*patterns)
|
321
|
+
return self[0] if patterns.empty?
|
358
322
|
|
359
|
-
|
360
|
-
|
361
|
-
when String then keep.chars
|
362
|
-
when Array then keep.map(&:to_s)
|
363
|
-
when Range then keep.to_a.map(&:to_s)
|
364
|
-
else raise TypeError, "Invalid parameter: #{keep.inspect}"
|
365
|
-
end
|
323
|
+
patterns.each_with_object(self) { |pat, str| str.sub!(pat, '') }
|
324
|
+
end
|
366
325
|
|
367
|
-
|
368
|
-
|
326
|
+
def shuffle(separator = '')
|
327
|
+
split(separator).shuffle.join
|
328
|
+
end
|
369
329
|
|
370
|
-
|
371
|
-
|
372
|
-
|
330
|
+
def shuffle!(separator = '')
|
331
|
+
replace(shuffle(separator))
|
332
|
+
end
|
373
333
|
|
374
|
-
|
375
|
-
|
376
|
-
|
334
|
+
def sift(keep)
|
335
|
+
keep = case keep
|
336
|
+
when String then keep.chars
|
337
|
+
when Array then keep.map(&:to_s)
|
338
|
+
when Range then keep.to_a.map(&:to_s)
|
339
|
+
else raise TypeError, "Invalid parameter: #{keep.inspect}"
|
340
|
+
end
|
377
341
|
|
378
|
-
|
379
|
-
|
380
|
-
gsub!(/[^\w_ \-]+/i, '')
|
381
|
-
gsub!(/[ \-]+/i, '-')
|
382
|
-
gsub!(/^-|-$/i, '')
|
383
|
-
downcase! || self
|
384
|
-
end
|
342
|
+
chars.keep_if { |chr| keep.include?(chr) }.join
|
343
|
+
end
|
385
344
|
|
386
|
-
|
387
|
-
|
388
|
-
|
345
|
+
def sift!(keep)
|
346
|
+
replace(sift(keep))
|
347
|
+
end
|
389
348
|
|
390
|
-
|
391
|
-
|
392
|
-
|
349
|
+
def slugify
|
350
|
+
dup.slugify!
|
351
|
+
end
|
393
352
|
|
394
|
-
|
395
|
-
|
396
|
-
|
353
|
+
def slugify!
|
354
|
+
gsub!(/[^\x00-\x7F]+/, '')
|
355
|
+
gsub!(/[^\w \-]+/i, '')
|
356
|
+
gsub!(/[ \-]+/i, '-')
|
357
|
+
gsub!(/^-|-$/i, '')
|
358
|
+
downcase! || self
|
359
|
+
end
|
397
360
|
|
398
|
-
|
399
|
-
|
400
|
-
|
361
|
+
def sort
|
362
|
+
chars.sort.join
|
363
|
+
end
|
401
364
|
|
402
|
-
|
403
|
-
|
404
|
-
|
365
|
+
def sort!
|
366
|
+
replace(sort)
|
367
|
+
end
|
405
368
|
|
406
|
-
|
407
|
-
|
408
|
-
|
369
|
+
def transliterize
|
370
|
+
TRANSLITERATIONS.each_with_object(dup) { |(k, v), s| s.gsub!(k, v) }
|
371
|
+
end
|
409
372
|
|
410
|
-
|
411
|
-
|
373
|
+
def transliterize!
|
374
|
+
replace(transliterize)
|
375
|
+
end
|
412
376
|
|
413
|
-
|
414
|
-
|
377
|
+
def titleize!
|
378
|
+
replace(titleize)
|
379
|
+
end
|
415
380
|
|
416
|
-
|
417
|
-
|
418
|
-
|
381
|
+
def upcase?
|
382
|
+
upcase == self
|
383
|
+
end
|
419
384
|
|
420
|
-
|
421
|
-
|
422
|
-
|
385
|
+
def underscore!
|
386
|
+
replace(underscore)
|
387
|
+
end
|
423
388
|
|
424
|
-
|
425
|
-
|
426
|
-
|
389
|
+
def unpollute(delimiter = '^--^--^')
|
390
|
+
dup.unpollute!(delimiter)
|
391
|
+
end
|
427
392
|
|
428
|
-
|
429
|
-
|
430
|
-
|
393
|
+
def unpollute!(delimiter = '^--^--^')
|
394
|
+
gsub!(delimiter, '') || self
|
395
|
+
end
|
431
396
|
|
432
|
-
|
433
|
-
|
434
|
-
|
397
|
+
def unquote
|
398
|
+
dup.unquote!
|
399
|
+
end
|
435
400
|
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
end
|
401
|
+
def unquote!
|
402
|
+
[0, -1].each do |i|
|
403
|
+
case self[i, 1]
|
404
|
+
when "'", '"', '`' then self[i] = ''
|
441
405
|
end
|
442
|
-
|
443
|
-
self
|
444
406
|
end
|
445
407
|
|
446
|
-
|
447
|
-
|
448
|
-
.concat(self)
|
449
|
-
end
|
450
|
-
|
451
|
-
def unshift!(*patterns)
|
452
|
-
replace(unshift(*patterns))
|
453
|
-
end
|
408
|
+
self
|
409
|
+
end
|
454
410
|
|
455
|
-
|
456
|
-
|
457
|
-
|
411
|
+
def unshift(*patterns)
|
412
|
+
patterns.each_with_object('') { |pat, str| str << pat }
|
413
|
+
.concat(self)
|
414
|
+
end
|
458
415
|
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
str.gsub!('- ', ' ')
|
463
|
-
str.squeeze!(' ')
|
464
|
-
str.strip!
|
465
|
-
str.words
|
466
|
-
end
|
416
|
+
def unshift!(*patterns)
|
417
|
+
replace(unshift(*patterns))
|
418
|
+
end
|
467
419
|
|
468
|
-
|
469
|
-
|
470
|
-
|
420
|
+
def words
|
421
|
+
split(/\s+/)
|
422
|
+
end
|
471
423
|
|
472
|
-
|
473
|
-
|
474
|
-
|
424
|
+
def words_without_punctuation
|
425
|
+
str = dup
|
426
|
+
str.gsub!(%r{[.?¿¡…!,::;—"。?!、‘“”„«»〈〉《》,/\[\]]}, ' ')
|
427
|
+
str.gsub!('- ', ' ')
|
428
|
+
str.squeeze!(' ')
|
429
|
+
str.strip!
|
430
|
+
str.words
|
431
|
+
end
|
475
432
|
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
alias snakecase! underscore!
|
480
|
-
alias titlecase! titleize!
|
433
|
+
def variablize
|
434
|
+
"@#{gsub(/\W/, '_')}"
|
435
|
+
end
|
481
436
|
|
437
|
+
def variablize!
|
438
|
+
replace(variablize)
|
482
439
|
end
|
483
440
|
|
484
|
-
|
441
|
+
alias camelcase! camelize!
|
442
|
+
alias labelcase labelize
|
443
|
+
alias labelcase! labelize!
|
444
|
+
alias snakecase! underscore!
|
445
|
+
alias titlecase! titleize!
|
446
|
+
|
485
447
|
end
|
448
|
+
|
449
|
+
require 'lite/ruby/safe/string' unless defined?(ActiveSupport)
|