Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: remove ActiveSupport dependency #39

Merged
merged 5 commits into from
Nov 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Metrics/BlockLength:
Metrics/ClassLength:
Enabled: true
Exclude:
- 'lib/itax_code/transliterator.rb'
- 'lib/itax_code/utils.rb'
- 'test/**/*'

Expand Down
1 change: 0 additions & 1 deletion itax_code.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,5 @@ Gem::Specification.new do |spec|
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.add_dependency "activesupport"
spec.metadata["rubygems_mfa_required"] = "false"
end
2 changes: 0 additions & 2 deletions lib/itax_code.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# frozen_string_literal: true

require "active_support/all"

require "itax_code/version"
require "itax_code/utils"
require "itax_code/encoder"
Expand Down
9 changes: 5 additions & 4 deletions lib/itax_code/encoder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ class Encoder
# @option data [String, Date] :birthdate The user birthdate
# @option data [String] :birthplace The user birthplace
def initialize(data = {}, utils = Utils.new)
@utils = utils

@surname = data[:surname]
@name = data[:name]
@gender = data[:gender]&.upcase
Expand All @@ -31,7 +33,6 @@ def initialize(data = {}, utils = Utils.new)
validate_data_presence!

@birthdate = parse_birthdate!
@utils = utils
end

# Computes the tax code from its components.
Expand Down Expand Up @@ -79,16 +80,16 @@ def encode_birthplace(src = utils.cities, stop: false)
place_slug = utils.slugged(birthplace)
place_item = src.find { |i| place_slug == utils.slugged(i[lookup_key]) }

code = place_item.try(:[], "code")
return code if code.present?
code = place_item&.[]("code")
return code if utils.present?(code)
raise MissingDataError, "no code found for #{birthplace}" if stop

encode_birthplace(utils.countries, stop: true)
end

def validate_data_presence!
instance_variables.each do |ivar|
next if instance_variable_get(ivar).present?
next if utils.present?(instance_variable_get(ivar))

raise MissingDataError, "missing #{ivar} value"
end
Expand Down
6 changes: 3 additions & 3 deletions lib/itax_code/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def initialize(tax_code, utils = Utils.new)
@tax_code = tax_code&.upcase
@utils = utils

raise NoTaxCodeError if @tax_code.blank?
raise NoTaxCodeError if @utils.blank?(@tax_code)
raise InvalidTaxCodeError if @tax_code.length != LENGTH
raise InvalidControlInternalNumberError if raw[:cin] != @utils.encode_cin(@tax_code)
end
Expand Down Expand Up @@ -56,7 +56,7 @@ def raw
end

def raw_matches
@raw_matches ||= tax_code.scan(utils.regex).flatten
@raw_matches ||= tax_code.scan(utils.tax_code_sections_regex).flatten
end

def gender
Expand Down Expand Up @@ -92,7 +92,7 @@ def birthplace(src = utils.cities, stop: false)
if place.nil?
birthplace(utils.countries, stop: true) unless stop
else
place.to_h.deep_symbolize_keys
place.to_h.transform_keys(&:to_sym)
end
end

Expand Down
211 changes: 211 additions & 0 deletions lib/itax_code/transliterator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
# frozen_string_literal: true

module ItaxCode
# https://github.com/ruby-i18n/i18n/blob/master/lib/i18n/backend/transliterator.rb
class Transliterator
DEFAULT_REPLACEMENT_CHAR = "?"

def transliterate(string, replacement = nil)
replacement ||= DEFAULT_REPLACEMENT_CHAR
string.gsub(/[^\x00-\x7f]/u) { |char| approximations[char] || replacement }
end

private

def approximations
@approximations ||= {
"À" => "A",
"Á" => "A",
"Â" => "A",
"Ã" => "A",
"Ä" => "A",
"Å" => "A",
"Æ" => "AE",
"Ç" => "C",
"È" => "E",
"É" => "E",
"Ê" => "E",
"Ë" => "E",
"Ì" => "I",
"Í" => "I",
"Î" => "I",
"Ï" => "I",
"Ð" => "D",
"Ñ" => "N",
"Ò" => "O",
"Ó" => "O",
"Ô" => "O",
"Õ" => "O",
"Ö" => "O",
"×" => "x",
"Ø" => "O",
"Ù" => "U",
"Ú" => "U",
"Û" => "U",
"Ü" => "U",
"Ý" => "Y",
"Þ" => "Th",
"ß" => "ss",
"ẞ" => "SS",
"à" => "a",
"á" => "a",
"â" => "a",
"ã" => "a",
"ä" => "a",
"å" => "a",
"æ" => "ae",
"ç" => "c",
"è" => "e",
"é" => "e",
"ê" => "e",
"ë" => "e",
"ì" => "i",
"í" => "i",
"î" => "i",
"ï" => "i",
"ð" => "d",
"ñ" => "n",
"ò" => "o",
"ó" => "o",
"ô" => "o",
"õ" => "o",
"ö" => "o",
"ø" => "o",
"ù" => "u",
"ú" => "u",
"û" => "u",
"ü" => "u",
"ý" => "y",
"þ" => "th",
"ÿ" => "y",
"Ā" => "A",
"ā" => "a",
"Ă" => "A",
"ă" => "a",
"Ą" => "A",
"ą" => "a",
"Ć" => "C",
"ć" => "c",
"Ĉ" => "C",
"ĉ" => "c",
"Ċ" => "C",
"ċ" => "c",
"Č" => "C",
"č" => "c",
"Ď" => "D",
"ď" => "d",
"Đ" => "D",
"đ" => "d",
"Ē" => "E",
"ē" => "e",
"Ĕ" => "E",
"ĕ" => "e",
"Ė" => "E",
"ė" => "e",
"Ę" => "E",
"ę" => "e",
"Ě" => "E",
"ě" => "e",
"Ĝ" => "G",
"ĝ" => "g",
"Ğ" => "G",
"ğ" => "g",
"Ġ" => "G",
"ġ" => "g",
"Ģ" => "G",
"ģ" => "g",
"Ĥ" => "H",
"ĥ" => "h",
"Ħ" => "H",
"ħ" => "h",
"Ĩ" => "I",
"ĩ" => "i",
"Ī" => "I",
"ī" => "i",
"Ĭ" => "I",
"ĭ" => "i",
"Į" => "I",
"į" => "i",
"İ" => "I",
"ı" => "i",
"IJ" => "IJ",
"ij" => "ij",
"Ĵ" => "J",
"ĵ" => "j",
"Ķ" => "K",
"ķ" => "k",
"ĸ" => "k",
"Ĺ" => "L",
"ĺ" => "l",
"Ļ" => "L",
"ļ" => "l",
"Ľ" => "L",
"ľ" => "l",
"Ŀ" => "L",
"ŀ" => "l",
"Ł" => "L",
"ł" => "l",
"Ń" => "N",
"ń" => "n",
"Ņ" => "N",
"ņ" => "n",
"Ň" => "N",
"ň" => "n",
"ʼn" => "'n",
"Ŋ" => "NG",
"ŋ" => "ng",
"Ō" => "O",
"ō" => "o",
"Ŏ" => "O",
"ŏ" => "o",
"Ő" => "O",
"ő" => "o",
"Œ" => "OE",
"œ" => "oe",
"Ŕ" => "R",
"ŕ" => "r",
"Ŗ" => "R",
"ŗ" => "r",
"Ř" => "R",
"ř" => "r",
"Ś" => "S",
"ś" => "s",
"Ŝ" => "S",
"ŝ" => "s",
"Ş" => "S",
"ş" => "s",
"Š" => "S",
"š" => "s",
"Ţ" => "T",
"ţ" => "t",
"Ť" => "T",
"ť" => "t",
"Ŧ" => "T",
"ŧ" => "t",
"Ũ" => "U",
"ũ" => "u",
"Ū" => "U",
"ū" => "u",
"Ŭ" => "U",
"ŭ" => "u",
"Ů" => "U",
"ů" => "u",
"Ű" => "U",
"ű" => "u",
"Ų" => "U",
"ų" => "u",
"Ŵ" => "W",
"ŵ" => "w",
"Ŷ" => "Y",
"ŷ" => "y",
"Ÿ" => "Y",
"Ź" => "Z",
"ź" => "z",
"Ż" => "Z",
"ż" => "z",
"Ž" => "Z",
"ž" => "z"
}
end
end
end
27 changes: 22 additions & 5 deletions lib/itax_code/utils.rb
Original file line number Diff line number Diff line change
@@ -1,20 +1,37 @@
# frozen_string_literal: true

require "csv"
require "itax_code/transliterator"

module ItaxCode
class Utils
def regex
def blank?(obj)
obj.respond_to?(:empty?) ? !!obj.empty? : !obj
end

def present?(obj)
!blank?(obj)
end

def slugged(string)
transliterated = transliterate(string.downcase.strip)
transliterated.gsub(/[^\w-]+/, "-").gsub(/-{2,}/, "-").gsub(/^-+|-+$/, "")
end

def transliterate(string)
return string if string.ascii_only?

transliterator = Transliterator.new
transliterator.transliterate(string.unicode_normalize(:nfc))
end

def tax_code_sections_regex
/^([A-Z]{3})([A-Z]{3})
(([A-Z\d]{2})([ABCDEHLMPRST]{1})([A-Z\d]{2}))
([A-Z]{1}[A-Z\d]{3})
([A-Z]{1})$/x
end

def slugged(str, separator = "-")
str.gsub(/\s*@\s*/, " at ").gsub(/\s*&\s*/, " and ").parameterize(separator: separator)
end

def months
%w[A B C D E H L M P R S T]
end
Expand Down
2 changes: 1 addition & 1 deletion test/itax_code/encoder_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
require "test_helper"

module ItaxCode
class EncoderTest < ActiveSupport::TestCase
class EncoderTest < Minitest::Test
test "public interface" do
instance_methods = Encoder.instance_methods - Object.instance_methods

Expand Down
2 changes: 1 addition & 1 deletion test/itax_code/parser_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
require "test_helper"

module ItaxCode
class ParserTest < ActiveSupport::TestCase
class ParserTest < Minitest::Test
test "public interface" do
instance_methods = klass.instance_methods - Object.instance_methods

Expand Down
Loading