atlas_engine 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/app/countries/atlas_engine/au/country_profile.yml +2 -2
  3. data/app/countries/atlas_engine/bm/country_profile.yml +2 -2
  4. data/app/countries/atlas_engine/ch/country_profile.yml +2 -2
  5. data/app/countries/atlas_engine/es/country_profile.yml +1 -0
  6. data/app/countries/atlas_engine/gb/address_validation/es/query_builder.rb +9 -3
  7. data/app/countries/atlas_engine/it/address_validation/validators/full_address/exclusions/city.rb +1 -2
  8. data/app/countries/atlas_engine/it/country_profile.yml +2 -2
  9. data/app/countries/atlas_engine/kr/address_validation/validators/full_address/exclusions/city.rb +7 -7
  10. data/app/countries/atlas_engine/kr/country_profile.yml +2 -2
  11. data/app/countries/atlas_engine/pl/address_validation/exclusions/placeholder_postal_code.rb +1 -2
  12. data/app/countries/atlas_engine/pl/address_validation/exclusions/rural_address.rb +1 -2
  13. data/app/countries/atlas_engine/pt/address_validation/validators/full_address/exclusions/zip.rb +1 -2
  14. data/app/countries/atlas_engine/pt/country_profile.yml +2 -2
  15. data/app/countries/atlas_engine/si/address_validation/exclusions/unknown_city.rb +1 -2
  16. data/app/countries/atlas_engine/si/country_profile.yml +2 -2
  17. data/app/countries/atlas_engine/tt/country_profile.yml +2 -2
  18. data/app/lib/atlas_engine/validation_transcriber/address_parser_base.rb +7 -7
  19. data/app/models/atlas_engine/address_importer/open_address/transformer.rb +1 -1
  20. data/app/models/atlas_engine/address_validation/es/data_mappers/default_data_mapper.rb +1 -0
  21. data/app/models/atlas_engine/address_validation/es/datastore.rb +1 -1
  22. data/app/models/atlas_engine/address_validation/es/query_builder.rb +33 -15
  23. data/app/models/atlas_engine/address_validation/validators/full_address/address_comparison.rb +41 -27
  24. data/app/models/atlas_engine/address_validation/validators/full_address/building_comparison.rb +5 -0
  25. data/app/models/atlas_engine/address_validation/validators/full_address/candidate_result.rb +2 -4
  26. data/app/models/atlas_engine/address_validation/validators/full_address/city_comparison.rb +5 -0
  27. data/app/models/atlas_engine/address_validation/validators/full_address/exclusions/exclusion_base.rb +1 -2
  28. data/app/models/atlas_engine/address_validation/validators/full_address/field_comparison_base.rb +15 -3
  29. data/app/models/atlas_engine/address_validation/validators/full_address/province_code_comparison.rb +5 -0
  30. data/app/models/atlas_engine/address_validation/validators/full_address/relevant_components.rb +4 -10
  31. data/app/models/atlas_engine/address_validation/validators/full_address/street_comparison.rb +5 -0
  32. data/app/models/atlas_engine/address_validation/validators/full_address/zip_comparison.rb +5 -0
  33. data/app/models/atlas_engine/country_profile.rb +6 -1
  34. data/app/models/atlas_engine/country_profile_ingestion_subset.rb +3 -3
  35. data/app/models/atlas_engine/country_profile_validation_subset.rb +8 -7
  36. data/app/models/atlas_engine/elasticsearch/repository.rb +1 -1
  37. data/app/tasks/maintenance/atlas_engine/geo_json_import_task.rb +8 -6
  38. data/db/data/address_synonyms/index_configurations/default.yml +7 -0
  39. data/db/data/country_profiles/default.yml +4 -2
  40. data/lib/atlas_engine/version.rb +1 -1
  41. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 99901e1ca20e5c32dd90945bbe7bd2199ad9cf0c11507524e7210b621f0a647c
4
- data.tar.gz: c14b30e2629d198b5341e87190c0ccc38d016a644b9fea74e6d1bece611360b1
3
+ metadata.gz: 3285871f59bee7bdf0084bfb5f985a6e582a173a78baa496c07ba9e8bd526eda
4
+ data.tar.gz: b25b6b4d8637c34d43a78e60f457342ccd9f7117f02d039f961476a7a4ef310e
5
5
  SHA512:
6
- metadata.gz: b424ffd2640d6248aa00adfa8e1942fad3b0f954ecfeb339257eccf84e2976107151f7da4cf936f4f48eb450337582c1692e90d79b4ecf6658964cc78507b963
7
- data.tar.gz: 463dbcc8c3ad8a9aab64ee1212fc9d9148b49c5ad44a51fece73a1d8185af58453c6d9fa4002df4f9acca3aa8ee0122a140575e4b6a90b67633fc4565d5659ce
6
+ metadata.gz: ea581fe90f17c1924f2d370fef820dc8bf18ed094e570666cdc60f13b0ec37b7e8876749176bbb14cd9f408931c525f6f7b29afdf4da47270bf24f147f8f0bce
7
+ data.tar.gz: 6ef3dca52ae9bfc224d694c6cb326f743701280cb8d6be14f30421ea247c53822d8017acdeaad5641cfe34ac080ca33a1b010308575057fec2e040a1d7a3222e
@@ -3,8 +3,8 @@ ingestion:
3
3
  settings:
4
4
  min_zip_edge_ngram: "1"
5
5
  max_zip_edge_ngram: "4"
6
- open_address:
7
- feature_mapper: AtlasEngine::Au::AddressImporter::OpenAddress::Mapper
6
+ post_address_mapper:
7
+ open_address: AtlasEngine::Au::AddressImporter::OpenAddress::Mapper
8
8
  validation:
9
9
  address_parser: AtlasEngine::Au::ValidationTranscriber::AddressParser
10
10
  enabled: true
@@ -3,8 +3,8 @@ ingestion:
3
3
  correctors:
4
4
  open_address:
5
5
  - AtlasEngine::Bm::AddressImporter::Corrections::OpenAddress::CityAliasCorrector
6
- open_address:
7
- feature_mapper: AtlasEngine::Bm::AddressImporter::OpenAddress::Mapper
6
+ post_address_mapper:
7
+ open_address: AtlasEngine::Bm::AddressImporter::OpenAddress::Mapper
8
8
  validation:
9
9
  enabled: true
10
10
  has_provinces: true
@@ -9,8 +9,8 @@ validation:
9
9
  - fr
10
10
  - it
11
11
  ingestion:
12
- open_address:
13
- feature_mapper: AtlasEngine::Ch::AddressImporter::OpenAddress::Mapper
12
+ post_address_mapper:
13
+ open_address: AtlasEngine::Ch::AddressImporter::OpenAddress::Mapper
14
14
  correctors:
15
15
  open_address:
16
16
  - AtlasEngine::Ch::AddressImporter::Corrections::OpenAddress::LocaleCorrector
@@ -1,3 +1,4 @@
1
1
  id: ES
2
2
  validation:
3
3
  address_parser: AtlasEngine::Es::ValidationTranscriber::AddressParser
4
+
@@ -8,9 +8,15 @@ module AtlasEngine
8
8
  class QueryBuilder < AtlasEngine::AddressValidation::Es::QueryBuilder
9
9
  extend T::Sig
10
10
 
11
- sig { params(address: AtlasEngine::AddressValidation::AbstractAddress, locale: T.nilable(String)).void }
12
- def initialize(address, locale = nil)
13
- super(address, locale)
11
+ sig do
12
+ params(
13
+ address: AtlasEngine::AddressValidation::AbstractAddress,
14
+ parsings: AtlasEngine::ValidationTranscriber::AddressParsings,
15
+ profile: AtlasEngine::CountryProfile,
16
+ ).void
17
+ end
18
+ def initialize(address, parsings, profile)
19
+ super(address, parsings, profile)
14
20
 
15
21
  @parsings = T.let(
16
22
  AtlasEngine::Gb::ValidationTranscriber::FullAddressParser
@@ -12,13 +12,12 @@ module AtlasEngine
12
12
  class << self
13
13
  sig do
14
14
  override.params(
15
- session: AtlasEngine::AddressValidation::Session,
16
15
  candidate: AtlasEngine::AddressValidation::Candidate,
17
16
  address_comparison: AtlasEngine::AddressValidation::Validators::FullAddress::AddressComparison,
18
17
  )
19
18
  .returns(T::Boolean)
20
19
  end
21
- def apply?(session, candidate, address_comparison)
20
+ def apply?(candidate, address_comparison)
22
21
  true
23
22
  end
24
23
  end
@@ -8,8 +8,8 @@ validation:
8
8
  - AtlasEngine::It::AddressValidation::Validators::FullAddress::Exclusions::City
9
9
  unmatched_components_suggestion_threshold: 1
10
10
  ingestion:
11
- open_address:
12
- feature_mapper: AtlasEngine::It::AddressImporter::OpenAddress::Mapper
11
+ post_address_mapper:
12
+ open_address: AtlasEngine::It::AddressImporter::OpenAddress::Mapper
13
13
  correctors:
14
14
  open_address:
15
15
  - AtlasEngine::It::AddressImporter::Corrections::OpenAddress::CityCorrector
@@ -18,18 +18,17 @@ module AtlasEngine
18
18
 
19
19
  sig do
20
20
  override.params(
21
- session: AtlasEngine::AddressValidation::Session,
22
21
  candidate: AtlasEngine::AddressValidation::Candidate,
23
22
  address_comparison: AtlasEngine::AddressValidation::Validators::FullAddress::AddressComparison,
24
23
  )
25
24
  .returns(T::Boolean)
26
25
  end
27
- def apply?(session, candidate, address_comparison)
26
+ def apply?(candidate, address_comparison)
28
27
  candidate_si = extract_component_from_city(candidate, :si)
29
28
  candidate_gu = extract_component_from_city(candidate, :gu)
30
29
 
31
- (candidate_si.present? && contains_component?(:si, candidate_si, session)) ||
32
- (candidate_gu.present? && contains_component?(:gu, candidate_gu, session))
30
+ (candidate_si.present? && contains_component?(:si, candidate_si, address_comparison)) ||
31
+ (candidate_gu.present? && contains_component?(:gu, candidate_gu, address_comparison))
33
32
  end
34
33
 
35
34
  private
@@ -53,11 +52,12 @@ module AtlasEngine
53
52
  params(
54
53
  type: Symbol,
55
54
  value: String,
56
- session: AtlasEngine::AddressValidation::Session,
55
+ address_comparison: AtlasEngine::AddressValidation::Validators::FullAddress::AddressComparison,
57
56
  ).returns(T::Boolean)
58
57
  end
59
- def contains_component?(type, value, session)
60
- session.parsings.parsings.pluck(type)&.include?(value) || session.city&.include?(value)
58
+ def contains_component?(type, value, address_comparison)
59
+ address_comparison.parsings.parsings.pluck(type)&.include?(value) ||
60
+ address_comparison.address.city&.include?(value)
61
61
  end
62
62
  end
63
63
  end
@@ -1,7 +1,7 @@
1
1
  id: KR
2
2
  ingestion:
3
- open_address:
4
- feature_mapper: AtlasEngine::Kr::AddressImporter::OpenAddress::Mapper
3
+ post_address_mapper:
4
+ open_address: AtlasEngine::Kr::AddressImporter::OpenAddress::Mapper
5
5
  validation:
6
6
  enabled: true
7
7
  default_matching_strategy: es
@@ -11,12 +11,11 @@ module AtlasEngine
11
11
  class << self
12
12
  sig do
13
13
  override.params(
14
- session: AtlasEngine::AddressValidation::Session,
15
14
  candidate: AtlasEngine::AddressValidation::Candidate,
16
15
  address_comparison: AtlasEngine::AddressValidation::Validators::FullAddress::AddressComparison,
17
16
  ).returns(T::Boolean)
18
17
  end
19
- def apply?(session, candidate, address_comparison)
18
+ def apply?(candidate, address_comparison)
20
19
  placeholder_postal_code?(candidate)
21
20
  end
22
21
 
@@ -11,12 +11,11 @@ module AtlasEngine
11
11
  class << self
12
12
  sig do
13
13
  override.params(
14
- session: AtlasEngine::AddressValidation::Session,
15
14
  candidate: AtlasEngine::AddressValidation::Candidate,
16
15
  address_comparison: AtlasEngine::AddressValidation::Validators::FullAddress::AddressComparison,
17
16
  ).returns(T::Boolean)
18
17
  end
19
- def apply?(session, candidate, address_comparison)
18
+ def apply?(candidate, address_comparison)
20
19
  rural_address?(candidate) && poor_city_match?(address_comparison)
21
20
  end
22
21
 
@@ -11,13 +11,12 @@ module AtlasEngine
11
11
  class << self
12
12
  sig do
13
13
  override.params(
14
- session: AtlasEngine::AddressValidation::Session,
15
14
  candidate: AtlasEngine::AddressValidation::Candidate,
16
15
  address_comparison: AtlasEngine::AddressValidation::Validators::FullAddress::AddressComparison,
17
16
  )
18
17
  .returns(T::Boolean)
19
18
  end
20
- def apply?(session, candidate, address_comparison)
19
+ def apply?(candidate, address_comparison)
21
20
  street_comparison_result = address_comparison.street_comparison.sequence_comparison
22
21
  building_comparison_result = address_comparison.building_comparison.sequence_comparison
23
22
 
@@ -3,8 +3,8 @@ ingestion:
3
3
  correctors:
4
4
  open_address:
5
5
  - AtlasEngine::Pt::AddressImporter::Corrections::OpenAddress::CityCorrector
6
- open_address:
7
- feature_mapper: AtlasEngine::Pt::AddressImporter::OpenAddress::Mapper
6
+ post_address_mapper:
7
+ open_address: AtlasEngine::Pt::AddressImporter::OpenAddress::Mapper
8
8
  validation:
9
9
  enabled: true
10
10
  default_matching_strategy: es
@@ -11,12 +11,11 @@ module AtlasEngine
11
11
  class << self
12
12
  sig do
13
13
  override.params(
14
- session: AtlasEngine::AddressValidation::Session,
15
14
  candidate: AtlasEngine::AddressValidation::Candidate,
16
15
  address_comparison: AtlasEngine::AddressValidation::Validators::FullAddress::AddressComparison,
17
16
  ).returns(T::Boolean)
18
17
  end
19
- def apply?(session, candidate, address_comparison)
18
+ def apply?(candidate, address_comparison)
20
19
  poor_city_match?(address_comparison)
21
20
  end
22
21
 
@@ -1,7 +1,7 @@
1
1
  id: SI
2
2
  ingestion:
3
- open_address:
4
- feature_mapper: AtlasEngine::Si::AddressImporter::OpenAddress::Mapper
3
+ post_address_mapper:
4
+ open_address: AtlasEngine::Si::AddressImporter::OpenAddress::Mapper
5
5
  correctors:
6
6
  open_address:
7
7
  - AtlasEngine::Si::AddressImporter::OpenAddress::Corrections::CityDistrictCorrector
@@ -1,7 +1,7 @@
1
1
  id: TT
2
2
  ingestion:
3
- open_address:
4
- feature_mapper: AtlasEngine::Tt::AddressImporter::OpenAddress::Mapper
3
+ post_address_mapper:
4
+ open_address: AtlasEngine::Tt::AddressImporter::OpenAddress::Mapper
5
5
  validation:
6
6
  address_parser: AtlasEngine::ValidationTranscriber::AddressParserNorthAmerica
7
7
  has_provinces: false
@@ -23,15 +23,15 @@ module AtlasEngine
23
23
 
24
24
  BUILDING_NAME = "(?<building_name>[\\w ]+)"
25
25
  BUILDING_NUM =
26
- "(?<building_num>("\
27
- '([[:digit:]]+\s)?([[:digit:]]+/[[:digit:]]+)|'\
28
- '[[:digit:]][[:alpha:][:digit:]/\-]*|'\
29
- '[[:alpha:]][[:digit:]][[:alpha:][:digit:]/\-]*'\
26
+ "(?<building_num>(" \
27
+ '([[:digit:]]+\s)?([[:digit:]]+/[[:digit:]]+)|' \
28
+ '[[:digit:]][[:alpha:][:digit:]/\-]*|' \
29
+ '[[:alpha:]][[:digit:]][[:alpha:][:digit:]/\-]*' \
30
30
  "))"
31
31
  NUMERIC_ONLY_BUILDING_NUM =
32
- "(?<building_num>("\
33
- '([[:digit:]]+\s+)?[[:digit:]][[:digit:]/]*[[:digit:]]|'\
34
- "[[:digit:]]+"\
32
+ "(?<building_num>(" \
33
+ '([[:digit:]]+\s+)?[[:digit:]][[:digit:]/]*[[:digit:]]|' \
34
+ "[[:digit:]]+" \
35
35
  "))"
36
36
  NON_NUMERIC_STREET = "(?<street>[^[:digit:]/ -].*)"
37
37
  STREET = "(?<street>.+)"
@@ -11,7 +11,7 @@ module AtlasEngine
11
11
  def initialize(country_import:, locale: nil)
12
12
  @country_code = country_import.country_code
13
13
  @locale = locale
14
- @mapper = CountryProfile.for(@country_code).ingestion.open_address_feature_mapper.new(
14
+ @mapper = CountryProfile.for(@country_code).ingestion.post_address_mapper("open_address").new(
15
15
  country_code: @country_code, locale: @locale,
16
16
  )
17
17
  @corrector = AddressImporter::Corrections::Corrector.new(country_code: @country_code, source: "open_address")
@@ -38,6 +38,7 @@ module AtlasEngine
38
38
  .slice(:id, :locale, :country_code, :province_code, :region1, :region2, :region3, :region4)
39
39
  .deep_symbolize_keys,
40
40
  )
41
+ data[:city] = post_address[:city].first
41
42
  data[:city_aliases] = city_aliases(post_address[:city])
42
43
  data[:suburb] = post_address[:suburb]
43
44
  data[:zip] = Worldwide::Zip.normalize(
@@ -33,7 +33,7 @@ module AtlasEngine
33
33
  end
34
34
 
35
35
  @parsings = ValidationTranscriber::AddressParsings.new(address_input: address, locale: locale)
36
- @query_builder = QueryBuilder.for(address, locale)
36
+ @query_builder = QueryBuilder.for(address, parsings, locale)
37
37
  end
38
38
 
39
39
  sig do
@@ -12,18 +12,30 @@ module AtlasEngine
12
12
  class << self
13
13
  extend T::Sig
14
14
 
15
- sig { params(address: AbstractAddress, locale: T.nilable(String)).returns(QueryBuilder) }
16
- def for(address, locale = nil)
15
+ sig do
16
+ params(
17
+ address: AbstractAddress,
18
+ parsings: AtlasEngine::ValidationTranscriber::AddressParsings,
19
+ locale: T.nilable(String),
20
+ ).returns(QueryBuilder)
21
+ end
22
+ def for(address, parsings, locale = nil)
17
23
  profile = CountryProfile.for(T.must(address.country_code), locale)
18
- profile.attributes.dig("validation", "query_builder").constantize.new(address, locale)
24
+ profile.attributes.dig("validation", "query_builder").constantize.new(address, parsings, profile)
19
25
  end
20
26
  end
21
27
 
22
- sig { params(address: AbstractAddress, locale: T.nilable(String)).void }
23
- def initialize(address, locale = nil)
28
+ sig do
29
+ params(
30
+ address: AbstractAddress,
31
+ parsings: AtlasEngine::ValidationTranscriber::AddressParsings,
32
+ profile: CountryProfile,
33
+ ).void
34
+ end
35
+ def initialize(address, parsings, profile)
24
36
  @address = address
25
- @profile = CountryProfile.for(T.must(address.country_code), locale)
26
- @parsings = ValidationTranscriber::AddressParsings.new(address_input: address, locale: locale)
37
+ @profile = profile
38
+ @parsings = parsings
27
39
  end
28
40
 
29
41
  sig { abstract.returns(T::Hash[String, T.untyped]) }
@@ -133,16 +145,22 @@ module AtlasEngine
133
145
 
134
146
  sig { returns(T.nilable(Hash)) }
135
147
  def city_clause
136
- {
137
- "nested" => {
138
- "path" => "city_aliases",
139
- "query" => {
140
- "match" => {
141
- "city_aliases.alias" => { "query" => address.city.to_s, "fuzziness" => "auto" },
148
+ if profile.validation.city_alias
149
+ {
150
+ "nested" => {
151
+ "path" => "city_aliases",
152
+ "query" => {
153
+ "match" => {
154
+ "city_aliases.alias" => { "query" => address.city.to_s, "fuzziness" => "auto" },
155
+ },
142
156
  },
143
157
  },
144
- },
145
- }
158
+ }
159
+ else
160
+ {
161
+ "match" => { "city" => { "query" => address.city.to_s, "fuzziness" => "auto" } },
162
+ }
163
+ end
146
164
  end
147
165
 
148
166
  sig { returns(Hash) }
@@ -11,18 +11,21 @@ module AtlasEngine
11
11
 
12
12
  attr_reader :address, :candidate, :datastore
13
13
 
14
+ delegate :parsings, to: :datastore
15
+
14
16
  sig { params(address: AbstractAddress, candidate: Candidate, datastore: DatastoreBase).void }
15
17
  def initialize(address:, candidate:, datastore:)
16
18
  @address = address
17
19
  @candidate = candidate
18
20
  @datastore = datastore
21
+ @comparators_hash = {}
19
22
  end
20
23
 
21
24
  sig { params(other: AddressComparison).returns(Integer) }
22
25
  def <=>(other)
23
26
  # prefer addresses having more matched fields, e.g. matching on street + city + zip is better than
24
27
  # just matching on street + zip, or street + province
25
- matches = comparisons.count(&:match?) <=> other.comparisons.count(&:match?)
28
+ matches = comparators.count(&:match?) <=> other.comparators.count(&:match?)
26
29
  return matches * -1 if matches.nonzero?
27
30
 
28
31
  # merge all sequence comparisons together, erasing the individual field boundaries, and prefer
@@ -32,7 +35,7 @@ module AtlasEngine
32
35
 
33
36
  sig { returns(String) }
34
37
  def inspect
35
- "<addrcomp street#{comparisons.inspect}/>"
38
+ "<addrcomp street#{comparators.inspect}/>"
36
39
  end
37
40
 
38
41
  sig { returns(T::Boolean) }
@@ -42,27 +45,50 @@ module AtlasEngine
42
45
 
43
46
  sig { returns(ZipComparison) }
44
47
  def zip_comparison
45
- @zip_comparison ||= field_comparison(field: :zip)
48
+ T.cast(self.for(:zip), ZipComparison)
46
49
  end
47
50
 
48
51
  sig { returns(StreetComparison) }
49
52
  def street_comparison
50
- @street_comparison ||= field_comparison(field: :street)
53
+ T.cast(self.for(:street), StreetComparison)
51
54
  end
52
55
 
53
56
  sig { returns(CityComparison) }
54
57
  def city_comparison
55
- @city_comparison ||= field_comparison(field: :city)
58
+ T.cast(self.for(:city), CityComparison)
56
59
  end
57
60
 
58
61
  sig { returns(ProvinceCodeComparison) }
59
62
  def province_code_comparison
60
- @province_code_comparison ||= field_comparison(field: :province_code)
63
+ T.cast(self.for(:province_code), ProvinceCodeComparison)
61
64
  end
62
65
 
63
66
  sig { returns(BuildingComparison) }
64
67
  def building_comparison
65
- @building_comparison ||= field_comparison(field: :building)
68
+ T.cast(self.for(:building), BuildingComparison)
69
+ end
70
+
71
+ sig { params(component: Symbol).returns(FieldComparisonBase) }
72
+ def for(component)
73
+ @comparators_hash[component] ||= begin
74
+ klass = datastore.country_profile.validation.component_comparison(component)
75
+ klass.new(
76
+ address: address,
77
+ candidate: candidate,
78
+ datastore: datastore,
79
+ component: component,
80
+ )
81
+ end
82
+ end
83
+
84
+ sig { returns(T::Array[Symbol]) }
85
+ def components
86
+ comparators.map(&:component)
87
+ end
88
+
89
+ sig { returns(T::Array[Symbol]) }
90
+ def relevant_components
91
+ comparators.select(&:relevant?).map(&:component)
66
92
  end
67
93
 
68
94
  protected
@@ -70,36 +96,24 @@ module AtlasEngine
70
96
  sig do
71
97
  returns(T::Array[FieldComparisonBase])
72
98
  end
73
- def comparisons
74
- [
75
- street_comparison,
76
- city_comparison,
77
- zip_comparison,
78
- province_code_comparison,
79
- building_comparison,
80
- ].compact_blank
99
+ def comparators
100
+ datastore.country_profile.validation.address_comparison.keys.map do |component|
101
+ self.for(component.to_sym)
102
+ end
81
103
  end
82
104
 
83
105
  sig { returns(T::Array[AtlasEngine::AddressValidation::Token::Sequence::Comparison]) }
84
106
  def text_comparisons
85
- [
86
- street_comparison.sequence_comparison,
87
- city_comparison.sequence_comparison,
88
- zip_comparison.sequence_comparison,
89
- province_code_comparison.sequence_comparison,
90
- ].compact_blank
107
+ comparators.filter_map do |comparator|
108
+ comparison = comparator.sequence_comparison
109
+ comparison if comparison.class == AtlasEngine::AddressValidation::Token::Sequence::Comparison
110
+ end.compact_blank
91
111
  end
92
112
 
93
113
  sig { returns(AtlasEngine::AddressValidation::Token::Sequence::Comparison) }
94
114
  def merged_comparison
95
115
  @merged_comparisons ||= text_comparisons.reduce(&:merge)
96
116
  end
97
-
98
- sig { params(field: Symbol).returns(FieldComparisonBase) }
99
- def field_comparison(field:)
100
- klass = CountryProfile.for(address.country_code).validation.address_comparison(field: field)
101
- klass.new(address: address, candidate: candidate, datastore: datastore)
102
- end
103
117
  end
104
118
  end
105
119
  end
@@ -8,6 +8,11 @@ module AtlasEngine
8
8
  class BuildingComparison < FieldComparisonBase
9
9
  extend T::Sig
10
10
 
11
+ sig { override.returns(T::Boolean) }
12
+ def relevant?
13
+ false
14
+ end
15
+
11
16
  sig { override.returns(T.nilable(NumberComparison)) }
12
17
  def sequence_comparison
13
18
  @building_comparison ||= NumberComparison.new(
@@ -9,8 +9,6 @@ module AtlasEngine
9
9
  extend T::Sig
10
10
  include LogHelper
11
11
 
12
- delegate :street_comparison, to: :address_comparison
13
-
14
12
  sig do
15
13
  params(
16
14
  candidate: AddressValidation::CandidateTuple,
@@ -127,8 +125,8 @@ module AtlasEngine
127
125
  def matched_and_unmatched_components
128
126
  components = {}
129
127
  @matched_and_unmatched_components ||= begin
130
- components_to_compare.each do |field|
131
- components[field] = @address_comparison.send(:"#{field}_comparison").sequence_comparison
128
+ components_to_compare.each do |component|
129
+ components[component] = @address_comparison.for(component).sequence_comparison
132
130
  end
133
131
  components
134
132
  end
@@ -8,6 +8,11 @@ module AtlasEngine
8
8
  class CityComparison < FieldComparisonBase
9
9
  extend T::Sig
10
10
 
11
+ sig { override.returns(T::Boolean) }
12
+ def relevant?
13
+ true
14
+ end
15
+
11
16
  sig { override.returns(T.nilable(Token::Sequence::Comparison)) }
12
17
  def sequence_comparison
13
18
  return @city_comparison if defined?(@city_comparison)
@@ -14,12 +14,11 @@ module AtlasEngine
14
14
 
15
15
  sig do
16
16
  abstract.params(
17
- session: Session,
18
17
  candidate: Candidate,
19
18
  address_comparison: AddressComparison,
20
19
  ).returns(T::Boolean)
21
20
  end
22
- def apply?(session, candidate, address_comparison); end
21
+ def apply?(candidate, address_comparison); end
23
22
  end
24
23
  end
25
24
  end
@@ -11,15 +11,27 @@ module AtlasEngine
11
11
 
12
12
  abstract!
13
13
 
14
- SUPPORTED_FIELDS = Set.new([:street, :city, :zip, :province_code, :building])
14
+ sig { returns(Symbol) }
15
+ attr_reader :component
15
16
 
16
- sig { params(address: AbstractAddress, candidate: Candidate, datastore: DatastoreBase).void }
17
- def initialize(address:, candidate:, datastore:)
17
+ sig do
18
+ params(
19
+ address: AbstractAddress,
20
+ candidate: Candidate,
21
+ datastore: DatastoreBase,
22
+ component: Symbol,
23
+ ).void
24
+ end
25
+ def initialize(address:, candidate:, datastore:, component:)
18
26
  @address = address
19
27
  @datastore = datastore
20
28
  @candidate = candidate
29
+ @component = component
21
30
  end
22
31
 
32
+ sig { abstract.returns(T::Boolean) }
33
+ def relevant?; end
34
+
23
35
  sig { abstract.returns(T.any(T.nilable(Token::Sequence::Comparison), T.nilable(NumberComparison))) }
24
36
  def sequence_comparison; end
25
37
 
@@ -8,6 +8,11 @@ module AtlasEngine
8
8
  class ProvinceCodeComparison < FieldComparisonBase
9
9
  extend T::Sig
10
10
 
11
+ sig { override.returns(T::Boolean) }
12
+ def relevant?
13
+ true
14
+ end
15
+
11
16
  sig { override.returns(T.nilable(Token::Sequence::Comparison)) }
12
17
  def sequence_comparison
13
18
  return @province_code_comparison if defined?(@province_code_comparison)
@@ -17,13 +17,6 @@ module AtlasEngine
17
17
  sig { returns(AddressComparison) }
18
18
  attr_reader :address_comparison
19
19
 
20
- ALL_SUPPORTED_COMPONENTS = [
21
- :province_code,
22
- :city,
23
- :zip,
24
- :street,
25
- ].freeze
26
-
27
20
  sig do
28
21
  params(
29
22
  session: Session,
@@ -35,11 +28,12 @@ module AtlasEngine
35
28
  @session = session
36
29
  @candidate = candidate
37
30
  @address_comparison = address_comparison
31
+ @all_supported_components = address_comparison.relevant_components.dup
38
32
  end
39
33
 
40
34
  sig { returns(T::Array[Symbol]) }
41
35
  def components_to_validate
42
- supported_components = ALL_SUPPORTED_COMPONENTS.dup - unsupported_components_for_country
36
+ supported_components = @all_supported_components.dup - unsupported_components_for_country
43
37
  apply_exclusions(supported_components)
44
38
  supported_components.delete(:street) if exclude_street_validation?
45
39
  supported_components
@@ -47,7 +41,7 @@ module AtlasEngine
47
41
 
48
42
  sig { returns(T::Array[Symbol]) }
49
43
  def components_to_compare
50
- ALL_SUPPORTED_COMPONENTS.dup - unsupported_components_for_country
44
+ @all_supported_components.dup - unsupported_components_for_country
51
45
  end
52
46
 
53
47
  private
@@ -56,7 +50,7 @@ module AtlasEngine
56
50
  def apply_exclusions(supported_components)
57
51
  supported_components.delete_if do |component|
58
52
  exclusions(component).any? do |exclusion|
59
- if exclusion.apply?(session, candidate, address_comparison)
53
+ if exclusion.apply?(candidate, address_comparison)
60
54
  emit_excluded_validation(component, "excluded")
61
55
  true
62
56
  end
@@ -8,6 +8,11 @@ module AtlasEngine
8
8
  class StreetComparison < FieldComparisonBase
9
9
  extend T::Sig
10
10
 
11
+ sig { override.returns(T::Boolean) }
12
+ def relevant?
13
+ true
14
+ end
15
+
11
16
  sig { override.returns(T.nilable(Token::Sequence::Comparison)) }
12
17
  def sequence_comparison
13
18
  return @street_comparison if defined?(@street_comparison)
@@ -8,6 +8,11 @@ module AtlasEngine
8
8
  class ZipComparison < FieldComparisonBase
9
9
  extend T::Sig
10
10
 
11
+ sig { override.returns(T::Boolean) }
12
+ def relevant?
13
+ true
14
+ end
15
+
11
16
  sig { override.returns(T.nilable(Token::Sequence::Comparison)) }
12
17
  def sequence_comparison
13
18
  return @zip_comparison if defined?(@zip_comparison)
@@ -71,6 +71,11 @@ module AtlasEngine
71
71
 
72
72
  DEFAULT_PROFILE = "DEFAULT"
73
73
 
74
+ COUNTRIES = T.let(
75
+ Worldwide::Regions.all.select(&:country?).reject(&:deprecated?).map(&:iso_code).to_set,
76
+ T::Set[String],
77
+ )
78
+
74
79
  add_index :id, unique: true
75
80
  self.base_path = ""
76
81
  self.backend = Backend
@@ -183,7 +188,7 @@ module AtlasEngine
183
188
  def for(country_code, locale = nil)
184
189
  raise CountryNotFoundError if country_code.blank?
185
190
 
186
- unless country_code == DEFAULT_PROFILE || Worldwide.region(code: country_code).country?
191
+ unless country_code == DEFAULT_PROFILE || COUNTRIES.include?(country_code.upcase)
187
192
  raise CountryNotFoundError
188
193
  end
189
194
 
@@ -24,9 +24,9 @@ module AtlasEngine
24
24
  attributes.dig("settings", "min_zip_edge_ngram")
25
25
  end
26
26
 
27
- sig { returns(T::Class[AddressImporter::OpenAddress::DefaultMapper]) }
28
- def open_address_feature_mapper
29
- attributes.dig("open_address", "feature_mapper").constantize
27
+ sig { params(source: String).returns(T::Class[AddressImporter::OpenAddress::DefaultMapper]) }
28
+ def post_address_mapper(source)
29
+ attributes.dig("post_address_mapper", source).constantize
30
30
  end
31
31
 
32
32
  sig { returns(T.nilable(String)) }
@@ -69,18 +69,19 @@ module AtlasEngine
69
69
  attributes.dig("unmatched_components_suggestion_threshold") || 2
70
70
  end
71
71
 
72
- sig { params(field: Symbol).returns(T::Class[AddressValidation::Validators::FullAddress::FieldComparisonBase]) }
73
- def address_comparison(field:)
74
- unless field.in?(AddressValidation::Validators::FullAddress::FieldComparisonBase::SUPPORTED_FIELDS)
75
- raise ArgumentError.new, "Field #{field} is not supported"
76
- end
77
-
78
- attributes.dig("address_comparison", field.to_s).constantize
72
+ sig { params(component: Symbol).returns(T::Class[AddressValidation::Validators::FullAddress::FieldComparisonBase]) }
73
+ def component_comparison(component)
74
+ attributes.dig("address_comparison", component.to_s).constantize
79
75
  end
80
76
 
81
77
  sig { returns(Integer) }
82
78
  def zip_prefix_length
83
79
  attributes.dig("zip_prefix_length") || 0
84
80
  end
81
+
82
+ sig { returns(T::Boolean) }
83
+ def city_alias
84
+ attributes.dig("city_alias").nil? ? true : attributes.dig("city_alias")
85
+ end
85
86
  end
86
87
  end
@@ -230,7 +230,7 @@ module AtlasEngine
230
230
  ).void
231
231
  end
232
232
  def update_aliases_for_index(index_name:, remove_alias:, add_alias:)
233
- is_writable = add_alias == active_alias ? true : false
233
+ is_writable = add_alias == active_alias
234
234
 
235
235
  body = {
236
236
  actions: [
@@ -18,12 +18,14 @@ module Maintenance
18
18
  attribute :geojson_file_path, :string
19
19
  attribute :locale, :string
20
20
 
21
- def process = ::AtlasEngine::AddressImporter::OpenAddress::GeoJsonImportLauncherJob.perform_later(
22
- country_code:,
23
- geojson_file_path: geojson_file_path.strip,
24
- clear_records:,
25
- locale:,
26
- )
21
+ def process
22
+ ::AtlasEngine::AddressImporter::OpenAddress::GeoJsonImportLauncherJob.perform_later(
23
+ country_code:,
24
+ geojson_file_path: geojson_file_path.strip,
25
+ clear_records:,
26
+ locale:,
27
+ )
28
+ end
27
29
  end
28
30
  end
29
31
  end
@@ -28,6 +28,13 @@ mappings:
28
28
  fields:
29
29
  keyword:
30
30
  type: keyword
31
+ city:
32
+ type: text
33
+ analyzer: text_analyzer
34
+ search_analyzer: city_analyzer
35
+ fields:
36
+ keyword:
37
+ type: keyword
31
38
  city_aliases:
32
39
  type: nested
33
40
  dynamic: "false"
@@ -4,11 +4,13 @@ ingestion:
4
4
  correctors: {}
5
5
  settings: {}
6
6
  data_mapper: AtlasEngine::AddressValidation::Es::DataMappers::DefaultDataMapper
7
- open_address:
8
- feature_mapper: AtlasEngine::AddressImporter::OpenAddress::DefaultMapper
7
+ post_address_mapper:
8
+ open_address: AtlasEngine::AddressImporter::OpenAddress::DefaultMapper
9
9
  validation:
10
10
  enabled: false
11
11
  has_provinces: true
12
+ zip_prefix_length: 0
13
+ city_alias: true
12
14
  index_locales: []
13
15
  default_matching_strategy: local
14
16
  normalized_components: []
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module AtlasEngine
5
- VERSION = "0.4.0"
5
+ VERSION = "0.5.0"
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: atlas_engine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-02-13 00:00:00.000000000 Z
11
+ date: 2024-02-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: annex_29