addressing 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +32 -0
  3. data/README.md +223 -112
  4. data/data/UPSTREAM_VERSION +1 -0
  5. data/data/address_formats.json +2256 -206
  6. data/data/countries.json +1282 -0
  7. data/data/locale.json +222 -0
  8. data/data/subdivision/BR-AC.json +22 -22
  9. data/data/subdivision/BR-AL.json +102 -102
  10. data/data/subdivision/BR-AM.json +62 -62
  11. data/data/subdivision/BR-AP.json +16 -16
  12. data/data/subdivision/BR-BA.json +417 -417
  13. data/data/subdivision/BR-CE.json +184 -184
  14. data/data/subdivision/BR-DF.json +1 -1
  15. data/data/subdivision/BR-ES.json +79 -79
  16. data/data/subdivision/BR-GO.json +246 -246
  17. data/data/subdivision/BR-MA.json +217 -217
  18. data/data/subdivision/BR-MG.json +853 -853
  19. data/data/subdivision/BR-MS.json +78 -78
  20. data/data/subdivision/BR-MT.json +141 -141
  21. data/data/subdivision/BR-PA.json +144 -144
  22. data/data/subdivision/BR-PB.json +223 -223
  23. data/data/subdivision/BR-PE.json +185 -185
  24. data/data/subdivision/BR-PI.json +223 -223
  25. data/data/subdivision/BR-PR.json +400 -400
  26. data/data/subdivision/BR-RJ.json +93 -93
  27. data/data/subdivision/BR-RN.json +166 -166
  28. data/data/subdivision/BR-RO.json +52 -52
  29. data/data/subdivision/BR-RR.json +15 -15
  30. data/data/subdivision/BR-RS.json +497 -497
  31. data/data/subdivision/BR-SC.json +295 -295
  32. data/data/subdivision/BR-SE.json +75 -75
  33. data/data/subdivision/BR-SP.json +645 -645
  34. data/data/subdivision/BR-TO.json +139 -139
  35. data/data/subdivision/CL-AI.json +10 -10
  36. data/data/subdivision/CL-AN.json +9 -9
  37. data/data/subdivision/CL-AP.json +4 -4
  38. data/data/subdivision/CL-AR.json +32 -32
  39. data/data/subdivision/CL-AT.json +9 -9
  40. data/data/subdivision/CL-BI.json +34 -34
  41. data/data/subdivision/CL-CO.json +15 -15
  42. data/data/subdivision/CL-LI.json +33 -33
  43. data/data/subdivision/CL-LL.json +30 -30
  44. data/data/subdivision/CL-LR.json +12 -12
  45. data/data/subdivision/CL-MA.json +11 -11
  46. data/data/subdivision/CL-ML.json +30 -30
  47. data/data/subdivision/CL-NB.json +21 -21
  48. data/data/subdivision/CL-RM.json +52 -52
  49. data/data/subdivision/CL-TA.json +7 -7
  50. data/data/subdivision/CL-VS.json +38 -38
  51. data/data/subdivision/CV.json +9 -9
  52. data/data/subdivision/KY.json +3 -3
  53. data/data/subdivision/TV.json +1 -1
  54. data/lib/addressing/address.rb +7 -3
  55. data/lib/addressing/address_format.rb +55 -81
  56. data/lib/addressing/address_validator.rb +98 -0
  57. data/lib/addressing/blank.rb +32 -0
  58. data/lib/addressing/country.rb +28 -314
  59. data/lib/addressing/data_source.rb +75 -0
  60. data/lib/addressing/default_formatter.rb +25 -25
  61. data/lib/addressing/enum.rb +2 -6
  62. data/lib/addressing/field_violation.rb +17 -0
  63. data/lib/addressing/lazy_subdivisions.rb +16 -15
  64. data/lib/addressing/locale.rb +20 -269
  65. data/lib/addressing/model.rb +20 -78
  66. data/lib/addressing/postal_label_formatter.rb +16 -15
  67. data/lib/addressing/subdivision.rb +113 -116
  68. data/lib/addressing/version.rb +1 -1
  69. data/lib/addressing.rb +6 -1
  70. metadata +9 -3
  71. data/data/address_formats.dump +0 -0
@@ -1,33 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Addressing
4
+ # The children of a subdivision, loaded on first access.
5
+ #
6
+ # Behaves like the hash that Subdivision.all returns for the same parents.
4
7
  class LazySubdivisions
8
+ extend Forwardable
9
+ include Enumerable
10
+
11
+ def_delegators :subdivisions, :each, :size, :keys, :values, :key?, :include?, :member?, :[], :fetch, :select, :filter, :reject
12
+
5
13
  def initialize(parents)
6
14
  @parents = parents
7
- @subdivisions = {}
8
- @initialized = false
9
15
  end
10
16
 
11
- def [](key)
12
- do_initialize unless @initialized
13
- @subdivisions[key]
17
+ # Checks for children without building them.
18
+ def empty?
19
+ @subdivisions ? @subdivisions.empty? : !Subdivision.any?(@parents)
14
20
  end
15
21
 
16
- def any?
17
- do_initialize unless @initialized
18
- @subdivisions.any?
19
- end
22
+ def any?(*args, &block)
23
+ return subdivisions.any?(*args, &block) if block || args.any?
20
24
 
21
- def empty?
22
- do_initialize unless @initialized
23
- @subdivisions.empty?
25
+ !empty?
24
26
  end
25
27
 
26
28
  private
27
29
 
28
- def do_initialize
29
- @initialized = true
30
- @subdivisions = Subdivision.all(@parents)
30
+ def subdivisions
31
+ @subdivisions ||= Subdivision.all(@parents)
31
32
  end
32
33
  end
33
34
  end
@@ -2,228 +2,6 @@
2
2
 
3
3
  module Addressing
4
4
  class Locale
5
- ALIASES = {
6
- "az-AZ" => "az-Latn-AZ",
7
- "bs-BA" => "bs-Latn-BA",
8
- "ha-GH" => "ha-Latn-GH",
9
- "ha-NE" => "ha-Latn-NE",
10
- "ha-NG" => "ha-Latn-NG",
11
- "in" => "id",
12
- "in-ID" => "id-ID",
13
- "iw" => "he",
14
- "iw-IL" => "he-IL",
15
- "kk-KZ" => "kk-Cyrl-KZ",
16
- "ks-IN" => "ks-Arab-IN",
17
- "ky-KG" => "ky-Cyrl-KG",
18
- "mn-MN" => "mn-Cyrl-MN",
19
- "mo" => "ro-MD",
20
- "ms-BN" => "ms-Latn-BN",
21
- "ms-MY" => "ms-Latn-MY",
22
- "ms-SG" => "ms-Latn-SG",
23
- "no" => "nb",
24
- "no-NO" => "nb-NO",
25
- "no-NO-NY" => "nn-NO",
26
- "pa-IN" => "pa-Guru-IN",
27
- "pa-PK" => "pa-Arab-PK",
28
- "sh" => "sr-Latn",
29
- "sh-BA" => "sr-Latn-BA",
30
- "sh-CS" => "sr-Latn-RS",
31
- "sh-YU" => "sr-Latn-RS",
32
- "shi-MA" => "shi-Tfng-MA",
33
- "sr-BA" => "sr-Cyrl-BA",
34
- "sr-ME" => "sr-Latn-ME",
35
- "sr-RS" => "sr-Cyrl-RS",
36
- "sr-XK" => "sr-Cyrl-XK",
37
- "tl" => "fil",
38
- "tl-PH" => "fil-PH",
39
- "tzm-MA" => "tzm-Latn-MA",
40
- "ug-CN" => "ug-Arab-CN",
41
- "uz-AF" => "uz-Arab-AF",
42
- "uz-UZ" => "uz-Latn-UZ",
43
- "vai-LR" => "vai-Vaii-LR",
44
- "zh-CN" => "zh-Hans-CN",
45
- "zh-HK" => "zh-Hant-HK",
46
- "zh-MO" => "zh-Hant-MO",
47
- "zh-SG" => "zh-Hans-SG",
48
- "zh-TW" => "zh-Hant-TW"
49
- }.freeze
50
-
51
- PARENTS = {
52
- "en-150" => "en-001",
53
- "en-AG" => "en-001",
54
- "en-AI" => "en-001",
55
- "en-AT" => "en-150",
56
- "en-AU" => "en-001",
57
- "en-BB" => "en-001",
58
- "en-BE" => "en-150",
59
- "en-BM" => "en-001",
60
- "en-BS" => "en-001",
61
- "en-BW" => "en-001",
62
- "en-BZ" => "en-001",
63
- "en-CC" => "en-001",
64
- "en-CH" => "en-150",
65
- "en-CK" => "en-001",
66
- "en-CM" => "en-001",
67
- "en-CX" => "en-001",
68
- "en-CY" => "en-001",
69
- "en-CZ" => "en-150",
70
- "en-DE" => "en-150",
71
- "en-DG" => "en-001",
72
- "en-DK" => "en-150",
73
- "en-DM" => "en-001",
74
- "en-ER" => "en-001",
75
- "en-ES" => "en-150",
76
- "en-FI" => "en-150",
77
- "en-FJ" => "en-001",
78
- "en-FK" => "en-001",
79
- "en-FM" => "en-001",
80
- "en-FR" => "en-150",
81
- "en-GB" => "en-001",
82
- "en-GD" => "en-001",
83
- "en-GG" => "en-001",
84
- "en-GH" => "en-001",
85
- "en-GI" => "en-001",
86
- "en-GM" => "en-001",
87
- "en-GS" => "en-001",
88
- "en-GY" => "en-001",
89
- "en-HK" => "en-001",
90
- "en-HU" => "en-150",
91
- "en-ID" => "en-001",
92
- "en-IE" => "en-001",
93
- "en-IL" => "en-001",
94
- "en-IM" => "en-001",
95
- "en-IN" => "en-001",
96
- "en-IO" => "en-001",
97
- "en-IT" => "en-150",
98
- "en-JE" => "en-001",
99
- "en-JM" => "en-001",
100
- "en-KE" => "en-001",
101
- "en-KI" => "en-001",
102
- "en-KN" => "en-001",
103
- "en-KY" => "en-001",
104
- "en-LC" => "en-001",
105
- "en-LR" => "en-001",
106
- "en-LS" => "en-001",
107
- "en-MG" => "en-001",
108
- "en-MO" => "en-001",
109
- "en-MS" => "en-001",
110
- "en-MT" => "en-001",
111
- "en-MU" => "en-001",
112
- "en-MV" => "en-001",
113
- "en-MW" => "en-001",
114
- "en-MY" => "en-001",
115
- "en-NA" => "en-001",
116
- "en-NF" => "en-001",
117
- "en-NG" => "en-001",
118
- "en-NL" => "en-150",
119
- "en-NO" => "en-150",
120
- "en-NR" => "en-001",
121
- "en-NU" => "en-001",
122
- "en-NZ" => "en-001",
123
- "en-PG" => "en-001",
124
- "en-PK" => "en-001",
125
- "en-PL" => "en-150",
126
- "en-PN" => "en-001",
127
- "en-PT" => "en-150",
128
- "en-PW" => "en-001",
129
- "en-RO" => "en-150",
130
- "en-RW" => "en-001",
131
- "en-SB" => "en-001",
132
- "en-SC" => "en-001",
133
- "en-SD" => "en-001",
134
- "en-SE" => "en-150",
135
- "en-SG" => "en-001",
136
- "en-SH" => "en-001",
137
- "en-SI" => "en-150",
138
- "en-SK" => "en-150",
139
- "en-SL" => "en-001",
140
- "en-SS" => "en-001",
141
- "en-SX" => "en-001",
142
- "en-SZ" => "en-001",
143
- "en-TC" => "en-001",
144
- "en-TK" => "en-001",
145
- "en-TO" => "en-001",
146
- "en-TT" => "en-001",
147
- "en-TV" => "en-001",
148
- "en-TZ" => "en-001",
149
- "en-UG" => "en-001",
150
- "en-VC" => "en-001",
151
- "en-VG" => "en-001",
152
- "en-VU" => "en-001",
153
- "en-WS" => "en-001",
154
- "en-ZA" => "en-001",
155
- "en-ZM" => "en-001",
156
- "en-ZW" => "en-001",
157
- "es-AR" => "es-419",
158
- "es-BO" => "es-419",
159
- "es-BR" => "es-419",
160
- "es-BZ" => "es-419",
161
- "es-CL" => "es-419",
162
- "es-CO" => "es-419",
163
- "es-CR" => "es-419",
164
- "es-CU" => "es-419",
165
- "es-DO" => "es-419",
166
- "es-EC" => "es-419",
167
- "es-GT" => "es-419",
168
- "es-HN" => "es-419",
169
- "es-MX" => "es-419",
170
- "es-NI" => "es-419",
171
- "es-PA" => "es-419",
172
- "es-PE" => "es-419",
173
- "es-PR" => "es-419",
174
- "es-PY" => "es-419",
175
- "es-SV" => "es-419",
176
- "es-US" => "es-419",
177
- "es-UY" => "es-419",
178
- "es-VE" => "es-419",
179
- "hi-Latn" => "und",
180
- "ht" => "fr-HT",
181
- "nb" => "no",
182
- "nn" => "no",
183
- "pt-AO" => "pt-PT",
184
- "pt-CH" => "pt-PT",
185
- "pt-CV" => "pt-PT",
186
- "pt-GQ" => "pt-PT",
187
- "pt-GW" => "pt-PT",
188
- "pt-LU" => "pt-PT",
189
- "pt-MO" => "pt-PT",
190
- "pt-MZ" => "pt-PT",
191
- "pt-ST" => "pt-PT",
192
- "pt-TL" => "pt-PT",
193
- "az-Arab" => "und",
194
- "az-Cyrl" => "und",
195
- "bal-Latn" => "und",
196
- "blt-Latn" => "und",
197
- "bs-Cyrl" => "und",
198
- "byn-Latn" => "und",
199
- "en-Dsrt" => "und",
200
- "en-Shaw" => "und",
201
- "iu-Latn" => "und",
202
- "kk-Arab" => "und",
203
- "ks-Deva" => "und",
204
- "ku-Arab" => "und",
205
- "ky-Arab" => "und",
206
- "ky-Latn" => "und",
207
- "ml-Arab" => "und",
208
- "mn-Mong" => "und",
209
- "mni-Mtei" => "und",
210
- "ms-Arab" => "und",
211
- "pa-Arab" => "und",
212
- "sat-Deva" => "und",
213
- "sd-Deva" => "und",
214
- "sd-Khoj" => "und",
215
- "sd-Sind" => "und",
216
- "so-Arab" => "und",
217
- "sr-Latn" => "und",
218
- "sw-Arab" => "und",
219
- "tg-Arab" => "und",
220
- "uz-Arab" => "und",
221
- "uz-Cyrl" => "und",
222
- "yue-Hans" => "und",
223
- "zh-Hant" => "und",
224
- "zh-Hant-MO" => "zh-Hant-HK"
225
- }.freeze
226
-
227
5
  # Checks whether two locales match.
228
6
  def self.match(first_locale, second_locale)
229
7
  return false if first_locale.to_s.empty? || second_locale.to_s.empty?
@@ -238,12 +16,7 @@ module Addressing
238
16
  def self.match_candidates(first_locale, second_locale)
239
17
  return false if first_locale.to_s.empty? || second_locale.to_s.empty?
240
18
 
241
- first_locale = canonicalize(first_locale)
242
- second_locale = canonicalize(second_locale)
243
- first_locale_candidates = candidates(first_locale)
244
- second_locale_candidates = candidates(second_locale)
245
-
246
- (first_locale_candidates & second_locale_candidates).any?
19
+ (candidates(canonicalize(first_locale)) & candidates(canonicalize(second_locale))).any?
247
20
  end
248
21
 
249
22
  # Resolves the locale from the available locales.
@@ -254,14 +27,7 @@ module Addressing
254
27
  # If no candidate is found in the list, an error is raised.
255
28
  def self.resolve(available_locales, locale, fallback_locale = nil)
256
29
  locale = canonicalize(locale)
257
- resolved_locale = nil
258
-
259
- candidates(locale, fallback_locale).each do |candidate|
260
- if available_locales.include?(candidate)
261
- resolved_locale = candidate
262
- break
263
- end
264
- end
30
+ resolved_locale = candidates(locale, fallback_locale).find { |candidate| available_locales.include?(candidate) }
265
31
 
266
32
  # No locale could be resolved, stop here.
267
33
  raise UnknownLocaleError.new(locale) if resolved_locale.nil?
@@ -304,54 +70,39 @@ module Addressing
304
70
  # 1) sr-Latn
305
71
  # 2) sr
306
72
  def self.candidates(locale, fallback_locale = nil)
307
- locale = replace_alias(locale)
308
- candidates = [locale]
309
-
310
- while (parent = parent(locale))
311
- candidates << parent
312
- locale = parent
313
- end
314
-
315
- if fallback_locale
316
- candidates << fallback_locale
317
-
318
- while (parent = parent(fallback_locale))
319
- candidates << parent
320
- fallback_locale = parent
321
- end
322
- end
323
-
73
+ candidates = lineage(replace_alias(locale))
74
+ candidates += lineage(fallback_locale) if fallback_locale
324
75
  candidates.uniq
325
76
  end
326
77
 
78
+ # Gets the given locale followed by its parents.
79
+ def self.lineage(locale)
80
+ lineage = [locale]
81
+ lineage << locale while (locale = parent(locale))
82
+ lineage
83
+ end
84
+ private_class_method :lineage
85
+
327
86
  # Gets the parent for the given locale.
328
87
  def self.parent(locale)
329
- parent = nil
330
-
331
- if PARENTS.key?(locale)
332
- parent = PARENTS[locale]
333
- elsif locale.include?("-")
334
- locale_parts = locale.split("-")
335
- locale_parts.pop
336
- parent = locale_parts.join("-")
337
- end
88
+ parent = definitions["parents"].fetch(locale) { locale.include?("-") ? locale.rpartition("-").first : nil }
338
89
 
339
90
  # The library doesn't have data for the empty `und` locale, it
340
91
  # is more user friendly to use the configured fallback instead.
341
- if parent == "und"
342
- parent = nil
343
- end
344
-
345
- parent
92
+ (parent == "und") ? nil : parent
346
93
  end
347
94
 
348
95
  # Replaces a locale alias with the real locale.
349
96
  #
350
97
  # For example, "zh-CN" is replaced with "zh-Hans-CN".
351
98
  def self.replace_alias(locale)
352
- return locale if locale.to_s.empty? || !ALIASES.key?(locale)
99
+ definitions["aliases"].fetch(locale, locale)
100
+ end
353
101
 
354
- ALIASES[locale]
102
+ # Gets the locale aliases and parents.
103
+ def self.definitions
104
+ Addressing.data_source.fetch("locale")
355
105
  end
106
+ private_class_method :definitions
356
107
  end
357
108
  end
@@ -2,94 +2,36 @@
2
2
 
3
3
  module Addressing
4
4
  module Model
5
+ # The error message for each kind of field violation.
6
+ FIELD_VIOLATION_MESSAGES = {
7
+ blank: "should not be blank",
8
+ present: "should be blank",
9
+ invalid: "should be valid"
10
+ }.freeze
11
+ private_constant :FIELD_VIOLATION_MESSAGES
12
+
5
13
  def validates_address_format(
6
- fields: [:country_code, :administrative_area, :locality, :dependent_locality, :postal_code, :sorting_code, :address_line1, :address_line2, :organization, :given_name, :additional_name, :family_name, :locale], field_overrides: nil, verify_postal_code: true, **options
14
+ fields: Address::FIELDS, field_overrides: nil, verify_postal_code: true, **options
7
15
  )
8
16
  fields = Array(fields)
9
17
  field_overrides ||= FieldOverrides.new({})
10
18
 
11
- options[:if] ||= -> { fields.any? { |f| changes.key?(f.to_s) } } unless options[:unless]
12
-
13
- class_eval do
14
- validate :verify_address_format, **options
15
-
16
- define_method :verify_address_format do
17
- values = fields.each_with_object({}) { |f, v| v[f] = send(f) if respond_to?(f) }
18
- address = Address.new(**values)
19
-
20
- return unless address.country_code.present?
21
-
22
- address_format = AddressFormat.get(address.country_code)
23
-
24
- # Validate the presence of required fields.
25
- AddressFormatHelper.required_fields(address_format, field_overrides).each do |required_field|
26
- next unless address.send(required_field).blank?
27
-
28
- errors.add(required_field, "should not be blank")
29
- end
30
-
31
- used_fields = address_format.used_fields - field_overrides.hidden_fields
32
-
33
- # Validate the absence of unused fields.
34
- unused_fields = AddressField.all.values - used_fields
35
- unused_fields.each do |unused_field|
36
- next if address.send(unused_field).blank?
37
-
38
- errors.add(unused_field, "should be blank")
39
- end
40
-
41
- # Validate subdivisions.
42
- subdivisions = verify_subdivisions(address, address_format, field_overrides)
43
-
44
- # Validate postal code.
45
- verify_postal_code(address.postal_code, subdivisions, address_format) if used_fields.include?(AddressField::POSTAL_CODE) && verify_postal_code
46
- end
47
-
48
- define_method :verify_subdivisions do |address, address_format, field_overrides|
49
- parents = [address_format.country_code]
50
- subdivisions = []
51
-
52
- address_format.subdivision_fields.each do |field|
53
- value = address.send(field)
54
- # The field is empty or validation is disabled.
55
- break if value.blank? || field_overrides.hidden_fields.include?(field)
56
-
57
- subdivision = Subdivision.get(value, parents)
58
- if subdivision.nil?
59
- errors.add(field, "should be valid")
60
- break
61
- end
62
-
63
- parents << value
64
- subdivisions << subdivision
65
- # No predefined subdivisions below this level, stop here.
66
- break unless subdivision.children?
67
- end
68
-
69
- subdivisions
70
- end
71
-
72
- define_method :verify_postal_code do |postal_code, subdivisions, address_format|
73
- # Nothing to validate.
74
- return if postal_code.blank?
19
+ # Without change tracking, as on a plain ActiveModel class, validate every time.
20
+ options[:if] ||= -> { !respond_to?(:changes) || fields.any? { |f| changes.key?(f.to_s) } } unless options[:unless]
75
21
 
76
- pattern = subdivisions.inject(address_format.postal_code_pattern) do |pattern, subdivision|
77
- subdivision_pattern = subdivision.postal_code_pattern
78
- next pattern if subdivision_pattern.blank?
22
+ validate :validate_address_format, **options
79
23
 
80
- subdivision_pattern
81
- end
24
+ # A method rather than a block, so that a later call, in a subclass for
25
+ # example, replaces the configuration of an earlier one.
26
+ define_method :validate_address_format do
27
+ values = fields.each_with_object({}) { |f, v| v[f] = send(f) if respond_to?(f) }
28
+ address = Address.new(**values)
82
29
 
83
- if pattern
84
- # The pattern must match the provided value completely.
85
- match = postal_code.match(Regexp.new(pattern.gsub("\\\\", "\\").to_s, "i"))
86
- if match.nil? || match[0] != postal_code
87
- errors.add(AddressField::POSTAL_CODE, "should be valid")
88
- nil
89
- end
90
- end
30
+ AddressValidator.validate(address, field_overrides: field_overrides, verify_postal_code: verify_postal_code).each do |violation|
31
+ errors.add(violation.field, violation.kind, message: FIELD_VIOLATION_MESSAGES.fetch(violation.kind))
91
32
  end
92
33
  end
34
+ private :validate_address_format
93
35
  end
94
36
  end
95
37
  end
@@ -2,28 +2,30 @@
2
2
 
3
3
  module Addressing
4
4
  class PostalLabelFormatter < DefaultFormatter
5
- DEFAULT_OPTIONS = {
6
- locale: DEFAULT_LOCALE,
7
- html: false,
8
- html_tag: "p",
9
- html_attributes: {translate: "no"},
10
- origin_country: ""
11
- }
5
+ DEFAULT_OPTIONS = DefaultFormatter::DEFAULT_OPTIONS.merge(html: false, origin_country: "")
12
6
 
13
7
  protected
14
8
 
15
- def build_view(address, address_format, options)
16
- raise ArgumentError, "The origin_country option cannot be empty." if options[:origin_country].empty?
9
+ # The origin country has no default, so format raises until it is given,
10
+ # to the constructor or to format.
11
+ def assert_options(options)
12
+ super
13
+
14
+ return unless options.key?(:origin_country)
15
+
16
+ origin_country = options[:origin_country]
17
+ raise ArgumentError, "The option `origin_country` must be a non-empty string." unless origin_country.is_a?(String) && !origin_country.empty?
18
+ end
17
19
 
20
+ def build_view(address, address_format, options)
18
21
  view = super
19
- view = view.map do |key, element|
22
+ view.each do |key, element|
20
23
  # Uppercase fields where required by the format.
21
24
  element[:value] = element[:value].upcase if address_format.uppercase_fields.include?(key)
22
- [key, element]
23
- end.to_h
25
+ end
24
26
 
25
27
  # Handle international mailing.
26
- if address.country_code != options[:origin_country]
28
+ if address.country_code != options[:origin_country].upcase
27
29
  # Prefix the postal code.
28
30
  field = AddressField::POSTAL_CODE
29
31
 
@@ -37,8 +39,7 @@ module Addressing
37
39
  # transit, it is desirable for the name of the country of
38
40
  # destination to be added in an internationally known language.
39
41
  country = view["country"][:value]
40
- english_countries = Country.list("en")
41
- english_country = english_countries[address.country_code]
42
+ english_country = country_list("en")[address.country_code]
42
43
 
43
44
  if country != english_country
44
45
  country += " - #{english_country}"