lib/mini_defender/rules/integer.rb in mini_defender-0.5.8 vs lib/mini_defender/rules/integer.rb in mini_defender-0.6.0
- old
+ new
@@ -1,19 +1,83 @@
# frozen_string_literal: true
class MiniDefender::Rules::Integer < MiniDefender::Rule
+ attr_reader :mode
+ attr_reader :parsed
+
+ DIGIT_MAP = {
+ # Arabic-Indic Digits
+ "\u0660" => '0',
+ "\u0661" => '1',
+ "\u0662" => '2',
+ "\u0663" => '3',
+ "\u0664" => '4',
+ "\u0665" => '5',
+ "\u0666" => '6',
+ "\u0667" => '7',
+ "\u0668" => '8',
+ "\u0669" => '9',
+
+ # Extended Arabic-Indic Digits
+ "\u06F0" => '0',
+ "\u06F1" => '1',
+ "\u06F2" => '2',
+ "\u06F3" => '3',
+ "\u06F4" => '4',
+ "\u06F5" => '5',
+ "\u06F6" => '6',
+ "\u06F7" => '7',
+ "\u06F8" => '8',
+ "\u06F9" => '9',
+ }
+
+ def initialize(mode = 'strict')
+ @mode = mode
+ end
+
def self.signature
'integer'
end
+ def self.make(args)
+ new(args[0] || 'strict')
+ end
+
def coerce(value)
- value.to_i
+ @parsed
end
def passes?(attribute, value, validator)
- value.is_a?(Integer) || value.is_a?(String) && value.match?(/^\d+$/)
+ # Avoid converting integers to string and back
+ if value.is_a?(Integer)
+ @parsed = value
+ return true
+ end
+
+ value = value.to_s
+
+ if @mode == 'relaxed'
+ value = normalize_digits(value)
+ end
+
+ @parsed = Integer(value)
+ rescue
+ false
end
def message(attribute, value, validator)
"The value must be an integer."
+ end
+
+ def normalize_digits(data)
+ # Check if arabic digits exist or avoid expensive string creation operation
+ unless data.match?(/[\u0660-\u0669\u06F0-\u06F9]/)
+ return data
+ end
+
+ DIGIT_MAP.each do |k, v|
+ data = data.gsub(k, v)
+ end
+
+ data
end
end