blackstack_commons 0.0.6 → 0.0.7
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/examples/example01.rb +290 -0
- data/examples/example02.rb +3 -0
- data/lib/datetime.rb +6 -0
- data/lib/exception.rb +5 -0
- data/lib/fixnum.rb +14 -0
- data/lib/float.rb +6 -0
- data/lib/functions.rb +555 -0
- data/lib/string.rb +115 -0
- data/lib/time.rb +6 -0
- metadata +11 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e5f9a516f584be61a23ccf4a8e49cc5f62c0f8ca
|
4
|
+
data.tar.gz: a75e5f139c87961a3d03f1ea4d9e5c06fb2c060a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8491e3bc4478a58267fec9979dd823398d0cc1a3642db74933c19c764dd70ab32e6a10727f70694d070e18417db7b76b6559d01f138d5262a8d7c9ed4002c6e9
|
7
|
+
data.tar.gz: b68d4a2df8db3b240b016e80cb6366714e262f7a7eb9f4d56e28fe887bd970f760a373116c0cca9b6882d794de9f42bc8c07b91b66515472e1781df193df9427
|
@@ -0,0 +1,290 @@
|
|
1
|
+
require_relative '../lib/blackstack_commons'
|
2
|
+
|
3
|
+
# returns true if the string meets all the security requirements for a password
|
4
|
+
puts ""
|
5
|
+
puts "Passwords"
|
6
|
+
a = ['Hello', 'HelloWorld12$3']
|
7
|
+
a.each { |s|
|
8
|
+
print "'#{s}'.password?... "
|
9
|
+
puts s.password?.to_s
|
10
|
+
}
|
11
|
+
|
12
|
+
# returns true if the string match with the regex of a GUID
|
13
|
+
puts ""
|
14
|
+
puts "GUIDs"
|
15
|
+
a = [
|
16
|
+
'{331a92c3-5fe1-47a2-a31b-cfa439b5b4f9}',
|
17
|
+
'331a92c3-5fe1-47a2-a31b-cfa439b5b4f9',
|
18
|
+
'{331A92C3-5FE1-47A2-A31B-CFA439B5B4F9}',
|
19
|
+
'331A92C3-5FE1-47A2-A31B-CFA439B5B4F9',
|
20
|
+
'331A92C35FE147A2A31BCFA439B5B4F9',
|
21
|
+
]
|
22
|
+
a.each { |s|
|
23
|
+
print "'#{s}'.guid?... "
|
24
|
+
puts s.guid?.to_s
|
25
|
+
}
|
26
|
+
|
27
|
+
# returns true if the string match with the regex of a filename
|
28
|
+
puts ""
|
29
|
+
puts "Filenames"
|
30
|
+
a = [
|
31
|
+
'filename.txt',
|
32
|
+
'filename',
|
33
|
+
'filename.txt.rar',
|
34
|
+
]
|
35
|
+
a.each { |s|
|
36
|
+
print "'#{s}'.filename?... "
|
37
|
+
puts s.filename?.to_s
|
38
|
+
}
|
39
|
+
|
40
|
+
# returns true if the string match with the regex of an email
|
41
|
+
puts ""
|
42
|
+
puts "Emails"
|
43
|
+
a = [
|
44
|
+
'tango@expandedventure.com',
|
45
|
+
'tango@expandedventure.com.ar',
|
46
|
+
'tango',
|
47
|
+
'tango@',
|
48
|
+
]
|
49
|
+
a.each { |s|
|
50
|
+
print "'#{s}'.email?... "
|
51
|
+
puts s.email?.to_s
|
52
|
+
}
|
53
|
+
|
54
|
+
# returns true if the string match with the regex of a domain
|
55
|
+
puts ""
|
56
|
+
puts "Domains"
|
57
|
+
a = [
|
58
|
+
'tango',
|
59
|
+
'tango@expandedventure',
|
60
|
+
'tango@expandedventure.com',
|
61
|
+
'tango@expandedventure.com.ar',
|
62
|
+
'expandedventure.com',
|
63
|
+
'expandedventure.com.ar',
|
64
|
+
'https://expandedventure.com.ar',
|
65
|
+
'www.expandedventure.com.ar',
|
66
|
+
'https://www.expandedventure.com.ar',
|
67
|
+
]
|
68
|
+
a.each { |s|
|
69
|
+
print "'#{s}'.domain?... "
|
70
|
+
puts s.domain?.to_s
|
71
|
+
}
|
72
|
+
|
73
|
+
# returns true if the string match with the regex of a phone number
|
74
|
+
puts ""
|
75
|
+
puts "Domains"
|
76
|
+
a = [
|
77
|
+
'+54 9 11 5061 2148',
|
78
|
+
'545-5561-2148',
|
79
|
+
'545-561-2148',
|
80
|
+
'545 561 2148',
|
81
|
+
'54 545 561 2148',
|
82
|
+
'+54 545 561 2148',
|
83
|
+
'+54 545-561-2148',
|
84
|
+
'+54-545-561-2148',
|
85
|
+
]
|
86
|
+
a.each { |s|
|
87
|
+
print "'#{s}'.domain?... "
|
88
|
+
puts s.phone?.to_s
|
89
|
+
}
|
90
|
+
|
91
|
+
# returns true if the string match with the regex of a URL
|
92
|
+
puts ""
|
93
|
+
puts "URLs"
|
94
|
+
a = [
|
95
|
+
'tango',
|
96
|
+
'tango@expandedventure',
|
97
|
+
'tango@expandedventure.com',
|
98
|
+
'tango@expandedventure.com.ar',
|
99
|
+
'expandedventure.com',
|
100
|
+
'expandedventure.com.ar',
|
101
|
+
'https://expandedventure.com.ar',
|
102
|
+
'www.expandedventure.com.ar',
|
103
|
+
'https://www.expandedventure.com.ar',
|
104
|
+
]
|
105
|
+
a.each { |s|
|
106
|
+
print "'#{s}'.url?... "
|
107
|
+
puts s.url?.to_s
|
108
|
+
}
|
109
|
+
|
110
|
+
# returns true if the string match with the regex of a number
|
111
|
+
puts ""
|
112
|
+
puts "Fixnums"
|
113
|
+
a = [
|
114
|
+
'5',
|
115
|
+
'5.5',
|
116
|
+
'5,5',
|
117
|
+
'5000',
|
118
|
+
'5,000',
|
119
|
+
'5.000',
|
120
|
+
]
|
121
|
+
a.each { |s|
|
122
|
+
print "'#{s.to_s}'.fixnum?... "
|
123
|
+
puts s.fixnum?.to_s
|
124
|
+
}
|
125
|
+
|
126
|
+
# returns true if the string match with the regex of a datetime used in the BlackStack's API
|
127
|
+
puts ""
|
128
|
+
puts "SQL DateTimes"
|
129
|
+
a = [
|
130
|
+
'20191106215030',
|
131
|
+
'20191106',
|
132
|
+
'2019-11-06',
|
133
|
+
'2019-11-06 21:50:30',
|
134
|
+
'2019-13-06 21:50:30', # invalid month
|
135
|
+
'2019-11-06 25:50:30', # invalid hour
|
136
|
+
'2019-11-06 21:70:30', # invalid minute
|
137
|
+
'2019-11-06 21:50:70', # invalid second
|
138
|
+
]
|
139
|
+
a.each { |s|
|
140
|
+
print "'#{s.to_s}'.sql_datetime?... "
|
141
|
+
puts s.sql_datetime?.to_s
|
142
|
+
}
|
143
|
+
|
144
|
+
#
|
145
|
+
puts ""
|
146
|
+
puts "API DateTimes"
|
147
|
+
a = [
|
148
|
+
'20191106215030',
|
149
|
+
'20191106',
|
150
|
+
'2019-11-06',
|
151
|
+
'2019-11-06 21:50:30',
|
152
|
+
'20191306215030', # invalid month
|
153
|
+
'20191106255030', # invalid hour
|
154
|
+
'20191106217030', # invalid minute
|
155
|
+
'20191106215070', # invalid second
|
156
|
+
]
|
157
|
+
a.each { |s|
|
158
|
+
print "'#{s.to_s}'.api_datetime?... "
|
159
|
+
puts s.api_datetime?.to_s
|
160
|
+
}
|
161
|
+
|
162
|
+
# Convierte un string con formato sql-datatime a un string con formato sql-datetime.
|
163
|
+
puts ""
|
164
|
+
puts "SQL DateTime -> API DateTime"
|
165
|
+
a = [
|
166
|
+
'2019-11-06 21:50:30',
|
167
|
+
]
|
168
|
+
a.each { |s|
|
169
|
+
print "'#{s.to_s}'.sql_to_api_datetime... "
|
170
|
+
puts s.sql_to_api_datetime.to_s
|
171
|
+
}
|
172
|
+
|
173
|
+
# Convierte un string con formato api-datatime (yyyymmddhhmmss) a un string con formato sql-datetime (yyyy-mm-dd hh:mm:ss).
|
174
|
+
puts ""
|
175
|
+
puts "API DateTime -> SQL DateTime"
|
176
|
+
a = [
|
177
|
+
'20191106215030',
|
178
|
+
]
|
179
|
+
a.each { |s|
|
180
|
+
print "'#{s.to_s}'.api_to_sql_datetime... "
|
181
|
+
puts s.api_to_sql_datetime.to_s
|
182
|
+
}
|
183
|
+
|
184
|
+
# Rewrite a GUID as a standard (normalized) format.
|
185
|
+
puts ""
|
186
|
+
puts "Any GUID -> Normalized Guid"
|
187
|
+
a = [
|
188
|
+
'{331a92c3-5fe1-47a2-a31b-cfa439b5b4f9}',
|
189
|
+
'331a92c3-5fe1-47a2-a31b-cfa439b5b4f9',
|
190
|
+
'{331A92C3-5FE1-47A2-A31B-CFA439B5B4F9}',
|
191
|
+
'331A92C3-5FE1-47A2-A31B-CFA439B5B4F9',
|
192
|
+
]
|
193
|
+
a.each { |s|
|
194
|
+
print "'#{s}'.to_guid... "
|
195
|
+
puts s.to_guid.to_s
|
196
|
+
}
|
197
|
+
|
198
|
+
# Escape simple-quotes too add the string into literal-string of a dynamic query build into the Ruby code.
|
199
|
+
# Example: "I'm BlackStack" -> "I''m BlackStack"
|
200
|
+
puts ""
|
201
|
+
puts "Any String -> String with Escaped Quotes"
|
202
|
+
a = [
|
203
|
+
"I'm BlackStack",
|
204
|
+
"Hello World!",
|
205
|
+
]
|
206
|
+
a.each { |s|
|
207
|
+
print "'#{s}'.to_sql... "
|
208
|
+
puts s.to_sql.to_s
|
209
|
+
}
|
210
|
+
|
211
|
+
#
|
212
|
+
puts ""
|
213
|
+
puts "Spintax"
|
214
|
+
a = [
|
215
|
+
"I'm BlackStack",
|
216
|
+
"Hello World!",
|
217
|
+
"{Hello|Hi} World!",
|
218
|
+
"{Hello|Hi|Good {Morning|Afternoon}} World!", # Nexted spintax. Not supported.
|
219
|
+
"{Hello|Hi World!", # wrong syntax.
|
220
|
+
]
|
221
|
+
a.each { |s|
|
222
|
+
print "'#{s}'.spintax?... "
|
223
|
+
puts s.spintax?.to_s
|
224
|
+
}
|
225
|
+
|
226
|
+
# Returns a random spin from a spintax
|
227
|
+
puts ""
|
228
|
+
puts "Spin"
|
229
|
+
a = [
|
230
|
+
"{Hello|Hi|Good Morning|Good Afternoon} World!",
|
231
|
+
"{Hello|Hi|Good Morning|Good Afternoon} World!",
|
232
|
+
"{Hello|Hi|Good Morning|Good Afternoon} World!",
|
233
|
+
"{Hello|Hi|Good Morning|Good Afternoon} World!",
|
234
|
+
]
|
235
|
+
a.each { |s|
|
236
|
+
print "'#{s}'.spin... "
|
237
|
+
puts s.spin
|
238
|
+
}
|
239
|
+
|
240
|
+
# Converts a time object to an SQL friendy string
|
241
|
+
puts ""
|
242
|
+
puts "Time object -> SQL"
|
243
|
+
a = [
|
244
|
+
Time.new(2019,11,6,15,25,55),
|
245
|
+
DateTime.new(2019,11,6,15,25,55),
|
246
|
+
]
|
247
|
+
a.each { |o|
|
248
|
+
print "'#{o.to_s}'.to_sql... "
|
249
|
+
puts o.to_sql
|
250
|
+
}
|
251
|
+
|
252
|
+
# Converts number to a string with a format like xx,xxx,xxx.xxxx
|
253
|
+
puts ""
|
254
|
+
puts "Fixnum & Floats -> Screen Friendly Text"
|
255
|
+
a = [
|
256
|
+
64443,
|
257
|
+
64443.5454,
|
258
|
+
]
|
259
|
+
a.each { |i|
|
260
|
+
print "'#{i.to_s}'.to_label... "
|
261
|
+
puts i.to_label
|
262
|
+
}
|
263
|
+
|
264
|
+
# Converts number to a string with a format like xx,xxx,xxx.xxxx
|
265
|
+
puts ""
|
266
|
+
puts "Fixnum Minutes -> Time Spent (days, hours, minutes)"
|
267
|
+
a = [
|
268
|
+
59,
|
269
|
+
60,
|
270
|
+
61,
|
271
|
+
600,
|
272
|
+
601,
|
273
|
+
1440,
|
274
|
+
1441,
|
275
|
+
1500,
|
276
|
+
1501,
|
277
|
+
]
|
278
|
+
a.each { |i|
|
279
|
+
print "Minutes '#{i.to_s}'.to_time_spent... "
|
280
|
+
puts i.to_time_spent
|
281
|
+
}
|
282
|
+
|
283
|
+
|
284
|
+
=begin # TODO: Pending
|
285
|
+
encode_string
|
286
|
+
encode_html
|
287
|
+
encode_exception
|
288
|
+
encode_period
|
289
|
+
encode_javascript
|
290
|
+
=end
|
data/lib/datetime.rb
ADDED
data/lib/exception.rb
ADDED
data/lib/fixnum.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
class Fixnum
|
2
|
+
# Converts number to a string with a format like xx,xxx,xxx.xxxx
|
3
|
+
def to_label()
|
4
|
+
BlackStack::Number::Encoding::format_with_separator(self)
|
5
|
+
end
|
6
|
+
|
7
|
+
# Convierte una cantidad de minutos a una leyenda legible por el usuario.
|
8
|
+
# Ejemplo: "2 days, 5 hours"
|
9
|
+
# Ejemplo: "4 hours, 30 minutes"
|
10
|
+
# Ejemplo: "3 days, 4 hour"
|
11
|
+
def to_time_spent()
|
12
|
+
BlackStack::Number::Encoding::encode_minutes(self)
|
13
|
+
end
|
14
|
+
end # class String
|
data/lib/float.rb
ADDED
data/lib/functions.rb
ADDED
@@ -0,0 +1,555 @@
|
|
1
|
+
module BlackStack
|
2
|
+
# -----------------------------------------------------------------------------------------
|
3
|
+
# DateTime Functions
|
4
|
+
# -----------------------------------------------------------------------------------------
|
5
|
+
module DateTime
|
6
|
+
# -----------------------------------------------------------------------------------------
|
7
|
+
# Encoding
|
8
|
+
# -----------------------------------------------------------------------------------------
|
9
|
+
module Encoding
|
10
|
+
# Convierte un objeto date-time a un string con formato sql-datetime (yyyy-mm-dd hh:mm:ss).
|
11
|
+
def self.datetime_to_sql(o)
|
12
|
+
return o.strftime("%Y-%m-%d %H:%M:%S")
|
13
|
+
end
|
14
|
+
end # module Encode
|
15
|
+
|
16
|
+
# -----------------------------------------------------------------------------------------
|
17
|
+
# Miscelaneous
|
18
|
+
# -----------------------------------------------------------------------------------------
|
19
|
+
module Misc
|
20
|
+
def self.datetime_values_check(year,month,day,hour,minute,second)
|
21
|
+
if (year.to_i<1900 || year.to_i>=2100)
|
22
|
+
return false
|
23
|
+
end
|
24
|
+
|
25
|
+
if (month.to_i<1 || month.to_i>12)
|
26
|
+
return false
|
27
|
+
end
|
28
|
+
|
29
|
+
# TODO: Considerar la cantidad de dias de cada mes, y los anios biciestos. Buscar alguna funcion existente.
|
30
|
+
if (day.to_i<1 || day.to_i>31)
|
31
|
+
return false
|
32
|
+
end
|
33
|
+
|
34
|
+
if (hour.to_i<0 || hour.to_i>23)
|
35
|
+
return false
|
36
|
+
end
|
37
|
+
|
38
|
+
if (minute.to_i<0 || minute.to_i>59)
|
39
|
+
return false
|
40
|
+
end
|
41
|
+
|
42
|
+
if (second.to_i<0 || second.to_i>59)
|
43
|
+
return false
|
44
|
+
end
|
45
|
+
|
46
|
+
return true
|
47
|
+
end # datetime_values_check
|
48
|
+
end # module Misc
|
49
|
+
end # module DateTime
|
50
|
+
|
51
|
+
# -----------------------------------------------------------------------------------------
|
52
|
+
# Numeric Functions
|
53
|
+
# -----------------------------------------------------------------------------------------
|
54
|
+
module Number
|
55
|
+
# -----------------------------------------------------------------------------------------
|
56
|
+
# Encoding
|
57
|
+
# -----------------------------------------------------------------------------------------
|
58
|
+
module Encoding
|
59
|
+
# Converts number to a string with a format like xx,xxx,xxx.xxxx
|
60
|
+
# number: it may be int or float
|
61
|
+
def self.format_with_separator(number)
|
62
|
+
whole_part, decimal_part = number.to_s.split('.')
|
63
|
+
[whole_part.gsub(/(\d)(?=\d{3}+$)/, '\1,'), decimal_part].compact.join('.')
|
64
|
+
end
|
65
|
+
|
66
|
+
# Convierte una cantidad de minutos a una leyenda legible por el usuario.
|
67
|
+
# Ejemplo: "2 days, 5 hours"
|
68
|
+
# Ejemplo: "4 hours, 30 minutes"
|
69
|
+
# Ejemplo: "3 days, 4 hour"
|
70
|
+
def self.encode_minutes(n)
|
71
|
+
# TODO: validar que n sea un entero mayor a 0
|
72
|
+
if (n<0)
|
73
|
+
return "?"
|
74
|
+
end
|
75
|
+
if (n<60)
|
76
|
+
return "#{n} minutes"
|
77
|
+
elsif (n<24*60)
|
78
|
+
return "#{(n/60).to_i} hours, #{n-60*(n/60).to_i} minutes"
|
79
|
+
else
|
80
|
+
return "#{(n/(24*60)).to_i} days, #{((n-24*60*(n/(24*60)).to_i)/60).to_i} hours"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end # module Encode
|
84
|
+
end # module Number
|
85
|
+
|
86
|
+
# -----------------------------------------------------------------------------------------
|
87
|
+
# String Functions
|
88
|
+
# -----------------------------------------------------------------------------------------
|
89
|
+
module Strings
|
90
|
+
|
91
|
+
GUID_SIZE = 36
|
92
|
+
MATCH_PASSWORD = /^(?=.*[a-zA-Z])(?=.*[0-9]).{6,}$/
|
93
|
+
MATCH_GUID = /[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]\-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]\-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]\-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]/
|
94
|
+
MATCH_FILENAME = /^[\w,\s-]+\.[A-Za-z]{3}$/
|
95
|
+
MATCH_EMAIL = /[A-Z0-9._%a-z\-]+@(?:[A-Z0-9a-z\-]+\.)+[A-Za-z]{2,4}/
|
96
|
+
MATCH_DOMAIN = /(?:[A-Z0-9a-z\-]+\.)+[A-Za-z]{2,4}/
|
97
|
+
MATCH_DATE_STANDARD = /^\d{4}\-(0?[1-9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])$/
|
98
|
+
MATCH_PHONE = /(?:\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}/
|
99
|
+
MATCH_URL = /(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?/ # /(?:\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}/
|
100
|
+
MATCH_LINKEDIN_COMPANY_URL = /(https?:\/\/)?(www\\.)?linkedin\.com\/company\//
|
101
|
+
MATCH_FIXNUM = /^[0-9]+$/
|
102
|
+
MATCH_CONTENT_SPINNING = /{[^}]+}/
|
103
|
+
MATCH_SPINNED_TEXT = /code me/ # TODO: define this regex for the issue #1226
|
104
|
+
|
105
|
+
# -----------------------------------------------------------------------------------------
|
106
|
+
# Fuzzy String Comparsion Functions: How similar are 2 strings that are not exactly equal.
|
107
|
+
# -----------------------------------------------------------------------------------------
|
108
|
+
module SQL
|
109
|
+
def self.string_to_sql_string(s)
|
110
|
+
#return s.force_encoding("UTF-8").gsub("'", "''").to_s
|
111
|
+
return s.gsub("'", "''").to_s
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# -----------------------------------------------------------------------------------------
|
116
|
+
# Fuzzy String Comparsion Functions: How similar are 2 strings that are not exactly equal.
|
117
|
+
# -----------------------------------------------------------------------------------------
|
118
|
+
module Comparing
|
119
|
+
# retorna 0 si los strings son iguales
|
120
|
+
# https://stackoverflow.com/questions/16323571/measure-the-distance-between-two-strings-with-ruby
|
121
|
+
def self.levenshtein_distance(s, t)
|
122
|
+
s.downcase!
|
123
|
+
t.downcase!
|
124
|
+
|
125
|
+
m = s.length
|
126
|
+
n = t.length
|
127
|
+
return m if n == 0
|
128
|
+
return n if m == 0
|
129
|
+
d = Array.new(m+1) {Array.new(n+1)}
|
130
|
+
|
131
|
+
(0..m).each {|i| d[i][0] = i}
|
132
|
+
(0..n).each {|j| d[0][j] = j}
|
133
|
+
(1..n).each do |j|
|
134
|
+
(1..m).each do |i|
|
135
|
+
d[i][j] = if s[i-1] == t[j-1] # adjust index into string
|
136
|
+
d[i-1][j-1] # no operation required
|
137
|
+
else
|
138
|
+
[ d[i-1][j]+1, # deletion
|
139
|
+
d[i][j-1]+1, # insertion
|
140
|
+
d[i-1][j-1]+1, # substitution
|
141
|
+
].min
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
d[m][n]
|
146
|
+
end
|
147
|
+
|
148
|
+
# retorna la cantidad de palabras con mas de 3 caracteres que se encuentran en el parametro s
|
149
|
+
def self.max_sardi_distance(s)
|
150
|
+
s.downcase!
|
151
|
+
s.gsub!(/-/,' ')
|
152
|
+
ss = s.scan(/\b([a-z]+)\b/)
|
153
|
+
n = 0
|
154
|
+
ss.each { |x|
|
155
|
+
x = x[0]
|
156
|
+
if (x.size > 3) # para evitar keywords triviales como 'and'
|
157
|
+
n += 1
|
158
|
+
end
|
159
|
+
}
|
160
|
+
n
|
161
|
+
end
|
162
|
+
|
163
|
+
# retorna la cantidad de palabras con mas de 3 caracteres del parametro s que se encuentran en el parametro t
|
164
|
+
def self.sardi_distance(s, t)
|
165
|
+
s.downcase!
|
166
|
+
t.downcase!
|
167
|
+
s.gsub!(/-/,' ')
|
168
|
+
t.gsub!(/-/,' ')
|
169
|
+
max_distance = max_sardi_distance(s)
|
170
|
+
ss = s.scan(/\b([a-z]+)\b/)
|
171
|
+
tt = t.scan(/\b([a-z]+)\b/)
|
172
|
+
n = 0
|
173
|
+
ss.each { |x|
|
174
|
+
x = x[0]
|
175
|
+
if (x.size > 3) # para evitar keywords triviales como 'and'
|
176
|
+
if ( tt.select { |y| y[0] == x }.size > 0 )
|
177
|
+
n += 1
|
178
|
+
end
|
179
|
+
end
|
180
|
+
}
|
181
|
+
return max_distance - n
|
182
|
+
end
|
183
|
+
end # module Comparing
|
184
|
+
|
185
|
+
# -----------------------------------------------------------------------------------------
|
186
|
+
# Encoding: Make a string nice to be shown into an HTML string.
|
187
|
+
# -----------------------------------------------------------------------------------------
|
188
|
+
module Encoding
|
189
|
+
# Then it makes it compatible with UTF-8.
|
190
|
+
# More details here: https://bitbucket.org/leandro_sardi/blackstack/issues/961
|
191
|
+
def self.encode_string(s)
|
192
|
+
s.encode("UTF-8")
|
193
|
+
end
|
194
|
+
|
195
|
+
# Escape the string to be shown into an HTML screen.
|
196
|
+
# Then it makes it compatible with UTF-8.
|
197
|
+
# More details here: https://bitbucket.org/leandro_sardi/blackstack/issues/961
|
198
|
+
def self.encode_html(s)
|
199
|
+
encode_string(CGI.escapeHTML(s.to_s))
|
200
|
+
end
|
201
|
+
|
202
|
+
# Generates a description string from an exception object.
|
203
|
+
# Eescapes the string to be shown into an HTML screen.
|
204
|
+
# Makes it compatible with UTF-8.
|
205
|
+
# More details here: https://bitbucket.org/leandro_sardi/blackstack/issues/961
|
206
|
+
def self.encode_exception(e, include_backtrace=true)
|
207
|
+
ret = 'Error:' + encode_html(e.to_s)
|
208
|
+
if (include_backtrace == true)
|
209
|
+
e.backtrace.each { |s|
|
210
|
+
ret += "<br/>" + encode_html(s)
|
211
|
+
} # e.backtrace.each
|
212
|
+
end # if
|
213
|
+
ret
|
214
|
+
end
|
215
|
+
|
216
|
+
# Returns a string with a description of a period of time, to be shown in the screen.
|
217
|
+
# period: it may be 'H', 'D', 'W', 'M', 'Y'
|
218
|
+
# units: it is a positive integer
|
219
|
+
def self.encode_period(period, units)
|
220
|
+
s = "Last "
|
221
|
+
s += units.to_s + " " if units.to_i > 1
|
222
|
+
s += "Hours" if period.upcase == "H" && units.to_i != 1
|
223
|
+
s += "Days" if period.upcase == "D" && units.to_i != 1
|
224
|
+
s += "Weeks" if period.upcase == "W" && units.to_i != 1
|
225
|
+
s += "Months" if period.upcase == "M" && units.to_i != 1
|
226
|
+
s += "Years" if period.upcase == "Y" && units.to_i != 1
|
227
|
+
s += "Hour" if period.upcase == "H" && units.to_i == 1
|
228
|
+
s += "Day" if period.upcase == "D" && units.to_i == 1
|
229
|
+
s += "Week" if period.upcase == "W" && units.to_i == 1
|
230
|
+
s += "Month" if period.upcase == "M" && units.to_i == 1
|
231
|
+
s += "Year" if period.upcase == "Y" && units.to_i == 1
|
232
|
+
s
|
233
|
+
end
|
234
|
+
|
235
|
+
#
|
236
|
+
def self.encode_guid(s)
|
237
|
+
return s.gsub('{',"").gsub('}',"").upcase
|
238
|
+
end
|
239
|
+
|
240
|
+
#
|
241
|
+
def self.encode_javascript(s)
|
242
|
+
s.to_s.gsub("'", "\\\\'").gsub("\r", "' + String.fromCharCode(13) + '").gsub("\n", "' + String.fromCharCode(10) + '")
|
243
|
+
end
|
244
|
+
|
245
|
+
end # module Encoding
|
246
|
+
|
247
|
+
# -----------------------------------------------------------------------------------------
|
248
|
+
# DateTime
|
249
|
+
# -----------------------------------------------------------------------------------------
|
250
|
+
module DateTime
|
251
|
+
# Check the string has the format yyyymmddhhmmss.
|
252
|
+
# => Return true if success. Otherwise, return false.
|
253
|
+
# => Year cannot be lower than 1900.
|
254
|
+
# => Year cannot be higher or equal than 2100.
|
255
|
+
def self.datetime_api_check(s)
|
256
|
+
return false if (s.size!=14)
|
257
|
+
year = s[0..3]
|
258
|
+
month = s[4..5]
|
259
|
+
day = s[6..7]
|
260
|
+
hour = s[8..9]
|
261
|
+
minute = s[10..11]
|
262
|
+
second = s[12..13]
|
263
|
+
BlackStack::DateTime::Misc::datetime_values_check(year,month,day,hour,minute,second)
|
264
|
+
end # def datetime_api_check
|
265
|
+
|
266
|
+
# Check the string has the format yyyy-mm-dd hh:mm:ss.
|
267
|
+
# => Return true if success. Otherwise, return false.
|
268
|
+
# => Year cannot be lower than 1900.
|
269
|
+
# => Year cannot be higher or equal than 2100.
|
270
|
+
def self.datetime_sql_check(s)
|
271
|
+
return false if (s.size!=19)
|
272
|
+
year = s[0..3]
|
273
|
+
month = s[5..6]
|
274
|
+
day = s[8..9]
|
275
|
+
hour = s[11..12]
|
276
|
+
minute = s[14..15]
|
277
|
+
second = s[17..18]
|
278
|
+
BlackStack::DateTime::Misc::datetime_values_check(year,month,day,hour,minute,second)
|
279
|
+
end # def datetime_sql_check
|
280
|
+
|
281
|
+
# Convierte un string con formato api-datatime (yyyymmddhhmmss) a un string con formato sql-datetime (yyyy-mm-dd hh:mm:ss).
|
282
|
+
def self.datetime_api_to_sql(s)
|
283
|
+
raise "Wrong Api DataTime Format." if (datetime_api_check(s)==false)
|
284
|
+
year = s[0..3]
|
285
|
+
month = s[4..5]
|
286
|
+
day = s[6..7]
|
287
|
+
hour = s[8..9]
|
288
|
+
minute = s[10..11]
|
289
|
+
second = s[12..13]
|
290
|
+
ret = "#{year}-#{month}-#{day} #{hour}:#{minute}:#{second}"
|
291
|
+
return ret
|
292
|
+
end # def datetime_api_to_sql
|
293
|
+
|
294
|
+
# Convierte un string con formato sql-datatime a un string con formato sql-datetime.
|
295
|
+
def self.datetime_sql_to_api(s)
|
296
|
+
raise "Wrong SQL DataTime Format." if (datetime_sql_check(s)==false)
|
297
|
+
year = s[0..3]
|
298
|
+
month = s[5..6]
|
299
|
+
day = s[8..9]
|
300
|
+
hour = s[11..12]
|
301
|
+
minute = s[14..15]
|
302
|
+
second = s[17..18]
|
303
|
+
ret = "#{year}#{month}#{day}#{hour}#{minute}#{second}"
|
304
|
+
return ret
|
305
|
+
end # def datetime_sql_to_api
|
306
|
+
end # module DateTime
|
307
|
+
|
308
|
+
|
309
|
+
# -----------------------------------------------------------------------------------------
|
310
|
+
# Spinning
|
311
|
+
# -----------------------------------------------------------------------------------------
|
312
|
+
module Spinning
|
313
|
+
# Esta funcion retorna una variacion al azar del texto que se pasa.
|
314
|
+
# Esta funcion se ocupa de dividir el texto en partes, para eviar el error "too big to product" que arroja la libraría.
|
315
|
+
def self.random_spinning_variation(text)
|
316
|
+
ret = text
|
317
|
+
|
318
|
+
text.scan(MATCH_CONTENT_SPINNING).each { |s|
|
319
|
+
a = ContentSpinning.new(s).spin
|
320
|
+
rep = a[rand(a.size)]
|
321
|
+
ret = ret.gsub(s, rep)
|
322
|
+
a = nil
|
323
|
+
}
|
324
|
+
|
325
|
+
return ret
|
326
|
+
end
|
327
|
+
|
328
|
+
# retorna true si la sintaxis del texto spineado es correcta
|
329
|
+
# caso contrario retorna false
|
330
|
+
# no soporta spinnings anidados. ejemplo: {my|our|{a car of mine}}
|
331
|
+
def self.valid_spinning_syntax?(s)
|
332
|
+
# valido que exste
|
333
|
+
n = 0
|
334
|
+
s.split('').each { |c|
|
335
|
+
n+=1 if c=='{'
|
336
|
+
n-=1 if c=='}'
|
337
|
+
if n!=0 && n!=1
|
338
|
+
#raise "Closing spining char '}' with not previous opening spining char '{'." if n<0
|
339
|
+
#raise "Opening spining char '{' inside another spining block." if n>1
|
340
|
+
return false if n<0 # Closing spining char '}' with not previous opening spining char '{'.
|
341
|
+
return false if n>1 # Opening spining char '{' inside another spining block.
|
342
|
+
end
|
343
|
+
}
|
344
|
+
|
345
|
+
# obtengo cada uno de los spinnings
|
346
|
+
s.scan(MATCH_CONTENT_SPINNING).each { |x|
|
347
|
+
a = x.split('|')
|
348
|
+
raise "No variations delimited by '|' inside spinning block." if a.size <= 1
|
349
|
+
}
|
350
|
+
|
351
|
+
true
|
352
|
+
end
|
353
|
+
|
354
|
+
# returns true if the text is spinned.
|
355
|
+
# otherwise, returns false.
|
356
|
+
def self.spintax?(s)
|
357
|
+
s.scan(MATCH_CONTENT_SPINNING).size > 0
|
358
|
+
end
|
359
|
+
end # module Spinning
|
360
|
+
|
361
|
+
|
362
|
+
# -----------------------------------------------------------------------------------------
|
363
|
+
# Miscelaneus
|
364
|
+
# -----------------------------------------------------------------------------------------
|
365
|
+
module Misc
|
366
|
+
# make a Ruby string safe for a filesystem.
|
367
|
+
# References:
|
368
|
+
# => https://stackoverflow.com/questions/1939333/how-to-make-a-ruby-string-safe-for-a-filesystem
|
369
|
+
# => http://devblog.muziboo.com/2008/06/17/attachment-fu-sanitize-filename-regex-and-unicode-gotcha/
|
370
|
+
def self.sanitize_filename(filename)
|
371
|
+
ret = filename.strip do |name|
|
372
|
+
# NOTE: File.basename doesn't work right with Windows paths on Unix
|
373
|
+
# get only the filename, not the whole path
|
374
|
+
name.gsub!(/^.*(\\|\/)/, '')
|
375
|
+
|
376
|
+
# Strip out the non-ascii character
|
377
|
+
name.gsub!(/[^0-9A-Za-z.\-]/, '_')
|
378
|
+
end
|
379
|
+
return ret
|
380
|
+
end
|
381
|
+
end # module Misc
|
382
|
+
|
383
|
+
|
384
|
+
# -----------------------------------------------------------------------------------------
|
385
|
+
# Email Appending Functions
|
386
|
+
# -----------------------------------------------------------------------------------------
|
387
|
+
module Appending
|
388
|
+
APPEND_PATTERN_FNAME_DOT_LNAME = 0
|
389
|
+
APPEND_PATTERN_FNAME = 1
|
390
|
+
APPEND_PATTERN_LNAME = 2
|
391
|
+
APPEND_PATTERN_F_LNAME = 3
|
392
|
+
APPEND_PATTERN_F_DOT_LNAME = 4
|
393
|
+
|
394
|
+
#
|
395
|
+
def self.name_pattern(pattern, fname, lname)
|
396
|
+
if (pattern==APPEND_PATTERN_FNAME_DOT_LNAME)
|
397
|
+
return "#{fname}.#{lname}"
|
398
|
+
elsif (pattern==APPEND_PATTERN_FNAME)
|
399
|
+
return "#{fname}"
|
400
|
+
elsif (pattern==APPEND_PATTERN_LNAME)
|
401
|
+
return "#{lname}"
|
402
|
+
elsif (pattern==APPEND_PATTERN_F_LNAME)
|
403
|
+
return "#{fname[0]}#{lname}"
|
404
|
+
elsif (pattern==APPEND_PATTERN_F_DOT_LNAME)
|
405
|
+
return "#{fname[0]}.#{lname}"
|
406
|
+
else
|
407
|
+
raise "getNamePattern: Unknown pattern code."
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
411
|
+
#
|
412
|
+
def self.get_email_variations(first_name, last_name, domain, is_a_big_company)
|
413
|
+
variations = Array.new
|
414
|
+
variations << first_name + "." + last_name + "@" + domain
|
415
|
+
variations << first_name[0] + last_name + "@" + domain
|
416
|
+
variations << first_name + "_" + last_name + "@" + domain
|
417
|
+
variations << first_name[0] + "." + last_name + "@" + domain
|
418
|
+
if (is_a_big_company == false)
|
419
|
+
variations << last_name + "@" + domain
|
420
|
+
variations << first_name + "@" + domain
|
421
|
+
end
|
422
|
+
#variations << first_name + "." + last_name + "@" + domain
|
423
|
+
#variations << first_name + "_" + last_name + "@" + domain
|
424
|
+
#variations << last_name + "." + first_name + "@" + domain
|
425
|
+
#variations << last_name + "_" + first_name + "@" + domain
|
426
|
+
#variations << first_name[0] + "." + last_name + "@" + domain
|
427
|
+
#variations << first_name + "." + last_name[0] + "@" + domain
|
428
|
+
#variations << last_name[0] + "." + first_name + "@" + domain
|
429
|
+
#variations << last_name + "." + first_name[0] + "@" + domain
|
430
|
+
#variations << first_name[0] + last_name + "@" + domain
|
431
|
+
#variations << first_name + last_name[0] + "@" + domain
|
432
|
+
#variations << last_name[0] + first_name + "@" + domain
|
433
|
+
#variations << last_name + first_name[0] + "@" + domain
|
434
|
+
#variations << first_name + "@" + domain
|
435
|
+
#variations << last_name + "@" + domain
|
436
|
+
return variations
|
437
|
+
end
|
438
|
+
end # module Appending
|
439
|
+
end # module String
|
440
|
+
|
441
|
+
# -----------------------------------------------------------------------------------------
|
442
|
+
# Network
|
443
|
+
# -----------------------------------------------------------------------------------------
|
444
|
+
module Netting
|
445
|
+
CALL_METHOD_GET = 'get'
|
446
|
+
CALL_METHOD_POST = 'post'
|
447
|
+
DEFAULT_SSL_VERIFY_MODE = OpenSSL::SSL::VERIFY_NONE
|
448
|
+
SUCCESS = 'success'
|
449
|
+
|
450
|
+
# New call_get
|
451
|
+
def self.call_get(uri, params = {}, ssl_verify_mode=BlackStack::Netting::DEFAULT_SSL_VERIFY_MODE)
|
452
|
+
uri.query = URI.encode_www_form(params)
|
453
|
+
Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https', :verify_mode => ssl_verify_mode) do |http|
|
454
|
+
req = Net::HTTP::Get.new uri
|
455
|
+
res = http.request req
|
456
|
+
case res
|
457
|
+
when Net::HTTPSuccess then res
|
458
|
+
when Net::HTTPRedirection then BlackStack::Netting::call_get(URI(res['location']), params)
|
459
|
+
else
|
460
|
+
res.error!
|
461
|
+
end
|
462
|
+
end
|
463
|
+
end
|
464
|
+
|
465
|
+
# New call_post
|
466
|
+
def self.call_post(uri, params = {}, ssl_verify_mode=BlackStack::Netting::DEFAULT_SSL_VERIFY_MODE)
|
467
|
+
Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https', :verify_mode => ssl_verify_mode) do |http|
|
468
|
+
req = Net::HTTP::Post.new(uri)
|
469
|
+
req['Content-Type'] = 'application/json'
|
470
|
+
req.set_form_data(params)
|
471
|
+
res = http.request req
|
472
|
+
case res
|
473
|
+
when Net::HTTPSuccess then res
|
474
|
+
when Net::HTTPRedirection then BlackStack::Netting::call_post(URI(res['location']), params)
|
475
|
+
else
|
476
|
+
res.error!
|
477
|
+
end
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
481
|
+
#
|
482
|
+
def self.api_call(url, params={}, method=BlackStack::Netting::CALL_METHOD_POST, ssl_verify_mode=BlackStack::Netting::DEFAULT_SSL_VERIFY_MODE, max_retries=5)
|
483
|
+
nTries = 0
|
484
|
+
bSuccess = false
|
485
|
+
parsed = nil
|
486
|
+
sError = ""
|
487
|
+
while (nTries < max_retries && bSuccess == false)
|
488
|
+
begin
|
489
|
+
nTries = nTries + 1
|
490
|
+
uri = URI(url)
|
491
|
+
res = BlackStack::Netting::call_post(uri, params, ssl_verify_mode) if method==BlackStack::Netting::CALL_METHOD_POST
|
492
|
+
res = BlackStack::Netting::call_get(uri, params, ssl_verify_mode) if method==BlackStack::Netting::CALL_METHOD_GET
|
493
|
+
parsed = JSON.parse(res.body)
|
494
|
+
if (parsed['status']==BlackStack::Netting::SUCCESS)
|
495
|
+
bSuccess = true
|
496
|
+
else
|
497
|
+
sError = "Status: #{parsed['status'].to_s}. Description: #{parsed['value'].to_s}."
|
498
|
+
end
|
499
|
+
rescue Errno::ECONNREFUSED => e
|
500
|
+
sError = "Errno::ECONNREFUSED:" + e.to_s
|
501
|
+
rescue => e2
|
502
|
+
sError = "Exception:" + e2.to_s
|
503
|
+
end
|
504
|
+
end # while
|
505
|
+
|
506
|
+
if (bSuccess==false)
|
507
|
+
raise "#{sError}"
|
508
|
+
end
|
509
|
+
end # apicall
|
510
|
+
|
511
|
+
# Download a file from an url to a local folder.
|
512
|
+
# url: must be somedomain.net instead of somedomain.net/, otherwise, it will throw exception.
|
513
|
+
# to: must be a valid path to a folder.
|
514
|
+
def self.download(url, to)
|
515
|
+
uri = URI(url)
|
516
|
+
domain = uri.host.start_with?('www.') ? uri.host[4..-1] : uri.host
|
517
|
+
path = uri.path
|
518
|
+
filename = path.split("/").last
|
519
|
+
Net::HTTP.start(domain) do |http|
|
520
|
+
resp = http.get(path)
|
521
|
+
open(to, "wb") do |file|
|
522
|
+
file.write(resp.body)
|
523
|
+
end
|
524
|
+
end
|
525
|
+
end
|
526
|
+
|
527
|
+
# Return the extension of the last path into an URL.
|
528
|
+
# Example: get_url_extension("http://connect.data.com/sitemap_index.xml?foo_param=foo_value") => ".xml"
|
529
|
+
def self.get_url_extension(url)
|
530
|
+
return File.extname(URI.parse(url).path.to_s)
|
531
|
+
end
|
532
|
+
|
533
|
+
# Removes the 'www.' from an URL.
|
534
|
+
def self.get_host_without_www(url)
|
535
|
+
url = "http://#{url}" if URI.parse(url).scheme.nil?
|
536
|
+
host = URI.parse(url).host.downcase
|
537
|
+
host.start_with?('www.') ? host[4..-1] : host
|
538
|
+
end
|
539
|
+
|
540
|
+
# Get the final URL if a web page is redirecting.
|
541
|
+
def self.get_redirect(url)
|
542
|
+
uri = URI.parse(url)
|
543
|
+
protocol = uri.scheme
|
544
|
+
host = uri.host.downcase
|
545
|
+
res = Net::HTTP.get_response(uri)
|
546
|
+
"#{protocol}://#{host}#{res['location']}"
|
547
|
+
end
|
548
|
+
|
549
|
+
# returns the age in days of the given file
|
550
|
+
def self.file_age(filename)
|
551
|
+
(Time.now - File.ctime(filename))/(24*3600)
|
552
|
+
end
|
553
|
+
end # module Netting
|
554
|
+
|
555
|
+
end # module BlackStack
|
data/lib/string.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
class String
|
2
|
+
# returns true if the string meets all the security requirements for a password
|
3
|
+
def password?
|
4
|
+
return true if self.to_s =~ BlackStack::Strings::MATCH_PASSWORD
|
5
|
+
return false
|
6
|
+
end
|
7
|
+
|
8
|
+
# returns true if the string match with the regex of a GUID
|
9
|
+
def guid?
|
10
|
+
return true if self.to_s =~ BlackStack::Strings::MATCH_GUID
|
11
|
+
return false
|
12
|
+
end
|
13
|
+
|
14
|
+
# returns true if the string match with the regex of a filename
|
15
|
+
def filename?
|
16
|
+
return true if self.to_s =~ BlackStack::Strings::MATCH_FILENAME
|
17
|
+
return false
|
18
|
+
end
|
19
|
+
|
20
|
+
# returns true if the string match with the regex of an email
|
21
|
+
def email?
|
22
|
+
return true if self.to_s =~ BlackStack::Strings::MATCH_EMAIL
|
23
|
+
return false
|
24
|
+
end
|
25
|
+
|
26
|
+
# returns true if the string match with the regex of a domain
|
27
|
+
def domain?
|
28
|
+
return true if self.to_s =~ BlackStack::Strings::MATCH_DOMAIN
|
29
|
+
return false
|
30
|
+
end
|
31
|
+
|
32
|
+
# returns true if the string match with the regex of a phone number
|
33
|
+
def phone?
|
34
|
+
return true if self.to_s =~ BlackStack::Strings::MATCH_PHONE
|
35
|
+
return false
|
36
|
+
end
|
37
|
+
|
38
|
+
# returns true if the string match with the regex of a URL
|
39
|
+
def url?
|
40
|
+
return true if self.to_s =~ BlackStack::Strings::MATCH_URL
|
41
|
+
return false
|
42
|
+
end
|
43
|
+
|
44
|
+
# returns true if the string match with the regex of a number
|
45
|
+
def fixnum?
|
46
|
+
return true if self.to_s =~ BlackStack::Strings::MATCH_FIXNUM
|
47
|
+
return false
|
48
|
+
end
|
49
|
+
|
50
|
+
# returns true if the string match with the regex of a datetime used in the BlackStack's API
|
51
|
+
def api_datetime?
|
52
|
+
BlackStack::Strings::DateTime::datetime_api_check(self.to_s)
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
def sql_datetime?
|
57
|
+
BlackStack::Strings::DateTime::datetime_sql_check(self.to_s)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Convierte un string con formato sql-datatime a un string con formato sql-datetime.
|
61
|
+
def sql_to_api_datetime
|
62
|
+
BlackStack::Strings::DateTime::datetime_sql_to_api(self.to_s)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Convierte un string con formato api-datatime (yyyymmddhhmmss) a un string con formato sql-datetime (yyyy-mm-dd hh:mm:ss).
|
66
|
+
def api_to_sql_datetime
|
67
|
+
BlackStack::Strings::DateTime::datetime_api_to_sql(self.to_s)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Rewrite a GUID as a standard format.
|
71
|
+
# Example: {331a92c3-5fe1-47a2-a31b-cfa439b5b4f9} -> 331A92C3-5FE1-47A2-A31B-CFA439B5B4F9
|
72
|
+
def to_guid
|
73
|
+
BlackStack::Strings::Encoding::encode_guid(self.to_s)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Escape simple-quotes too add the string into literal-string of a dynamic query build into the Ruby code.
|
77
|
+
# Example: "I'm BlackStack" -> "I''m BlackStack"
|
78
|
+
def to_sql
|
79
|
+
BlackStack::Strings::SQL::string_to_sql_string(self.to_s)
|
80
|
+
end
|
81
|
+
|
82
|
+
#
|
83
|
+
def spintax?
|
84
|
+
BlackStack::Strings::Spinning::spintax?(self.to_s)
|
85
|
+
end
|
86
|
+
|
87
|
+
#
|
88
|
+
def spintax?
|
89
|
+
BlackStack::Strings::Spinning::valid_spinning_syntax?(self.to_s) &&
|
90
|
+
BlackStack::Strings::Spinning::spintax?(self.to_s)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Returns a random spin from a spintax
|
94
|
+
def spin
|
95
|
+
BlackStack::Strings::Spinning::random_spinning_variation(self.to_s)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Then it makes it compatible with UTF-8.
|
99
|
+
# More details here: https://bitbucket.org/leandro_sardi/blackstack/issues/961
|
100
|
+
def encode_string()
|
101
|
+
BlackStack::Strings::Encoding::encode_string(self.to_s)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Escape the string to be shown into an HTML screen.
|
105
|
+
# Then it makes it compatible with UTF-8.
|
106
|
+
# More details here: https://bitbucket.org/leandro_sardi/blackstack/issues/961
|
107
|
+
def encode_html()
|
108
|
+
BlackStack::Strings::Encoding::encode_html(self.to_s)
|
109
|
+
end
|
110
|
+
|
111
|
+
end # class String
|
112
|
+
|
113
|
+
#i.to_label
|
114
|
+
|
115
|
+
#dt.to_sql
|
data/lib/time.rb
ADDED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: blackstack_commons
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Leandro Daniel Sardi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-11-
|
11
|
+
date: 2019-11-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: content_spinning
|
@@ -56,7 +56,16 @@ executables: []
|
|
56
56
|
extensions: []
|
57
57
|
extra_rdoc_files: []
|
58
58
|
files:
|
59
|
+
- examples/example01.rb
|
60
|
+
- examples/example02.rb
|
59
61
|
- lib/blackstack_commons.rb
|
62
|
+
- lib/datetime.rb
|
63
|
+
- lib/exception.rb
|
64
|
+
- lib/fixnum.rb
|
65
|
+
- lib/float.rb
|
66
|
+
- lib/functions.rb
|
67
|
+
- lib/string.rb
|
68
|
+
- lib/time.rb
|
60
69
|
homepage: https://rubygems.org/gems/blackstack_commons
|
61
70
|
licenses:
|
62
71
|
- MIT
|