amka 2.0.0 → 2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5f2628c4521fdb7fc9d1c9a09318e9189d837ede318ac1d19ac5fc606a1b9c24
4
- data.tar.gz: da07a7a6bb486d1409f26a25969fc109ec392bac6b9e8c237a88fd6d0a816650
3
+ metadata.gz: de5ab67f3f55def8127fdcc62f80227e3a1eac67310f5505fb0d2bd885235b5e
4
+ data.tar.gz: 8898093154bfa16391dbf6721204350f4f2052088db0db2be4dc0ee8cda51e38
5
5
  SHA512:
6
- metadata.gz: 56db96d08effcd378cb0c7f2bd7ae18041c2ce04c2d195152d94714e1fa750b67a1230467bd15b7871ec06dcd7632e96087dd7af3a55b44cbc4e248221a67754
7
- data.tar.gz: a042775a314e742322c36c7769d07ffd152ce2893147226c64bafe12d6a4da6eaa281f931dcdc43cb22e3dc9fefa25b08e0dbd311f71a17179a769490a2938d7
6
+ metadata.gz: 1e46d541a313fd37f7d58f98d244459110d77d22630e65d2b8941fa7c5a4a69f1d0eb8e50962acd6d7e83bec5f6b4fa227e8c1d8e3c9ef8a01c9bbd2b2589b15
7
+ data.tar.gz: d2b9da885d006f520a93b4a08f07561f5518b1369f16fd9c40da0a78560cee23edef7a49359e9addf8c0ec1cbeed401ebcf0159870d37325fb87ebf07a483faa
data/CHANGELOG.md CHANGED
@@ -5,6 +5,25 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.1.0] - 2023-05-14
9
+
10
+ ### Added
11
+
12
+ - New `validate` method that returns detailed validation errors
13
+ - New `validate!` method that raises exceptions with descriptive messages
14
+ - Added `safe_valid?` method to Luhn class for exception-free validation
15
+ - Improved error handling with specific `ValidationError` class
16
+
17
+ ### Changed
18
+
19
+ - Improved `valid?` method to never raise exceptions
20
+ - Refactored validation logic for better maintainability
21
+ - Better error messages for validation failures
22
+
23
+ ### Fixed
24
+
25
+ - Rubocop compliance for method length
26
+
8
27
  ## [2.0.0] - 2025-04-16
9
28
 
10
29
  ### Changed
data/README.md CHANGED
@@ -56,16 +56,31 @@ gem install amka
56
56
  ```ruby
57
57
  require 'amka'
58
58
 
59
- # To validate (takes the AMKA as a string and returns true or false)
59
+ # Simple Validation (returns true or false)
60
60
  Amka.valid?('01011441432')
61
- # returns false (i did not use a valid one in this example just in case
62
- # it belonged to a real person!!!!)
61
+ # returns false
63
62
 
64
63
  # You can also pass the 4 digit year of birth as a second string argument
65
64
  # This will increase the accuracy of the date part of validation to 100%.
66
65
  Amka.valid?('111098xxxxx', '1998')
67
66
 
68
- # To generate (returns the AMKA as a string)
67
+ # Detailed Validation with Error Messages
68
+ errors = Amka.validate('01AB9012345')
69
+ if errors.empty?
70
+ puts "Valid AMKA!"
71
+ else
72
+ puts "Invalid AMKA: #{errors.join(', ')}"
73
+ # => "Invalid AMKA: AMKA must contain only digits"
74
+ end
75
+
76
+ # Exception-based Validation
77
+ begin
78
+ Amka.validate!('01019012345') # Returns true if valid
79
+ rescue Amka::ValidationError => e
80
+ puts "Error: #{e.message}"
81
+ end
82
+
83
+ # To generate a random AMKA (returns the AMKA as a string)
69
84
  Amka.generate
70
85
 
71
86
  # To generate with a specific date (date format: [d]d/[m]m/yyyy)
data/lib/amka/luhn.rb CHANGED
@@ -50,6 +50,33 @@ module Amka
50
50
  (digits_sum % 10).zero?
51
51
  end
52
52
 
53
+ # Validates if a given ID follows the Luhn algorithm, without raising exceptions
54
+ #
55
+ # This is a safe version of valid? that returns false for any invalid input
56
+ # instead of raising exceptions. It's designed for use in validation pipelines
57
+ # where exceptions would need to be caught.
58
+ #
59
+ # @param luhn_id [Object] the ID to validate
60
+ # @return [Boolean] true if valid according to Luhn algorithm, false otherwise
61
+ # @example Safe validation with clean inputs
62
+ # Amka::Luhn.safe_valid?('4532015112830366') #=> true
63
+ # @example Safe validation with problematic inputs
64
+ # Amka::Luhn.safe_valid?(nil) #=> false
65
+ # Amka::Luhn.safe_valid?(12345) #=> false
66
+ # Amka::Luhn.safe_valid?('abc-123') #=> false
67
+ def self.safe_valid?(luhn_id)
68
+ # Return false for non-string input
69
+ return false unless luhn_id.is_a?(String)
70
+ # Return false for strings with non-digits
71
+ return false unless luhn_id.match(/\A\d+\Z/)
72
+
73
+ digits_sum = calculate_digits_sum(luhn_id)
74
+ (digits_sum % 10).zero?
75
+ rescue StandardError
76
+ # Catch any unexpected errors and return false
77
+ false
78
+ end
79
+
53
80
  # Generates a valid Luhn ID
54
81
  #
55
82
  # Creates a number that passes the Luhn check by:
data/lib/amka/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Amka
4
- VERSION = '2.0.0'
4
+ VERSION = '2.1.0'
5
5
  end
data/lib/amka.rb CHANGED
@@ -31,6 +31,9 @@ module Amka
31
31
  # Standard error class for the Amka gem
32
32
  class Error < StandardError; end
33
33
 
34
+ # Error raised when AMKA format or content is invalid
35
+ class ValidationError < Error; end
36
+
34
37
  # Validates whether a given string is a valid AMKA
35
38
  #
36
39
  # The validation checks three conditions:
@@ -38,7 +41,10 @@ module Amka
38
41
  # 2. The first 6 digits must form a valid date (DDMMYY format)
39
42
  # 3. The entire number must satisfy the Luhn algorithm check
40
43
  #
41
- # @param amka [String] the AMKA to validate, must be a string containing only digits
44
+ # This method will always return a boolean and never raise exceptions,
45
+ # returning false for any input that doesn't meet the AMKA criteria.
46
+ #
47
+ # @param amka [Object] the AMKA to validate, should be a string containing only digits
42
48
  # @param year [String, nil] optional four-digit year to match against
43
49
  # When provided, improves the validation by ensuring the birth year
44
50
  # matches exactly (resolves century ambiguity in 2-digit years)
@@ -47,14 +53,120 @@ module Amka
47
53
  # Amka.valid?('17019012345') #=> true
48
54
  # @example Validating with explicit year
49
55
  # Amka.valid?('17019012345', '1990') #=> true
56
+ # @example Validating invalid input
57
+ # Amka.valid?(nil) #=> false
58
+ # Amka.valid?(12345) #=> false
59
+ # Amka.valid?('abc123') #=> false
50
60
  def self.valid?(amka, year = nil)
51
- Utils.string_with_digits_or_fail(amka)
52
-
61
+ # Return false for non-string input
62
+ return false unless amka.is_a?(String)
63
+ # Return false for strings with non-digits
64
+ return false unless amka.match(/\A\d+\Z/)
65
+ # Check length requirement
53
66
  return false unless length_is_11?(amka)
54
67
 
55
- return Luhn.valid?(amka) if Utils.valid_date?(amka, year)
68
+ # Check if date and Luhn algorithm are valid
69
+ begin
70
+ return false unless Utils.valid_date?(amka, year)
56
71
 
57
- false
72
+ Luhn.safe_valid?(amka)
73
+ rescue ArgumentError
74
+ # If any validation raises an exception, the AMKA is invalid
75
+ false
76
+ end
77
+ end
78
+
79
+ # Validates an AMKA and returns an array of validation errors
80
+ #
81
+ # This method provides detailed feedback about why validation failed,
82
+ # returning an empty array for valid AMKAs or an array of error messages
83
+ # for invalid ones.
84
+ #
85
+ # @param amka [Object] the AMKA to validate
86
+ # @param year [String, nil] optional four-digit year to match against
87
+ # @return [Array<String>] empty array if valid, otherwise contains error messages
88
+ # @example Get validation errors
89
+ # errors = Amka.validate(input)
90
+ # if errors.empty?
91
+ # puts "Valid AMKA!"
92
+ # else
93
+ # puts "Invalid AMKA: #{errors.join(', ')}"
94
+ # end
95
+ def self.validate(amka, year = nil)
96
+ errors = []
97
+
98
+ # Check for basic format issues and return early if found
99
+ basic_format_errors = check_basic_format(amka)
100
+ return basic_format_errors unless basic_format_errors.empty?
101
+
102
+ # Check length
103
+ errors << 'AMKA must be exactly 11 digits long' unless length_is_11?(amka)
104
+
105
+ # Check date format
106
+ check_date(errors, amka, year)
107
+
108
+ # Check Luhn algorithm
109
+ check_luhn(errors, amka)
110
+
111
+ errors
112
+ end
113
+
114
+ # Helper method to validate basic format requirements
115
+ # @return [Array<String>] empty if valid, otherwise contains error message
116
+ def self.check_basic_format(amka)
117
+ errors = []
118
+
119
+ unless amka.is_a?(String)
120
+ errors << 'AMKA must be a string'
121
+ return errors
122
+ end
123
+
124
+ errors << 'AMKA must contain only digits' unless amka.match(/\A\d+\Z/)
125
+
126
+ errors
127
+ end
128
+ private_class_method :check_basic_format
129
+
130
+ # Helper method to validate date format
131
+ def self.check_date(errors, amka, year)
132
+ unless Utils.valid_date?(amka, year)
133
+ errors << 'First 6 digits of AMKA must form a valid date (DDMMYY)'
134
+ end
135
+ rescue ArgumentError
136
+ errors << 'Invalid date format in AMKA'
137
+ end
138
+ private_class_method :check_date
139
+
140
+ # Helper method to validate Luhn algorithm
141
+ def self.check_luhn(errors, amka)
142
+ errors << 'AMKA must satisfy the Luhn algorithm check' unless Luhn.safe_valid?(amka)
143
+ rescue StandardError
144
+ errors << 'Error checking Luhn algorithm'
145
+ end
146
+ private_class_method :check_luhn
147
+
148
+ # Strictly validates an AMKA and raises exceptions for invalid input
149
+ #
150
+ # Similar to valid? but raises specific exceptions when validation fails,
151
+ # which is useful for cases where you need detailed error information
152
+ # or when you prefer exceptions for control flow.
153
+ #
154
+ # @param amka [Object] the AMKA to validate
155
+ # @param year [String, nil] optional four-digit year to match against
156
+ # @return [true] if the AMKA is valid
157
+ # @raise [ValidationError] if the AMKA is invalid, with details about why
158
+ # @example Strict validation with exception handling
159
+ # begin
160
+ # Amka.validate!('17019012345') #=> true (if valid)
161
+ # rescue Amka::ValidationError => e
162
+ # puts e.message # Contains detailed error info
163
+ # end
164
+ def self.validate!(amka, year = nil)
165
+ errors = validate(amka, year)
166
+
167
+ raise ValidationError, errors.first unless errors.empty?
168
+
169
+ true
58
170
  end
59
171
 
60
172
  # Generates a random valid AMKA
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: amka
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ioannis Angelakopoulos
@@ -35,6 +35,7 @@ metadata:
35
35
  homepage_uri: https://github.com/ioagel/amka
36
36
  source_code_uri: https://github.com/ioagel/amka
37
37
  changelog_uri: https://github.com/ioagel/amka/blob/master/CHANGELOG.md
38
+ documentation_uri: http://rubydoc.info/gems/amka
38
39
  rubygems_mfa_required: 'true'
39
40
  post_install_message:
40
41
  rdoc_options: []