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