class ActiveModel::Validations::CuilValidator
Here start the implementation of CUIT/CUIL validator
Public Instance Methods
validate_each(record, attr_name, value)
click to toggle source
# File lib/active_model/validations/cuit_validator.rb, line 12 def validate_each(record, attr_name, value) return if detect_any_failure_in :length, :digits, :dni_compatibility, :gender_compatibility, :v_digit, data: [ record, attr_name, value ] end
Protected Instance Methods
check_digits_failure(record, attr_name, value)
click to toggle source
# File lib/active_model/validations/cuit_validator.rb, line 31 def check_digits_failure(record, attr_name, value) type, dni, v_digit = separate_cuit_groups value unless (type + dni + v_digit) =~ /\A\d+\Z/ record.errors.add(attr_name, :cuit_invalid_format) end end
check_dni_compatibility_failure(record, attr_name, value)
click to toggle source
# File lib/active_model/validations/cuit_validator.rb, line 38 def check_dni_compatibility_failure(record, attr_name, value) _, dni, _ = separate_cuit_groups value unless !options[:dni_compatible].present? || record.public_send(options[:dni_compatible]) == dni record.errors.add(attr_name, :cuit_dni_incompatible) end end
check_gender_compatibility_failure(record, attr_name, value)
click to toggle source
# File lib/active_model/validations/cuit_validator.rb, line 45 def check_gender_compatibility_failure(record, attr_name, value) type, _, _ = separate_cuit_groups value if options[:gender_compatible].present? unless gender_validation_passing?(record, type) record.errors.add(attr_name, :cuit_gender_incompatible) end end end
check_length_failure(record, attr_name, value)
click to toggle source
# File lib/active_model/validations/cuit_validator.rb, line 24 def check_length_failure(record, attr_name, value) type, dni, v_digit = separate_cuit_groups value unless type.length == 2 && dni.length == 8 && v_digit.length == 1 record.errors.add(attr_name, :cuit_invalid_format) end end
check_v_digit_failure(record, attr_name, value)
click to toggle source
# File lib/active_model/validations/cuit_validator.rb, line 55 def check_v_digit_failure(record, attr_name, value) type, dni, v_digit = separate_cuit_groups value unless v_digit.to_i == compute_v_digit(type, dni) record.errors.add(attr_name, :cuit_invalid_v_digit) end end
compute_v_digit(type, dni)
click to toggle source
AFIP dependent logic. Trust or die
# File lib/active_model/validations/cuit_validator.rb, line 63 def compute_v_digit(type, dni) sequence = [2,3,4,5,6,7,2,3,4,5].reverse precomputed_v_digit = 11 - (type + dni) .chars .each_with_index .inject(0) do |acc, (n, i)| acc + n.to_i * sequence[i] end % 11 case precomputed_v_digit when 11 0 when 10 9 else precomputed_v_digit end end
detect_any_failure_in(*properties, data: [])
click to toggle source
Sugar, turutu-tu-tuut-tu, ohhh, honey, honey
# File lib/active_model/validations/cuit_validator.rb, line 20 def detect_any_failure_in(*properties, data: []) properties.detect { |prop| send "check_#{prop}_failure", *data } end
gender_validation_passing?(record, type)
click to toggle source
# File lib/active_model/validations/cuit_validator.rb, line 93 def gender_validation_passing?(record, type) raise ArgumentError, 'Valicuit: gender field specification must be present!' unless options[:gender_compatible][:field].present? raise ArgumentError, 'Valicuit: declaration of male value missing!' unless options[:gender_compatible][:male].present? raise ArgumentError, 'Valicuit: declaration of female value missing!' unless options[:gender_compatible][:female].present? gender = case type when '20' options[:gender_compatible][:male] when '27' options[:gender_compatible][:female] when '30', '33' options[:gender_compatible][:company] || :pass when '23', '24', '25', '26' :pass else :dont_pass end gender == :pass ? true : gender == record.public_send(options[:gender_compatible][:field]) end
separate_cuit_groups(cuit)
click to toggle source
# File lib/active_model/validations/cuit_validator.rb, line 82 def separate_cuit_groups(cuit) separator = options[:separator] cuit = cuit.to_s if separator cuit.split(separator).first 3 else # Take standard CUIT/CUIL layout (2 digit, 8 digit, 1 digit) [ cuit[0..1], cuit[2..9], cuit[10] ] end.map(&:to_s) end