br-utils 0.1.0
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 +7 -0
- data/.gitignore +120 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +21 -0
- data/README.md +348 -0
- data/Rakefile +6 -0
- data/examples/boleto_usage_example.rb +79 -0
- data/examples/cep_usage_example.rb +148 -0
- data/examples/cnh_usage_example.rb +120 -0
- data/examples/cnpj_usage_example.rb +227 -0
- data/examples/cpf_usage_example.rb +237 -0
- data/examples/currency_usage_example.rb +266 -0
- data/examples/date_usage_example.rb +259 -0
- data/examples/email_usage_example.rb +321 -0
- data/examples/legal_nature_usage_example.rb +437 -0
- data/examples/legal_process_usage_example.rb +444 -0
- data/examples/license_plate_usage_example.rb +440 -0
- data/examples/phone_usage_example.rb +595 -0
- data/examples/pis_usage_example.rb +588 -0
- data/examples/renavam_usage_example.rb +499 -0
- data/examples/voter_id_usage_example.rb +573 -0
- data/lib/brazilian-utils/boleto-utils.rb +176 -0
- data/lib/brazilian-utils/cep-utils.rb +330 -0
- data/lib/brazilian-utils/cnh-utils.rb +88 -0
- data/lib/brazilian-utils/cnpj-utils.rb +202 -0
- data/lib/brazilian-utils/cpf-utils.rb +192 -0
- data/lib/brazilian-utils/currency-utils.rb +226 -0
- data/lib/brazilian-utils/data/legal_process_ids.json +38 -0
- data/lib/brazilian-utils/date-utils.rb +244 -0
- data/lib/brazilian-utils/email-utils.rb +54 -0
- data/lib/brazilian-utils/legal-nature-utils.rb +235 -0
- data/lib/brazilian-utils/legal-process-utils.rb +240 -0
- data/lib/brazilian-utils/license-plate-utils.rb +279 -0
- data/lib/brazilian-utils/phone-utils.rb +272 -0
- data/lib/brazilian-utils/pis-utils.rb +151 -0
- data/lib/brazilian-utils/renavam-utils.rb +113 -0
- data/lib/brazilian-utils/voter-id-utils.rb +165 -0
- metadata +123 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
require_relative '../lib/brazilian-utils/date-utils'
|
|
2
|
+
require 'date'
|
|
3
|
+
|
|
4
|
+
puts "=" * 70
|
|
5
|
+
puts "Brazilian Date Utils - Usage Examples"
|
|
6
|
+
puts "=" * 70
|
|
7
|
+
puts
|
|
8
|
+
|
|
9
|
+
# ============================================================================
|
|
10
|
+
# Holiday Checking
|
|
11
|
+
# ============================================================================
|
|
12
|
+
puts "1. CHECKING NATIONAL HOLIDAYS"
|
|
13
|
+
puts "-" * 70
|
|
14
|
+
|
|
15
|
+
# New Year
|
|
16
|
+
new_year = Date.new(2024, 1, 1)
|
|
17
|
+
puts "New Year (Jan 1, 2024): #{BrazilianUtils::DateUtils.is_holiday(new_year)}"
|
|
18
|
+
|
|
19
|
+
# Christmas
|
|
20
|
+
christmas = Date.new(2024, 12, 25)
|
|
21
|
+
puts "Christmas (Dec 25, 2024): #{BrazilianUtils::DateUtils.is_holiday(christmas)}"
|
|
22
|
+
|
|
23
|
+
# Independence Day
|
|
24
|
+
independence = Date.new(2024, 9, 7)
|
|
25
|
+
puts "Independence Day (Sep 7, 2024): #{BrazilianUtils::DateUtils.is_holiday(independence)}"
|
|
26
|
+
|
|
27
|
+
# Labor Day
|
|
28
|
+
labor_day = Date.new(2024, 5, 1)
|
|
29
|
+
puts "Labor Day (May 1, 2024): #{BrazilianUtils::DateUtils.is_holiday(labor_day)}"
|
|
30
|
+
|
|
31
|
+
# Regular day
|
|
32
|
+
regular_day = Date.new(2024, 3, 15)
|
|
33
|
+
puts "Regular day (Mar 15, 2024): #{BrazilianUtils::DateUtils.is_holiday(regular_day)}"
|
|
34
|
+
puts
|
|
35
|
+
|
|
36
|
+
# ============================================================================
|
|
37
|
+
# State Holidays
|
|
38
|
+
# ============================================================================
|
|
39
|
+
puts "2. CHECKING STATE-SPECIFIC HOLIDAYS"
|
|
40
|
+
puts "-" * 70
|
|
41
|
+
|
|
42
|
+
# São Paulo state holiday (July 9)
|
|
43
|
+
sp_holiday = Date.new(2024, 7, 9)
|
|
44
|
+
puts "July 9, 2024 in São Paulo: #{BrazilianUtils::DateUtils.is_holiday(sp_holiday, 'SP')}"
|
|
45
|
+
puts "July 9, 2024 in Rio de Janeiro: #{BrazilianUtils::DateUtils.is_holiday(sp_holiday, 'RJ')}"
|
|
46
|
+
puts "July 9, 2024 in Minas Gerais: #{BrazilianUtils::DateUtils.is_holiday(sp_holiday, 'MG')}"
|
|
47
|
+
puts
|
|
48
|
+
|
|
49
|
+
# Rio de Janeiro state holiday (November 20 - Consciência Negra)
|
|
50
|
+
rj_holiday = Date.new(2024, 11, 20)
|
|
51
|
+
puts "November 20, 2024 in Rio de Janeiro: #{BrazilianUtils::DateUtils.is_holiday(rj_holiday, 'RJ')}"
|
|
52
|
+
puts "November 20, 2024 in São Paulo: #{BrazilianUtils::DateUtils.is_holiday(rj_holiday, 'SP')}"
|
|
53
|
+
puts "November 20, 2024 in Mato Grosso: #{BrazilianUtils::DateUtils.is_holiday(rj_holiday, 'MT')}"
|
|
54
|
+
puts
|
|
55
|
+
|
|
56
|
+
# Bahia state holiday (July 2)
|
|
57
|
+
ba_holiday = Date.new(2024, 7, 2)
|
|
58
|
+
puts "July 2, 2024 in Bahia: #{BrazilianUtils::DateUtils.is_holiday(ba_holiday, 'BA')}"
|
|
59
|
+
puts "July 2, 2024 in São Paulo: #{BrazilianUtils::DateUtils.is_holiday(ba_holiday, 'SP')}"
|
|
60
|
+
puts
|
|
61
|
+
|
|
62
|
+
# ============================================================================
|
|
63
|
+
# Testing Today
|
|
64
|
+
# ============================================================================
|
|
65
|
+
puts "3. CHECKING TODAY'S DATE"
|
|
66
|
+
puts "-" * 70
|
|
67
|
+
|
|
68
|
+
today = Date.today
|
|
69
|
+
puts "Today is: #{today.strftime('%d/%m/%Y')}"
|
|
70
|
+
puts "Is today a national holiday? #{BrazilianUtils::DateUtils.is_holiday(today)}"
|
|
71
|
+
puts "Is today a holiday in SP? #{BrazilianUtils::DateUtils.is_holiday(today, 'SP')}"
|
|
72
|
+
puts "Is today a holiday in RJ? #{BrazilianUtils::DateUtils.is_holiday(today, 'RJ')}"
|
|
73
|
+
puts
|
|
74
|
+
|
|
75
|
+
# ============================================================================
|
|
76
|
+
# Different Date Types
|
|
77
|
+
# ============================================================================
|
|
78
|
+
puts "4. TESTING DIFFERENT DATE TYPES"
|
|
79
|
+
puts "-" * 70
|
|
80
|
+
|
|
81
|
+
date_obj = Date.new(2024, 12, 25)
|
|
82
|
+
datetime_obj = DateTime.new(2024, 12, 25, 10, 30, 0)
|
|
83
|
+
time_obj = Time.new(2024, 12, 25, 10, 30, 0)
|
|
84
|
+
|
|
85
|
+
puts "Date object (Christmas): #{BrazilianUtils::DateUtils.is_holiday(date_obj)}"
|
|
86
|
+
puts "DateTime object (Christmas): #{BrazilianUtils::DateUtils.is_holiday(datetime_obj)}"
|
|
87
|
+
puts "Time object (Christmas): #{BrazilianUtils::DateUtils.is_holiday(time_obj)}"
|
|
88
|
+
puts
|
|
89
|
+
|
|
90
|
+
# ============================================================================
|
|
91
|
+
# Invalid Inputs
|
|
92
|
+
# ============================================================================
|
|
93
|
+
puts "5. TESTING INVALID INPUTS"
|
|
94
|
+
puts "-" * 70
|
|
95
|
+
|
|
96
|
+
puts "String date '2024-01-01': #{BrazilianUtils::DateUtils.is_holiday('2024-01-01').inspect}"
|
|
97
|
+
puts "Invalid UF 'XX': #{BrazilianUtils::DateUtils.is_holiday(Date.new(2024, 1, 1), 'XX').inspect}"
|
|
98
|
+
puts "Invalid UF 'Invalid': #{BrazilianUtils::DateUtils.is_holiday(Date.new(2024, 1, 1), 'Invalid').inspect}"
|
|
99
|
+
puts
|
|
100
|
+
|
|
101
|
+
# ============================================================================
|
|
102
|
+
# Date to Text Conversion
|
|
103
|
+
# ============================================================================
|
|
104
|
+
puts "6. CONVERTING DATES TO TEXT"
|
|
105
|
+
puts "-" * 70
|
|
106
|
+
|
|
107
|
+
# Regular dates
|
|
108
|
+
date1 = '15/03/2024'
|
|
109
|
+
puts "#{date1}: #{BrazilianUtils::DateUtils.convert_date_to_text(date1)}"
|
|
110
|
+
|
|
111
|
+
date2 = '25/12/2023'
|
|
112
|
+
puts "#{date2}: #{BrazilianUtils::DateUtils.convert_date_to_text(date2)}"
|
|
113
|
+
|
|
114
|
+
# First day of month (special case using "Primeiro")
|
|
115
|
+
date3 = '01/01/2024'
|
|
116
|
+
puts "#{date3}: #{BrazilianUtils::DateUtils.convert_date_to_text(date3)}"
|
|
117
|
+
|
|
118
|
+
date4 = '01/05/2024'
|
|
119
|
+
puts "#{date4}: #{BrazilianUtils::DateUtils.convert_date_to_text(date4)}"
|
|
120
|
+
|
|
121
|
+
# Different months
|
|
122
|
+
date5 = '21/04/2024'
|
|
123
|
+
puts "#{date5}: #{BrazilianUtils::DateUtils.convert_date_to_text(date5)}"
|
|
124
|
+
|
|
125
|
+
date6 = '07/09/2024'
|
|
126
|
+
puts "#{date6}: #{BrazilianUtils::DateUtils.convert_date_to_text(date6)}"
|
|
127
|
+
puts
|
|
128
|
+
|
|
129
|
+
# ============================================================================
|
|
130
|
+
# Brazilian National Holidays in Text
|
|
131
|
+
# ============================================================================
|
|
132
|
+
puts "7. BRAZILIAN NATIONAL HOLIDAYS IN TEXT FORMAT"
|
|
133
|
+
puts "-" * 70
|
|
134
|
+
|
|
135
|
+
national_holidays = [
|
|
136
|
+
'01/01/2024', # New Year
|
|
137
|
+
'21/04/2024', # Tiradentes
|
|
138
|
+
'01/05/2024', # Labor Day
|
|
139
|
+
'07/09/2024', # Independence Day
|
|
140
|
+
'12/10/2024', # Nossa Senhora Aparecida
|
|
141
|
+
'02/11/2024', # All Souls Day
|
|
142
|
+
'15/11/2024', # Proclamation of the Republic
|
|
143
|
+
'25/12/2024' # Christmas
|
|
144
|
+
]
|
|
145
|
+
|
|
146
|
+
national_holidays.each do |holiday|
|
|
147
|
+
text = BrazilianUtils::DateUtils.convert_date_to_text(holiday)
|
|
148
|
+
puts "#{holiday}: #{text}"
|
|
149
|
+
end
|
|
150
|
+
puts
|
|
151
|
+
|
|
152
|
+
# ============================================================================
|
|
153
|
+
# Invalid Date Conversions
|
|
154
|
+
# ============================================================================
|
|
155
|
+
puts "8. TESTING INVALID DATE CONVERSIONS"
|
|
156
|
+
puts "-" * 70
|
|
157
|
+
|
|
158
|
+
invalid_dates = [
|
|
159
|
+
'32/01/2024', # Invalid day
|
|
160
|
+
'29/02/2023', # Not a leap year
|
|
161
|
+
'01-01-2024', # Wrong separator
|
|
162
|
+
'2024/01/01', # Wrong format
|
|
163
|
+
'00/01/2024', # Day zero
|
|
164
|
+
'01/13/2024', # Invalid month
|
|
165
|
+
'invalid', # Non-date string
|
|
166
|
+
'' # Empty string
|
|
167
|
+
]
|
|
168
|
+
|
|
169
|
+
invalid_dates.each do |date|
|
|
170
|
+
result = BrazilianUtils::DateUtils.convert_date_to_text(date)
|
|
171
|
+
puts "#{date.inspect}: #{result.inspect}"
|
|
172
|
+
end
|
|
173
|
+
puts
|
|
174
|
+
|
|
175
|
+
# ============================================================================
|
|
176
|
+
# Practical Use Case: Document Date
|
|
177
|
+
# ============================================================================
|
|
178
|
+
puts "9. PRACTICAL USE CASE: DOCUMENT FORMATTING"
|
|
179
|
+
puts "-" * 70
|
|
180
|
+
|
|
181
|
+
document_date = '15/03/2024'
|
|
182
|
+
formatted_date = BrazilianUtils::DateUtils.convert_date_to_text(document_date)
|
|
183
|
+
|
|
184
|
+
puts "Contract Template:"
|
|
185
|
+
puts "-" * 70
|
|
186
|
+
puts "Contrato celebrado em São Paulo, aos #{formatted_date}."
|
|
187
|
+
puts
|
|
188
|
+
puts "Invoice Template:"
|
|
189
|
+
puts "-" * 70
|
|
190
|
+
puts "Nota Fiscal emitida em: #{formatted_date.capitalize}"
|
|
191
|
+
puts
|
|
192
|
+
|
|
193
|
+
# ============================================================================
|
|
194
|
+
# Checking Multiple States
|
|
195
|
+
# ============================================================================
|
|
196
|
+
puts "10. CHECKING HOLIDAYS ACROSS ALL STATES"
|
|
197
|
+
puts "-" * 70
|
|
198
|
+
|
|
199
|
+
test_date = Date.new(2024, 11, 20) # Consciência Negra
|
|
200
|
+
states = %w[SP RJ MG BA RS PR SC PE CE GO DF]
|
|
201
|
+
|
|
202
|
+
puts "Date: November 20, 2024 (Consciência Negra)"
|
|
203
|
+
puts "Holiday Status by State:"
|
|
204
|
+
states.each do |state|
|
|
205
|
+
is_holiday = BrazilianUtils::DateUtils.is_holiday(test_date, state)
|
|
206
|
+
status = is_holiday ? "✓ Holiday" : "✗ Not a holiday"
|
|
207
|
+
puts " #{state}: #{status}"
|
|
208
|
+
end
|
|
209
|
+
puts
|
|
210
|
+
|
|
211
|
+
# ============================================================================
|
|
212
|
+
# Leap Year Handling
|
|
213
|
+
# ============================================================================
|
|
214
|
+
puts "11. LEAP YEAR DATE HANDLING"
|
|
215
|
+
puts "-" * 70
|
|
216
|
+
|
|
217
|
+
leap_date = '29/02/2024'
|
|
218
|
+
non_leap_date = '29/02/2023'
|
|
219
|
+
|
|
220
|
+
puts "#{leap_date}: #{BrazilianUtils::DateUtils.convert_date_to_text(leap_date)}"
|
|
221
|
+
puts "#{non_leap_date}: #{BrazilianUtils::DateUtils.convert_date_to_text(non_leap_date).inspect} (invalid)"
|
|
222
|
+
puts
|
|
223
|
+
|
|
224
|
+
# ============================================================================
|
|
225
|
+
# Combined Example: Check Holiday and Convert to Text
|
|
226
|
+
# ============================================================================
|
|
227
|
+
puts "12. COMBINED EXAMPLE: HOLIDAY CHECK + TEXT CONVERSION"
|
|
228
|
+
puts "-" * 70
|
|
229
|
+
|
|
230
|
+
def format_holiday_info(date_str, uf = nil)
|
|
231
|
+
begin
|
|
232
|
+
day, month, year = date_str.split('/').map(&:to_i)
|
|
233
|
+
date_obj = Date.new(year, month, day)
|
|
234
|
+
|
|
235
|
+
is_holiday = BrazilianUtils::DateUtils.is_holiday(date_obj, uf)
|
|
236
|
+
text = BrazilianUtils::DateUtils.convert_date_to_text(date_str)
|
|
237
|
+
|
|
238
|
+
puts "Data: #{date_str}"
|
|
239
|
+
puts "Por extenso: #{text}"
|
|
240
|
+
if uf
|
|
241
|
+
puts "Feriado em #{uf}? #{is_holiday ? 'Sim' : 'Não'}"
|
|
242
|
+
else
|
|
243
|
+
puts "Feriado nacional? #{is_holiday ? 'Sim' : 'Não'}"
|
|
244
|
+
end
|
|
245
|
+
puts
|
|
246
|
+
rescue => e
|
|
247
|
+
puts "Erro ao processar #{date_str}: #{e.message}"
|
|
248
|
+
puts
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
format_holiday_info('25/12/2024')
|
|
253
|
+
format_holiday_info('09/07/2024', 'SP')
|
|
254
|
+
format_holiday_info('15/03/2024')
|
|
255
|
+
format_holiday_info('01/01/2024', 'RJ')
|
|
256
|
+
|
|
257
|
+
puts "=" * 70
|
|
258
|
+
puts "Examples completed!"
|
|
259
|
+
puts "=" * 70
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
require_relative '../lib/brazilian-utils/email-utils'
|
|
2
|
+
|
|
3
|
+
puts "=" * 70
|
|
4
|
+
puts "Brazilian Email Utils - Usage Examples"
|
|
5
|
+
puts "=" * 70
|
|
6
|
+
puts
|
|
7
|
+
|
|
8
|
+
# ============================================================================
|
|
9
|
+
# Valid Email Addresses
|
|
10
|
+
# ============================================================================
|
|
11
|
+
puts "1. VALID EMAIL ADDRESSES"
|
|
12
|
+
puts "-" * 70
|
|
13
|
+
|
|
14
|
+
valid_emails = [
|
|
15
|
+
'brutils@brutils.com',
|
|
16
|
+
'user.name@example.com',
|
|
17
|
+
'user+tag@example.co.uk',
|
|
18
|
+
'user_123@test-domain.com',
|
|
19
|
+
'contact@company.com.br',
|
|
20
|
+
'john.doe@gmail.com',
|
|
21
|
+
'jane.smith@outlook.com',
|
|
22
|
+
'first.middle.last@example.com',
|
|
23
|
+
'employee@mail.example.com',
|
|
24
|
+
'user2024@example.com',
|
|
25
|
+
'User.Name@Example.COM'
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
valid_emails.each do |email|
|
|
29
|
+
result = BrazilianUtils::EmailUtils.is_valid(email)
|
|
30
|
+
status = result ? "✓ VALID" : "✗ INVALID"
|
|
31
|
+
puts "#{status.ljust(10)} #{email}"
|
|
32
|
+
end
|
|
33
|
+
puts
|
|
34
|
+
|
|
35
|
+
# ============================================================================
|
|
36
|
+
# Invalid Email Addresses
|
|
37
|
+
# ============================================================================
|
|
38
|
+
puts "2. INVALID EMAIL ADDRESSES"
|
|
39
|
+
puts "-" * 70
|
|
40
|
+
|
|
41
|
+
invalid_emails = [
|
|
42
|
+
'invalid-email@brutils', # No TLD
|
|
43
|
+
'.user@example.com', # Starts with dot
|
|
44
|
+
'user@', # No domain
|
|
45
|
+
'@example.com', # No local part
|
|
46
|
+
'user name@example.com', # Contains space
|
|
47
|
+
'user@example.c', # TLD too short
|
|
48
|
+
'user@@example.com', # Double @
|
|
49
|
+
'user..name@example.com', # Consecutive dots
|
|
50
|
+
'userexample.com', # No @ symbol
|
|
51
|
+
'user@examplecom', # No dot in domain
|
|
52
|
+
'user[name]@example.com', # Invalid characters
|
|
53
|
+
'', # Empty string
|
|
54
|
+
' user@example.com', # Leading space
|
|
55
|
+
'user@example.com ' # Trailing space
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
invalid_emails.each do |email|
|
|
59
|
+
result = BrazilianUtils::EmailUtils.is_valid(email)
|
|
60
|
+
status = result ? "✓ VALID" : "✗ INVALID"
|
|
61
|
+
display_email = email.empty? ? '(empty string)' : email.inspect
|
|
62
|
+
puts "#{status.ljust(10)} #{display_email}"
|
|
63
|
+
end
|
|
64
|
+
puts
|
|
65
|
+
|
|
66
|
+
# ============================================================================
|
|
67
|
+
# Using the valid? Alias
|
|
68
|
+
# ============================================================================
|
|
69
|
+
puts "3. USING THE valid? ALIAS"
|
|
70
|
+
puts "-" * 70
|
|
71
|
+
|
|
72
|
+
test_email = 'user@example.com'
|
|
73
|
+
puts "BrazilianUtils::EmailUtils.is_valid('#{test_email}'): #{BrazilianUtils::EmailUtils.is_valid(test_email)}"
|
|
74
|
+
puts "BrazilianUtils::EmailUtils.valid?('#{test_email}'): #{BrazilianUtils::EmailUtils.valid?(test_email)}"
|
|
75
|
+
puts
|
|
76
|
+
|
|
77
|
+
# ============================================================================
|
|
78
|
+
# Non-String Inputs
|
|
79
|
+
# ============================================================================
|
|
80
|
+
puts "4. NON-STRING INPUTS"
|
|
81
|
+
puts "-" * 70
|
|
82
|
+
|
|
83
|
+
non_string_inputs = [
|
|
84
|
+
[nil, 'nil'],
|
|
85
|
+
[123, 'Integer (123)'],
|
|
86
|
+
[12.34, 'Float (12.34)'],
|
|
87
|
+
[true, 'Boolean (true)'],
|
|
88
|
+
[['user@example.com'], 'Array'],
|
|
89
|
+
[{ email: 'user@example.com' }, 'Hash'],
|
|
90
|
+
[:email, 'Symbol']
|
|
91
|
+
]
|
|
92
|
+
|
|
93
|
+
non_string_inputs.each do |value, description|
|
|
94
|
+
result = BrazilianUtils::EmailUtils.is_valid(value)
|
|
95
|
+
status = result ? "✓ VALID" : "✗ INVALID"
|
|
96
|
+
puts "#{status.ljust(10)} #{description}"
|
|
97
|
+
end
|
|
98
|
+
puts
|
|
99
|
+
|
|
100
|
+
# ============================================================================
|
|
101
|
+
# Practical Use Case: Form Validation
|
|
102
|
+
# ============================================================================
|
|
103
|
+
puts "5. PRACTICAL USE CASE: FORM VALIDATION"
|
|
104
|
+
puts "-" * 70
|
|
105
|
+
|
|
106
|
+
def validate_contact_form(name, email, message)
|
|
107
|
+
errors = []
|
|
108
|
+
|
|
109
|
+
errors << "Name is required" if name.nil? || name.empty?
|
|
110
|
+
errors << "Email is required" if email.nil? || email.empty?
|
|
111
|
+
errors << "Invalid email format" unless BrazilianUtils::EmailUtils.valid?(email)
|
|
112
|
+
errors << "Message is required" if message.nil? || message.empty?
|
|
113
|
+
|
|
114
|
+
if errors.empty?
|
|
115
|
+
{ valid: true, message: "Form is valid" }
|
|
116
|
+
else
|
|
117
|
+
{ valid: false, errors: errors }
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Test cases
|
|
122
|
+
test_forms = [
|
|
123
|
+
{ name: 'João Silva', email: 'joao@example.com', message: 'Hello!' },
|
|
124
|
+
{ name: 'Maria Santos', email: 'invalid-email', message: 'Hi!' },
|
|
125
|
+
{ name: '', email: 'maria@example.com', message: 'Test' },
|
|
126
|
+
{ name: 'Pedro Costa', email: 'pedro@company.com.br', message: '' },
|
|
127
|
+
{ name: 'Ana Lima', email: '', message: 'Message' }
|
|
128
|
+
]
|
|
129
|
+
|
|
130
|
+
test_forms.each_with_index do |form, index|
|
|
131
|
+
puts "\nTest #{index + 1}:"
|
|
132
|
+
puts " Name: #{form[:name].inspect}"
|
|
133
|
+
puts " Email: #{form[:email].inspect}"
|
|
134
|
+
puts " Message: #{form[:message].inspect}"
|
|
135
|
+
|
|
136
|
+
result = validate_contact_form(form[:name], form[:email], form[:message])
|
|
137
|
+
|
|
138
|
+
if result[:valid]
|
|
139
|
+
puts " Result: ✓ #{result[:message]}"
|
|
140
|
+
else
|
|
141
|
+
puts " Result: ✗ Errors:"
|
|
142
|
+
result[:errors].each do |error|
|
|
143
|
+
puts " - #{error}"
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
puts
|
|
148
|
+
|
|
149
|
+
# ============================================================================
|
|
150
|
+
# Batch Email Validation
|
|
151
|
+
# ============================================================================
|
|
152
|
+
puts "6. BATCH EMAIL VALIDATION"
|
|
153
|
+
puts "-" * 70
|
|
154
|
+
|
|
155
|
+
email_list = [
|
|
156
|
+
'john.doe@gmail.com',
|
|
157
|
+
'invalid@domain',
|
|
158
|
+
'jane+newsletter@example.com',
|
|
159
|
+
'@incomplete.com',
|
|
160
|
+
'corporate@company.com.br',
|
|
161
|
+
'user..name@example.com',
|
|
162
|
+
'contact@subdomain.example.com',
|
|
163
|
+
'user@example.c',
|
|
164
|
+
'valid.email_123+tag@test-server.co.uk'
|
|
165
|
+
]
|
|
166
|
+
|
|
167
|
+
valid_emails = []
|
|
168
|
+
invalid_emails = []
|
|
169
|
+
|
|
170
|
+
email_list.each do |email|
|
|
171
|
+
if BrazilianUtils::EmailUtils.valid?(email)
|
|
172
|
+
valid_emails << email
|
|
173
|
+
else
|
|
174
|
+
invalid_emails << email
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
puts "Total emails: #{email_list.length}"
|
|
179
|
+
puts "Valid emails: #{valid_emails.length}"
|
|
180
|
+
puts "Invalid emails: #{invalid_emails.length}"
|
|
181
|
+
puts
|
|
182
|
+
puts "Valid emails:"
|
|
183
|
+
valid_emails.each { |email| puts " ✓ #{email}" }
|
|
184
|
+
puts
|
|
185
|
+
puts "Invalid emails:"
|
|
186
|
+
invalid_emails.each { |email| puts " ✗ #{email}" }
|
|
187
|
+
puts
|
|
188
|
+
|
|
189
|
+
# ============================================================================
|
|
190
|
+
# Real-World Email Examples
|
|
191
|
+
# ============================================================================
|
|
192
|
+
puts "7. REAL-WORLD EMAIL EXAMPLES"
|
|
193
|
+
puts "-" * 70
|
|
194
|
+
|
|
195
|
+
real_world_examples = {
|
|
196
|
+
'Gmail' => 'john.doe+spam@gmail.com',
|
|
197
|
+
'Outlook' => 'jane.smith@outlook.com',
|
|
198
|
+
'Corporate' => 'employee@company.com',
|
|
199
|
+
'Brazilian domain' => 'contato@empresa.com.br',
|
|
200
|
+
'Subdomain' => 'support@help.example.com',
|
|
201
|
+
'Government' => 'contato@governo.gov.br',
|
|
202
|
+
'University' => 'aluno@universidade.edu.br',
|
|
203
|
+
'With numbers' => 'user2024@example.com',
|
|
204
|
+
'With underscores' => 'first_last@example.com',
|
|
205
|
+
'Multiple dots' => 'first.middle.last@example.com'
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
real_world_examples.each do |category, email|
|
|
209
|
+
result = BrazilianUtils::EmailUtils.valid?(email)
|
|
210
|
+
status = result ? "✓" : "✗"
|
|
211
|
+
puts "#{status} #{category.ljust(18)}: #{email}"
|
|
212
|
+
end
|
|
213
|
+
puts
|
|
214
|
+
|
|
215
|
+
# ============================================================================
|
|
216
|
+
# Email Validation with Feedback
|
|
217
|
+
# ============================================================================
|
|
218
|
+
puts "8. EMAIL VALIDATION WITH DETAILED FEEDBACK"
|
|
219
|
+
puts "-" * 70
|
|
220
|
+
|
|
221
|
+
def validate_email_with_feedback(email)
|
|
222
|
+
unless email.is_a?(String)
|
|
223
|
+
return { valid: false, message: "Email must be a string, got #{email.class}" }
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
if email.empty?
|
|
227
|
+
return { valid: false, message: "Email cannot be empty" }
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
unless email.include?('@')
|
|
231
|
+
return { valid: false, message: "Email must contain @ symbol" }
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
if email.start_with?('.')
|
|
235
|
+
return { valid: false, message: "Email cannot start with a dot" }
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
unless email.match?(/\.[a-zA-Z]{2,}$/)
|
|
239
|
+
return { valid: false, message: "Email must have a valid TLD (at least 2 letters)" }
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
if BrazilianUtils::EmailUtils.valid?(email)
|
|
243
|
+
{ valid: true, message: "Email is valid" }
|
|
244
|
+
else
|
|
245
|
+
{ valid: false, message: "Email format is invalid" }
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
test_emails_feedback = [
|
|
250
|
+
'valid@example.com',
|
|
251
|
+
'invalid',
|
|
252
|
+
'@domain.com',
|
|
253
|
+
'.user@example.com',
|
|
254
|
+
'user@domain',
|
|
255
|
+
nil,
|
|
256
|
+
''
|
|
257
|
+
]
|
|
258
|
+
|
|
259
|
+
test_emails_feedback.each do |email|
|
|
260
|
+
result = validate_email_with_feedback(email)
|
|
261
|
+
status = result[:valid] ? "✓ VALID" : "✗ INVALID"
|
|
262
|
+
display = email.nil? ? 'nil' : (email.empty? ? '(empty)' : email)
|
|
263
|
+
puts "#{status.ljust(10)} #{display.ljust(25)} => #{result[:message]}"
|
|
264
|
+
end
|
|
265
|
+
puts
|
|
266
|
+
|
|
267
|
+
# ============================================================================
|
|
268
|
+
# Statistics
|
|
269
|
+
# ============================================================================
|
|
270
|
+
puts "9. EMAIL VALIDATION STATISTICS"
|
|
271
|
+
puts "-" * 70
|
|
272
|
+
|
|
273
|
+
all_test_emails = [
|
|
274
|
+
'user@example.com', 'invalid@', '@example.com', 'user.name@example.com',
|
|
275
|
+
'user+tag@example.co.uk', 'invalid email@test.com', 'user@domain',
|
|
276
|
+
'test..user@example.com', 'user@test-domain.com', '.user@example.com',
|
|
277
|
+
'user@example.c', 'john.doe@gmail.com', 'user@subdomain.example.com',
|
|
278
|
+
'contact@company.com.br', 'user@example.com '
|
|
279
|
+
]
|
|
280
|
+
|
|
281
|
+
valid_count = all_test_emails.count { |email| BrazilianUtils::EmailUtils.valid?(email) }
|
|
282
|
+
invalid_count = all_test_emails.count { |email| !BrazilianUtils::EmailUtils.valid?(email) }
|
|
283
|
+
|
|
284
|
+
puts "Total emails tested: #{all_test_emails.length}"
|
|
285
|
+
puts "Valid: #{valid_count} (#{(valid_count * 100.0 / all_test_emails.length).round(1)}%)"
|
|
286
|
+
puts "Invalid: #{invalid_count} (#{(invalid_count * 100.0 / all_test_emails.length).round(1)}%)"
|
|
287
|
+
puts
|
|
288
|
+
|
|
289
|
+
# ============================================================================
|
|
290
|
+
# Common Mistakes
|
|
291
|
+
# ============================================================================
|
|
292
|
+
puts "10. COMMON EMAIL MISTAKES"
|
|
293
|
+
puts "-" * 70
|
|
294
|
+
|
|
295
|
+
common_mistakes = {
|
|
296
|
+
'Missing @' => 'userexample.com',
|
|
297
|
+
'Missing domain' => 'user@',
|
|
298
|
+
'Missing local part' => '@example.com',
|
|
299
|
+
'Space in email' => 'user name@example.com',
|
|
300
|
+
'No TLD' => 'user@domain',
|
|
301
|
+
'TLD too short' => 'user@example.c',
|
|
302
|
+
'Starts with dot' => '.user@example.com',
|
|
303
|
+
'Consecutive dots' => 'user..name@example.com',
|
|
304
|
+
'Double @' => 'user@@example.com',
|
|
305
|
+
'Special chars' => 'user!name@example.com',
|
|
306
|
+
'Trailing space' => 'user@example.com ',
|
|
307
|
+
'Leading space' => ' user@example.com'
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
puts "Mistake Email Valid?"
|
|
311
|
+
puts "-" * 70
|
|
312
|
+
common_mistakes.each do |mistake, email|
|
|
313
|
+
result = BrazilianUtils::EmailUtils.valid?(email)
|
|
314
|
+
status = result ? "Yes" : "No"
|
|
315
|
+
puts "#{mistake.ljust(26)} #{email.inspect.ljust(30)} #{status}"
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
puts
|
|
319
|
+
puts "=" * 70
|
|
320
|
+
puts "Examples completed!"
|
|
321
|
+
puts "=" * 70
|