atlas_engine 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (24) hide show
  1. checksums.yaml +4 -4
  2. data/app/models/atlas_engine/address_validation/candidate.rb +3 -2
  3. data/app/models/atlas_engine/address_validation/es/candidate_selector.rb +12 -12
  4. data/app/models/atlas_engine/address_validation/es/validators/full_address.rb +9 -10
  5. data/app/models/atlas_engine/address_validation/es/validators/full_address_street.rb +1 -1
  6. data/app/models/atlas_engine/address_validation/validators/full_address/candidate_result.rb +20 -20
  7. data/app/models/atlas_engine/address_validation/validators/full_address/candidate_result_base.rb +4 -6
  8. data/app/models/atlas_engine/address_validation/validators/full_address/concern_builder.rb +8 -3
  9. data/app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_concern_builder.rb +6 -2
  10. data/app/models/atlas_engine/address_validation/validators/full_address/{invalid_zip_for_country_concern.rb → invalid_zip_for_country_concern_builder.rb} +14 -13
  11. data/app/models/atlas_engine/address_validation/validators/full_address/{invalid_zip_for_province_concern.rb → invalid_zip_for_province_concern_builder.rb} +15 -15
  12. data/app/models/atlas_engine/address_validation/validators/full_address/no_candidate_result.rb +2 -4
  13. data/app/models/atlas_engine/address_validation/validators/full_address/relevant_components.rb +9 -13
  14. data/app/models/atlas_engine/address_validation/validators/full_address/{unknown_address_concern.rb → unknown_address_concern_builder.rb} +11 -4
  15. data/app/models/atlas_engine/address_validation/validators/full_address/unknown_province_concern_builder.rb +38 -0
  16. data/app/models/atlas_engine/address_validation/validators/full_address/{unknown_zip_for_address_concern.rb → unknown_zip_for_address_concern_builder.rb} +12 -10
  17. data/app/models/atlas_engine/address_validation/validators/full_address/{unmatched_field_concern.rb → unmatched_field_concern_builder.rb} +17 -9
  18. data/app/models/atlas_engine/address_validation/validators/full_address/unsupported_script_result.rb +1 -1
  19. data/lib/atlas_engine/version.rb +1 -1
  20. metadata +8 -11
  21. data/app/models/atlas_engine/address_validation/candidate_tuple.rb +0 -15
  22. data/app/models/atlas_engine/address_validation/session.rb +0 -47
  23. data/app/models/atlas_engine/address_validation/validators/full_address/result_updater.rb +0 -42
  24. data/app/models/atlas_engine/address_validation/validators/full_address/unknown_province_concern.rb +0 -38
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3285871f59bee7bdf0084bfb5f985a6e582a173a78baa496c07ba9e8bd526eda
4
- data.tar.gz: b25b6b4d8637c34d43a78e60f457342ccd9f7117f02d039f961476a7a4ef310e
3
+ metadata.gz: 56b5b41a624c3481954aadfa0101c9883dfe3479a3cdec373f8ecccab8bae879
4
+ data.tar.gz: 73ee021ecf5d8357ae8f000df7e963e7504153fdc3b7bb98f188445aa8cd7989
5
5
  SHA512:
6
- metadata.gz: ea581fe90f17c1924f2d370fef820dc8bf18ed094e570666cdc60f13b0ec37b7e8876749176bbb14cd9f408931c525f6f7b29afdf4da47270bf24f147f8f0bce
7
- data.tar.gz: 6ef3dca52ae9bfc224d694c6cb326f743701280cb8d6be14f30421ea247c53822d8017acdeaad5641cfe34ac080ca33a1b010308575057fec2e040a1d7a3222e
6
+ metadata.gz: b93dee8561c73619222ca4a4e803fb2f911b3149955c5b1af7803990318a7ebd36e781c41643cf3076197f579833e9c2d361e8e4550a9d2d3de628d8e7819ef7
7
+ data.tar.gz: f2f593c6e2a7849dae6dce6a52d9402ce7d907a90511664d1218133b5d4a501b5ae98a26e54a06412c3fb37e3dc74c75ae17c575ae24fa4805c02ad888467d21
@@ -6,9 +6,10 @@ module AtlasEngine
6
6
  class Candidate
7
7
  extend T::Sig
8
8
  attr_reader :id, :index
9
+ attr_accessor :position
9
10
 
10
- sig { params(id: String, source: Hash, index: T.nilable(String)).void }
11
- def initialize(id:, source:, index: nil)
11
+ sig { params(id: String, source: Hash, position: Integer, index: T.nilable(String)).void }
12
+ def initialize(id:, source:, position: 0, index: nil)
12
13
  components_hash = Hash.new { |hash, key| hash[key] = Component.new(key, nil) }
13
14
 
14
15
  @components = source.each_with_object(components_hash) do |(key, value), hash|
@@ -21,7 +21,7 @@ module AtlasEngine
21
21
  end
22
22
  end
23
23
 
24
- sig { returns(T.nilable(CandidateTuple)) }
24
+ sig { returns(T.nilable(AddressValidation::Validators::FullAddress::AddressComparison)) }
25
25
  def best_candidate
26
26
  street_sequences_future = datastore.fetch_street_sequences_async
27
27
  city_sequences_future = datastore.fetch_city_sequence_async
@@ -36,28 +36,28 @@ module AtlasEngine
36
36
 
37
37
  attr_reader :datastore, :address
38
38
 
39
- sig { returns(T::Array[CandidateTuple]) }
39
+ sig { returns(T::Array[AddressValidation::Validators::FullAddress::AddressComparison]) }
40
40
  def sorted_candidates
41
- sorted_candidate_tuples = datastore.fetch_full_address_candidates
41
+ sorted_address_comparisons = datastore.fetch_full_address_candidates
42
42
  .filter_map.with_index(1) do |candidate, position|
43
- address_comparison = AtlasEngine::AddressValidation::Validators::FullAddress::AddressComparison.new(
43
+ candidate.position = position
44
+ address_comparison = AddressValidation::Validators::FullAddress::AddressComparison.new(
44
45
  address: address,
45
46
  candidate: candidate,
46
47
  datastore: datastore,
47
48
  )
48
- tuple = CandidateTuple.new(address_comparison, position, candidate)
49
- tuple if tuple.address_comparison.potential_match?
49
+ address_comparison if address_comparison.potential_match?
50
50
  end.sort
51
51
 
52
- emit_sorted_candidates(sorted_candidate_tuples)
53
- sorted_candidate_tuples
52
+ emit_sorted_candidates(sorted_address_comparisons.map(&:candidate))
53
+ sorted_address_comparisons
54
54
  end
55
55
 
56
- sig { params(sorted_candidate_tuples: T::Array[CandidateTuple]).void }
57
- def emit_sorted_candidates(sorted_candidate_tuples)
58
- log_info("Sorted candidates:\n #{sorted_candidate_tuples.map { |tuple| tuple.candidate.serialize }}")
56
+ sig { params(sorted_candidates: T::Array[Candidate]).void }
57
+ def emit_sorted_candidates(sorted_candidates)
58
+ log_info("Sorted candidates:\n #{sorted_candidates.map(&:serialize)}")
59
59
 
60
- initial_position_top_candidate = sorted_candidate_tuples.first&.position || 0
60
+ initial_position_top_candidate = sorted_candidates.first&.position || 0
61
61
  StatsD.distribution(
62
62
  "AddressValidation.query.initial_position_top_candidate",
63
63
  initial_position_top_candidate,
@@ -9,12 +9,11 @@ module AtlasEngine
9
9
  include LogHelper
10
10
 
11
11
  attr_reader :address, :result
12
- attr_accessor :session
13
12
 
14
13
  sig { params(address: TAddress, result: Result).void }
15
14
  def initialize(address:, result: Result.new)
16
15
  super
17
- @session = T.let(Session.new(address: address, matching_strategy: MatchingStrategies::Es), Session)
16
+ @matching_strategy = MatchingStrategies::Es
18
17
  end
19
18
 
20
19
  sig { override.returns(Result) }
@@ -30,23 +29,23 @@ module AtlasEngine
30
29
  sig { returns(AddressValidation::Validators::FullAddress::CandidateResultBase) }
31
30
  def build_candidate_result
32
31
  unless supported_address?(address)
33
- return AddressValidation::Validators::FullAddress::UnsupportedScriptResult.new(session:, result:)
32
+ return AddressValidation::Validators::FullAddress::UnsupportedScriptResult.new(address:, result:)
34
33
  end
35
34
 
36
35
  if best_candidate.nil?
37
- AddressValidation::Validators::FullAddress::NoCandidateResult.new(session:, result:)
36
+ AddressValidation::Validators::FullAddress::NoCandidateResult.new(address:, result:)
38
37
  else
39
38
  AddressValidation::Validators::FullAddress::CandidateResult.new(
40
- candidate: T.must(best_candidate),
39
+ address_comparison: T.must(best_candidate),
40
+ matching_strategy: @matching_strategy,
41
41
  result: result,
42
- session: session,
43
42
  )
44
43
  end
45
44
  end
46
45
 
47
46
  private
48
47
 
49
- sig { returns(T.nilable(CandidateTuple)) }
48
+ sig { returns(T.nilable(AddressValidation::Validators::FullAddress::AddressComparison)) }
50
49
  def best_candidate
51
50
  @best_candidate ||= T.let(
52
51
  begin
@@ -63,15 +62,15 @@ module AtlasEngine
63
62
  # We want our futures to complete even when we do not consume their value.
64
63
  candidate_futures&.map(&:wait!)
65
64
  end,
66
- T.nilable(CandidateTuple),
65
+ T.nilable(AddressValidation::Validators::FullAddress::AddressComparison),
67
66
  )
68
67
  end
69
68
 
70
69
  sig { params(locale: T.nilable(String)).returns(Concurrent::Promises::Future) }
71
70
  def best_candidate_future(locale = nil)
72
71
  AddressValidation::Es::CandidateSelector.new(
73
- datastore: session.datastore(locale: locale),
74
- address: session.address,
72
+ datastore: Es::Datastore.new(address: address, locale: locale),
73
+ address: address,
75
74
  ).best_candidate_async
76
75
  end
77
76
 
@@ -9,7 +9,7 @@ module AtlasEngine
9
9
  sig { params(address: TAddress, result: Result).void }
10
10
  def initialize(address:, result: Result.new)
11
11
  super
12
- @session = T.let(Session.new(address: address, matching_strategy: MatchingStrategies::EsStreet), Session)
12
+ @matching_strategy = MatchingStrategies::EsStreet
13
13
  end
14
14
  end
15
15
  end
@@ -11,16 +11,16 @@ module AtlasEngine
11
11
 
12
12
  sig do
13
13
  params(
14
- candidate: AddressValidation::CandidateTuple,
15
- session: Session,
14
+ address_comparison: AddressComparison,
15
+ matching_strategy: AddressValidation::MatchingStrategies,
16
16
  result: Result,
17
- )
18
- .void
17
+ ).void
19
18
  end
20
- def initialize(candidate:, session:, result:)
21
- super(session: session, result: result)
22
- @candidate = candidate.candidate
23
- @address_comparison = candidate.address_comparison
19
+ def initialize(address_comparison:, matching_strategy:, result:)
20
+ super(address: address_comparison.address, result: result)
21
+ @address_comparison = address_comparison
22
+ @candidate = address_comparison.candidate
23
+ @matching_strategy = matching_strategy
24
24
  end
25
25
 
26
26
  sig { override.void }
@@ -34,7 +34,7 @@ module AtlasEngine
34
34
 
35
35
  sig { returns(T::Boolean) }
36
36
  def suggestable?
37
- ConcernBuilder.should_suggest?(session.address, unmatched_components.keys)
37
+ ConcernBuilder.should_suggest?(address, unmatched_components.keys)
38
38
  end
39
39
 
40
40
  private
@@ -56,11 +56,11 @@ module AtlasEngine
56
56
 
57
57
  sig { void }
58
58
  def add_concerns_without_suggestions
59
- concern = InvalidZipConcernBuilder.for(session.address, [])
59
+ concern = InvalidZipConcernBuilder.for(address, [])
60
60
  result.concerns << concern if concern
61
61
 
62
- if ConcernBuilder.too_many_unmatched_components?(session.address, unmatched_components.keys)
63
- result.concerns << UnknownAddressConcern.new(session.address)
62
+ if ConcernBuilder.too_many_unmatched_components?(address, unmatched_components.keys)
63
+ result.concerns << UnknownAddressConcernBuilder.new(address).build
64
64
  end
65
65
  end
66
66
 
@@ -77,7 +77,7 @@ module AtlasEngine
77
77
  unmatched_component: unmatched_component,
78
78
  unmatched_field: field_name,
79
79
  matched_components: matched_components_to_validate.keys,
80
- address: session.address,
80
+ address: address,
81
81
  suggestion_ids: [suggestion.id].compact,
82
82
  ).build
83
83
  result.concerns << concern
@@ -90,7 +90,7 @@ module AtlasEngine
90
90
  unmatched_fields = { street: unmatched_field_name(:street) }.compact
91
91
 
92
92
  @suggestion ||= SuggestionBuilder.from_comparisons(
93
- session.address.to_h,
93
+ address.to_h,
94
94
  unmatched_components_to_validate,
95
95
  candidate,
96
96
  unmatched_fields,
@@ -126,7 +126,7 @@ module AtlasEngine
126
126
  components = {}
127
127
  @matched_and_unmatched_components ||= begin
128
128
  components_to_compare.each do |component|
129
- components[component] = @address_comparison.for(component).sequence_comparison
129
+ components[component] = address_comparison.for(component).sequence_comparison
130
130
  end
131
131
  components
132
132
  end
@@ -144,7 +144,7 @@ module AtlasEngine
144
144
 
145
145
  sig { returns(RelevantComponents) }
146
146
  def relevant_components
147
- @relevant_components ||= RelevantComponents.new(session, candidate, address_comparison)
147
+ @relevant_components ||= RelevantComponents.new(address_comparison, @matching_strategy)
148
148
  end
149
149
 
150
150
  sig do
@@ -167,17 +167,17 @@ module AtlasEngine
167
167
 
168
168
  original_street = T.must(unmatched_components_to_validate[:street]).left_sequence.raw_value
169
169
 
170
- if session.address.address1.to_s.include?(original_street)
170
+ if address.address1.to_s.include?(original_street)
171
171
  :address1
172
- elsif session.address.address2.to_s.include?(original_street)
172
+ elsif address.address2.to_s.include?(original_street)
173
173
  :address2
174
174
  end
175
175
  end
176
176
 
177
177
  sig { void }
178
178
  def log_unknown_field_name
179
- potential_streets = { potential_streets: session.parsings.potential_streets }
180
- input_address = session.address.to_h.compact_blank.except(:phone)
179
+ potential_streets = { potential_streets: address_comparison.parsings.potential_streets }
180
+ input_address = address.to_h.compact_blank.except(:phone)
181
181
  log_details = input_address.merge(potential_streets)
182
182
  log_info("[AddressValidation] Unable to identify unmatched field name", log_details)
183
183
  end
@@ -11,9 +11,9 @@ module AtlasEngine
11
11
 
12
12
  abstract!
13
13
 
14
- sig { params(session: Session, result: Result).void }
15
- def initialize(session:, result:)
16
- @session = session
14
+ sig { params(address: AbstractAddress, result: Result).void }
15
+ def initialize(address:, result:)
16
+ @address = address
17
17
  @result = result
18
18
  end
19
19
 
@@ -22,9 +22,7 @@ module AtlasEngine
22
22
 
23
23
  private
24
24
 
25
- attr_reader :session, :result
26
-
27
- delegate :address, to: :session
25
+ attr_reader :result, :address
28
26
 
29
27
  sig { void }
30
28
  def update_result_scope
@@ -110,7 +110,7 @@ module AtlasEngine
110
110
  return concern if concern
111
111
 
112
112
  if :province_code.in?(matched_components) && :city.in?(matched_components)
113
- return UnknownZipForAddressConcern.new(address, suggestion_ids)
113
+ return UnknownZipForAddressConcernBuilder.new(address).build(suggestion_ids)
114
114
  end
115
115
 
116
116
  build_default_concern
@@ -119,7 +119,7 @@ module AtlasEngine
119
119
  sig { returns(AddressValidation::Concern) }
120
120
  def build_province_concern
121
121
  if ([:zip, :city] - matched_components).empty?
122
- UnknownProvinceConcern.new(address, suggestion_ids)
122
+ UnknownProvinceConcernBuilder.new(address).build(suggestion_ids)
123
123
  else
124
124
  build_default_concern
125
125
  end
@@ -127,7 +127,12 @@ module AtlasEngine
127
127
 
128
128
  sig { returns(AddressValidation::Concern) }
129
129
  def build_default_concern
130
- UnmatchedFieldConcern.new(unmatched_component, matched_components, address, suggestion_ids, unmatched_field)
130
+ UnmatchedFieldConcernBuilder.new(
131
+ unmatched_component,
132
+ matched_components,
133
+ address,
134
+ unmatched_field,
135
+ ).build(suggestion_ids)
131
136
  end
132
137
  end
133
138
  end
@@ -22,9 +22,13 @@ module AtlasEngine
22
22
  return unless country.has_zip?
23
23
 
24
24
  if country_expects_zone_in_address?(country) && province.province?
25
- InvalidZipForProvinceConcern.new(address, suggestion_ids) unless province.valid_zip?(address.zip)
25
+ return if province.valid_zip?(address.zip)
26
+
27
+ InvalidZipForProvinceConcernBuilder.new(address).build
26
28
  else
27
- InvalidZipForCountryConcern.new(address, suggestion_ids) unless country.valid_zip?(address.zip)
29
+ return if country.valid_zip?(address.zip)
30
+
31
+ InvalidZipForCountryConcernBuilder.new(address).build(suggestion_ids)
28
32
  end
29
33
  end
30
34
 
@@ -5,31 +5,32 @@ module AtlasEngine
5
5
  module AddressValidation
6
6
  module Validators
7
7
  module FullAddress
8
- class InvalidZipForCountryConcern < AddressValidation::Concern
8
+ class InvalidZipForCountryConcernBuilder
9
+ extend T::Sig
9
10
  include ConcernFormatter
10
11
  attr_reader :address
11
12
 
12
- sig { params(address: AbstractAddress, suggestion_ids: T::Array[String]).void }
13
- def initialize(address, suggestion_ids)
13
+ sig { params(address: AbstractAddress).void }
14
+ def initialize(address)
14
15
  @address = address
16
+ end
17
+
18
+ sig { params(suggestion_ids: T::Array[String]).returns(Concern) }
19
+ def build(suggestion_ids = [])
20
+ message = country.field(key: :zip).error(
21
+ code: :invalid_for_country,
22
+ options: { country: country.full_name },
23
+ ).to_s
15
24
 
16
- super(
25
+ Concern.new(
17
26
  code: :zip_invalid_for_country,
18
27
  field_names: [:zip],
19
28
  message: message,
20
29
  type: T.must(Concern::TYPES[:error]),
21
30
  type_level: 1,
22
- suggestion_ids: suggestion_ids
31
+ suggestion_ids: suggestion_ids,
23
32
  )
24
33
  end
25
-
26
- sig { returns(String) }
27
- def message
28
- country.field(key: :zip).error(
29
- code: :invalid_for_country,
30
- options: { country: country.full_name },
31
- ).to_s
32
- end
33
34
  end
34
35
  end
35
36
  end
@@ -5,30 +5,30 @@ module AtlasEngine
5
5
  module AddressValidation
6
6
  module Validators
7
7
  module FullAddress
8
- class InvalidZipForProvinceConcern < AddressValidation::Concern
8
+ class InvalidZipForProvinceConcernBuilder
9
+ extend T::Sig
9
10
  include ConcernFormatter
10
11
  attr_reader :address
11
12
 
12
- sig { params(address: AbstractAddress, suggestion_ids: T::Array[String]).void }
13
- def initialize(address, suggestion_ids)
13
+ def initialize(address)
14
14
  @address = address
15
-
16
- super(
17
- code: :zip_invalid_for_province,
18
- field_names: [:zip],
19
- message: message,
20
- type: T.must(Concern::TYPES[:error]),
21
- type_level: 1,
22
- suggestion_ids: suggestion_ids
23
- )
24
15
  end
25
16
 
26
- sig { returns(String) }
27
- def message
28
- country.field(key: :zip).error(
17
+ sig { params(suggestion_ids: T::Array[String]).returns(Concern) }
18
+ def build(suggestion_ids = [])
19
+ message = country.field(key: :zip).error(
29
20
  code: :invalid_for_province,
30
21
  options: { province: province_name },
31
22
  ).to_s
23
+
24
+ Concern.new(
25
+ field_names: [:zip],
26
+ code: :zip_invalid_for_province,
27
+ type: T.must(Concern::TYPES[:error]),
28
+ type_level: 1,
29
+ suggestion_ids: suggestion_ids,
30
+ message: message,
31
+ )
32
32
  end
33
33
  end
34
34
  end
@@ -10,11 +10,9 @@ module AtlasEngine
10
10
 
11
11
  sig { void }
12
12
  def update_result
13
- result.concerns << UnknownAddressConcern.new(
14
- address,
15
- )
13
+ result.concerns << UnknownAddressConcernBuilder.new(address).build
16
14
 
17
- concern = InvalidZipConcernBuilder.for(session.address, [])
15
+ concern = InvalidZipConcernBuilder.for(address, [])
18
16
  result.concerns << concern if concern
19
17
 
20
18
  update_result_scope
@@ -8,9 +8,6 @@ module AtlasEngine
8
8
  class RelevantComponents
9
9
  extend T::Sig
10
10
 
11
- sig { returns(Session) }
12
- attr_reader :session
13
-
14
11
  sig { returns(Candidate) }
15
12
  attr_reader :candidate
16
13
 
@@ -19,15 +16,15 @@ module AtlasEngine
19
16
 
20
17
  sig do
21
18
  params(
22
- session: Session,
23
- candidate: Candidate,
24
19
  address_comparison: AddressComparison,
20
+ matching_strategy: AtlasEngine::AddressValidation::MatchingStrategies,
25
21
  ).void
26
22
  end
27
- def initialize(session, candidate, address_comparison)
28
- @session = session
29
- @candidate = candidate
23
+ def initialize(address_comparison, matching_strategy)
30
24
  @address_comparison = address_comparison
25
+ @matching_strategy = matching_strategy
26
+ @address = address_comparison.address
27
+ @candidate = address_comparison.candidate
31
28
  @all_supported_components = address_comparison.relevant_components.dup
32
29
  end
33
30
 
@@ -62,8 +59,7 @@ module AtlasEngine
62
59
  def exclude_street_validation?
63
60
  return @exclude_street_validation if defined?(@exclude_street_validation)
64
61
 
65
- @exclude_street_validation = if session.matching_strategy !=
66
- AddressValidation::MatchingStrategies::EsStreet
62
+ @exclude_street_validation = if @matching_strategy != AddressValidation::MatchingStrategies::EsStreet
67
63
  true
68
64
  elsif address_comparison.street_comparison.sequence_comparison.blank?
69
65
  emit_excluded_validation(:street, "not_found")
@@ -80,7 +76,7 @@ module AtlasEngine
80
76
 
81
77
  sig { returns(CountryProfile) }
82
78
  def country_profile
83
- @country_profile ||= CountryProfile.for(session.country_code)
79
+ @country_profile ||= CountryProfile.for(@address.country_code)
84
80
  end
85
81
 
86
82
  sig { params(component: Symbol, reason: String).void }
@@ -88,7 +84,7 @@ module AtlasEngine
88
84
  tags = [
89
85
  "reason:#{reason}",
90
86
  "component:#{component}",
91
- "country:#{session.country_code}",
87
+ "country:#{@address.country_code}",
92
88
  ]
93
89
  StatsD.increment("AddressValidation.skip", sample_rate: 1.0, tags: tags)
94
90
  end
@@ -97,7 +93,7 @@ module AtlasEngine
97
93
  def unsupported_components_for_country
98
94
  @unsupported_components_for_country ||= begin
99
95
  unsupported_components = []
100
- country = Worldwide.region(code: session.address.country_code)
96
+ country = Worldwide.region(code: @address.country_code)
101
97
  unsupported_components << :province_code if country.province_optional?
102
98
  unsupported_components << :province_code if country.hide_provinces_from_addresses
103
99
  unsupported_components << :city unless country.city_required?
@@ -5,7 +5,8 @@ module AtlasEngine
5
5
  module AddressValidation
6
6
  module Validators
7
7
  module FullAddress
8
- class UnknownAddressConcern < AddressValidation::Concern
8
+ class UnknownAddressConcernBuilder
9
+ extend T::Sig
9
10
  include ConcernFormatter
10
11
 
11
12
  sig { returns(TAddress) }
@@ -14,12 +15,18 @@ module AtlasEngine
14
15
  sig { params(address: TAddress).void }
15
16
  def initialize(address)
16
17
  @address = address
17
- super(
18
+ end
19
+
20
+ sig { params(suggestion_ids: T::Array[String]).returns(Concern) }
21
+ def build(suggestion_ids = [])
22
+ message = country.field(key: :address).error(code: :may_not_exist)
23
+
24
+ Concern.new(
18
25
  code: :address_unknown,
19
- message: Worldwide.region(code: address.country_code).field(key: :address).error(code: :may_not_exist),
26
+ message: message,
20
27
  type: T.must(Concern::TYPES[:warning]),
21
28
  type_level: 1,
22
- suggestion_ids: [],
29
+ suggestion_ids: suggestion_ids,
23
30
  field_names: [:address1],
24
31
  )
25
32
  end
@@ -0,0 +1,38 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module AtlasEngine
5
+ module AddressValidation
6
+ module Validators
7
+ module FullAddress
8
+ class UnknownProvinceConcernBuilder
9
+ extend T::Sig
10
+ include ConcernFormatter
11
+ attr_reader :address
12
+
13
+ sig { params(address: AbstractAddress).void }
14
+ def initialize(address)
15
+ @address = address
16
+ end
17
+
18
+ sig { params(suggestion_ids: T::Array[String]).returns(Concern) }
19
+ def build(suggestion_ids = [])
20
+ message = country.field(key: :province).error(
21
+ code: :unknown_for_city_and_zip,
22
+ options: { city: address.city, zip: address.zip },
23
+ ).to_s
24
+
25
+ Concern.new(
26
+ code: :province_inconsistent,
27
+ field_names: [:province],
28
+ message: message,
29
+ type: T.must(Concern::TYPES[:error]),
30
+ type_level: 1,
31
+ suggestion_ids: suggestion_ids,
32
+ )
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -5,26 +5,28 @@ module AtlasEngine
5
5
  module AddressValidation
6
6
  module Validators
7
7
  module FullAddress
8
- class UnknownZipForAddressConcern < AddressValidation::Concern
8
+ class UnknownZipForAddressConcernBuilder
9
+ extend T::Sig
9
10
  attr_reader :address
10
11
 
11
- sig { params(address: AbstractAddress, suggestion_ids: T::Array[String]).void }
12
- def initialize(address, suggestion_ids)
12
+ sig { params(address: AbstractAddress).void }
13
+ def initialize(address)
13
14
  @address = address
14
- super(
15
+ end
16
+
17
+ sig { params(suggestion_ids: T::Array[String]).returns(Concern) }
18
+ def build(suggestion_ids = [])
19
+ message = "Enter a valid ZIP for #{address.address1}, #{address.city}"
20
+
21
+ Concern.new(
15
22
  code: :zip_inconsistent,
16
23
  field_names: [:zip],
17
24
  message: message,
18
25
  type: T.must(Concern::TYPES[:warning]),
19
26
  type_level: 3,
20
- suggestion_ids: suggestion_ids
27
+ suggestion_ids: suggestion_ids,
21
28
  )
22
29
  end
23
-
24
- sig { returns(String) }
25
- def message
26
- "Enter a valid ZIP for #{address.address1}, #{address.city}"
27
- end
28
30
  end
29
31
  end
30
32
  end
@@ -5,9 +5,10 @@ module AtlasEngine
5
5
  module AddressValidation
6
6
  module Validators
7
7
  module FullAddress
8
- class UnmatchedFieldConcern < AddressValidation::Concern
8
+ class UnmatchedFieldConcernBuilder
9
+ extend T::Sig
9
10
  include ConcernFormatter
10
- attr_reader :component, :matched_components, :address, :unmatched_field
11
+ attr_reader :address, :component, :matched_components, :unmatched_field
11
12
 
12
13
  COMPONENTS_TO_LABELS = {
13
14
  zip: "ZIP",
@@ -25,26 +26,34 @@ module AtlasEngine
25
26
  unmatched_component: Symbol,
26
27
  matched_components: T::Array[Symbol],
27
28
  address: AbstractAddress,
28
- suggestion_ids: T::Array[String],
29
29
  unmatched_field: T.nilable(Symbol),
30
30
  ).void
31
31
  end
32
- def initialize(unmatched_component, matched_components, address, suggestion_ids, unmatched_field = nil)
32
+ def initialize(unmatched_component, matched_components, address, unmatched_field = nil)
33
+ @address = address
33
34
  @component = unmatched_component
34
35
  @matched_components = matched_components
35
- @address = address
36
36
  @unmatched_field = unmatched_field
37
+ end
37
38
 
38
- super(
39
+ sig do
40
+ params(
41
+ suggestion_ids: T::Array[String],
42
+ ).returns(Concern)
43
+ end
44
+ def build(suggestion_ids = [])
45
+ Concern.new(
39
46
  code: code,
40
47
  field_names: field_names,
41
48
  message: message,
42
49
  type: T.must(Concern::TYPES[:warning]),
43
50
  type_level: 3,
44
- suggestion_ids: suggestion_ids
51
+ suggestion_ids: suggestion_ids,
45
52
  )
46
53
  end
47
54
 
55
+ private
56
+
48
57
  sig { returns(String) }
49
58
  def message
50
59
  "Enter a valid #{COMPONENTS_TO_LABELS[component]} for #{valid_address_component_values.join(", ")}"
@@ -60,8 +69,6 @@ module AtlasEngine
60
69
  [field_name]
61
70
  end
62
71
 
63
- private
64
-
65
72
  sig { returns(T::Array[String]) }
66
73
  def valid_address_component_values
67
74
  matched_components.last(2).map do |component|
@@ -74,6 +81,7 @@ module AtlasEngine
74
81
  SHORTENED_COMPONENT_NAMES[component] || component
75
82
  end
76
83
 
84
+ sig { returns(Symbol) }
77
85
  def field_name
78
86
  unmatched_field || shortened_component_name
79
87
  end
@@ -10,7 +10,7 @@ module AtlasEngine
10
10
 
11
11
  sig { void }
12
12
  def update_result
13
- concern = InvalidZipConcernBuilder.for(session.address, [])
13
+ concern = InvalidZipConcernBuilder.for(address, [])
14
14
  result.concerns << concern if concern
15
15
 
16
16
  update_result_scope
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module AtlasEngine
5
- VERSION = "0.5.0"
5
+ VERSION = "0.6.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.5.0
4
+ version: 0.6.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-20 00:00:00.000000000 Z
11
+ date: 2024-02-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: annex_29
@@ -437,7 +437,6 @@ files:
437
437
  - app/models/atlas_engine/address_validation/abstract_address.rb
438
438
  - app/models/atlas_engine/address_validation/address.rb
439
439
  - app/models/atlas_engine/address_validation/candidate.rb
440
- - app/models/atlas_engine/address_validation/candidate_tuple.rb
441
440
  - app/models/atlas_engine/address_validation/concern.rb
442
441
  - app/models/atlas_engine/address_validation/concern_producer.rb
443
442
  - app/models/atlas_engine/address_validation/concern_queue.rb
@@ -463,7 +462,6 @@ files:
463
462
  - app/models/atlas_engine/address_validation/request.rb
464
463
  - app/models/atlas_engine/address_validation/result.rb
465
464
  - app/models/atlas_engine/address_validation/runs_validation.rb
466
- - app/models/atlas_engine/address_validation/session.rb
467
465
  - app/models/atlas_engine/address_validation/statsd_emitter.rb
468
466
  - app/models/atlas_engine/address_validation/strategies.rb
469
467
  - app/models/atlas_engine/address_validation/suggestion.rb
@@ -485,20 +483,19 @@ files:
485
483
  - app/models/atlas_engine/address_validation/validators/full_address/exclusions/exclusion_base.rb
486
484
  - app/models/atlas_engine/address_validation/validators/full_address/field_comparison_base.rb
487
485
  - app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_concern_builder.rb
488
- - app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_for_country_concern.rb
489
- - app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_for_province_concern.rb
486
+ - app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_for_country_concern_builder.rb
487
+ - app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_for_province_concern_builder.rb
490
488
  - app/models/atlas_engine/address_validation/validators/full_address/no_candidate_result.rb
491
489
  - app/models/atlas_engine/address_validation/validators/full_address/number_comparison.rb
492
490
  - app/models/atlas_engine/address_validation/validators/full_address/postal_code_matcher.rb
493
491
  - app/models/atlas_engine/address_validation/validators/full_address/province_code_comparison.rb
494
492
  - app/models/atlas_engine/address_validation/validators/full_address/relevant_components.rb
495
- - app/models/atlas_engine/address_validation/validators/full_address/result_updater.rb
496
493
  - app/models/atlas_engine/address_validation/validators/full_address/street_comparison.rb
497
494
  - app/models/atlas_engine/address_validation/validators/full_address/suggestion_builder.rb
498
- - app/models/atlas_engine/address_validation/validators/full_address/unknown_address_concern.rb
499
- - app/models/atlas_engine/address_validation/validators/full_address/unknown_province_concern.rb
500
- - app/models/atlas_engine/address_validation/validators/full_address/unknown_zip_for_address_concern.rb
501
- - app/models/atlas_engine/address_validation/validators/full_address/unmatched_field_concern.rb
495
+ - app/models/atlas_engine/address_validation/validators/full_address/unknown_address_concern_builder.rb
496
+ - app/models/atlas_engine/address_validation/validators/full_address/unknown_province_concern_builder.rb
497
+ - app/models/atlas_engine/address_validation/validators/full_address/unknown_zip_for_address_concern_builder.rb
498
+ - app/models/atlas_engine/address_validation/validators/full_address/unmatched_field_concern_builder.rb
502
499
  - app/models/atlas_engine/address_validation/validators/full_address/unsupported_script_result.rb
503
500
  - app/models/atlas_engine/address_validation/validators/full_address/zip_comparison.rb
504
501
  - app/models/atlas_engine/address_validation/validators/predicates/cache.rb
@@ -1,15 +0,0 @@
1
- # typed: true
2
- # frozen_string_literal: true
3
-
4
- module AtlasEngine
5
- module AddressValidation
6
- CandidateTuple = Struct.new(:address_comparison, :position, :candidate) do
7
- extend T::Sig
8
-
9
- sig { params(other: CandidateTuple).returns(Integer) }
10
- def <=>(other)
11
- to_a[0..1] <=> other.to_a[0..1] # only consider address_comparison and position
12
- end
13
- end
14
- end
15
- end
@@ -1,47 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- require "forwardable"
5
-
6
- module AtlasEngine
7
- module AddressValidation
8
- class Session
9
- extend Forwardable
10
- extend T::Sig
11
-
12
- sig { returns(AbstractAddress) }
13
- attr_reader :address
14
-
15
- sig { returns(MatchingStrategies) }
16
- attr_accessor :matching_strategy
17
-
18
- sig { returns(T::Hash[String, AtlasEngine::AddressValidation::DatastoreBase]) }
19
- attr_reader :datastore_hash
20
-
21
- def_delegators :@address, :address1, :address2, :city, :province_code, :country_code, :zip, :phone
22
-
23
- sig do
24
- params(
25
- address: AbstractAddress,
26
- matching_strategy: MatchingStrategies,
27
- ).void
28
- end
29
- def initialize(address:, matching_strategy: MatchingStrategies::Es)
30
- @address = address
31
- @matching_strategy = matching_strategy
32
- @datastore_hash = T.let({}, T::Hash[String, AtlasEngine::AddressValidation::DatastoreBase])
33
- end
34
-
35
- sig { params(locale: T.nilable(String)).returns(ValidationTranscriber::AddressParsings) }
36
- def parsings(locale: nil)
37
- datastore(locale: locale).parsings
38
- end
39
-
40
- sig { params(locale: T.nilable(String)).returns(AtlasEngine::AddressValidation::DatastoreBase) }
41
- def datastore(locale: nil)
42
- key = locale || "default"
43
- @datastore_hash[key] ||= AtlasEngine::AddressValidation::Es::Datastore.new(address: address, locale: locale)
44
- end
45
- end
46
- end
47
- end
@@ -1,42 +0,0 @@
1
- # typed: true
2
- # frozen_string_literal: true
3
-
4
- module AtlasEngine
5
- module AddressValidation
6
- module Validators
7
- module FullAddress
8
- class ResultUpdater
9
- extend T::Sig
10
- extend T::Helpers
11
- abstract!
12
-
13
- sig { params(session: Session, result: Result).void }
14
- def initialize(session:, result:)
15
- @session = session
16
- @result = result
17
- end
18
-
19
- private
20
-
21
- attr_reader :session, :result
22
-
23
- delegate :address, to: :session
24
-
25
- sig { void }
26
- def update_result_scope
27
- concern_fields = result.concerns.flat_map(&:field_names).uniq
28
- scopes_to_remove = concern_fields.flat_map { |field| contained_scopes_for(field) }
29
- result.validation_scope.reject! { |scope| scope.in?(scopes_to_remove) }
30
- end
31
-
32
- sig { params(scope: Symbol).returns(T.nilable(T::Array[Symbol])) }
33
- def contained_scopes_for(scope)
34
- return [] unless (scope_index = Result::SORTED_VALIDATION_SCOPES.index(scope))
35
-
36
- Result::SORTED_VALIDATION_SCOPES.slice(scope_index..)
37
- end
38
- end
39
- end
40
- end
41
- end
42
- end
@@ -1,38 +0,0 @@
1
- # typed: true
2
- # frozen_string_literal: true
3
-
4
- module AtlasEngine
5
- module AddressValidation
6
- module Validators
7
- module FullAddress
8
- class UnknownProvinceConcern < AddressValidation::Concern
9
- include ConcernFormatter
10
- attr_reader :address
11
-
12
- sig { params(address: AbstractAddress, suggestion_ids: T::Array[String]).void }
13
- def initialize(address, suggestion_ids)
14
- @address = address
15
- super(
16
- code: :province_inconsistent,
17
- field_names: [:province],
18
- message: message,
19
- type: T.must(Concern::TYPES[:error]),
20
- type_level: 1,
21
- suggestion_ids: suggestion_ids
22
- )
23
- end
24
-
25
- sig { returns(String) }
26
- def message
27
- country
28
- .field(key: :province)
29
- .error(
30
- code: :unknown_for_city_and_zip,
31
- options: { city: address.city, zip: address.zip },
32
- ).to_s
33
- end
34
- end
35
- end
36
- end
37
- end
38
- end