addressing 0.1.1 → 0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 93c92e35c1ba9b99ef0f8614354be6ce1140417527f1e3b53d97f5e03e430f42
4
- data.tar.gz: fdc66a367d15c31344f36e82db8c5740d57eefb34dc9e9219822bb5de4b2501d
3
+ metadata.gz: 0f6ea26657e38313826abc6c9dbab406b426b07ac6d03af922ab130d6b00e29f
4
+ data.tar.gz: d3037ec9973ae1e7f0054eece0bd3e1a7a683eda4f2c4b1ad04294b3112684c6
5
5
  SHA512:
6
- metadata.gz: c30cd13e71d74a015a551975032e0800b44ccded30378fee6c1603572bf2a8dee27f57dfda894ac358ff33e26407692ed11d0e9d7ef72f3a67756e77295f812f
7
- data.tar.gz: 35897859d6db9035e7fdde7282af57ebe042034a8d759a5eb8a9a79d76b91ea30ed6a5e84403c8ee74071f10c6d8879adf421d56037b5d641f8b384d22a6fd98
6
+ metadata.gz: 6db0b294a6ee4fb0cbb787a86e0fe506c539ea5a94ae7cb170373524540dd44a2139c90d0b6951d34728b42b19a84e3eed60bb7d50e8685ce4b65f9c21bbabb6
7
+ data.tar.gz: d6a857986eff573f2e136ccd1a07eb8b0da618ce00cb78af44590708a7dca54a79f1facbd2bd48ab48a9bcd66f7cce919e0c3d906572c8eebc40f12f0b5e976a
data/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  All notable changes to `addressing` will be documented in this file.
4
4
 
5
+ ## 0.2.0 (25-02-2022)
6
+
7
+ - Add ActiveRecord validations
8
+
5
9
  ## 0.1.1 (21-02-2022)
6
10
 
7
11
  - Fix typo in DE custom format
data/README.md CHANGED
@@ -172,6 +172,16 @@ p formatter.format(address, origin_country: "FR")
172
172
  # ÉTATS-UNIS - UNITED STATES
173
173
  ```
174
174
 
175
+ ### Validating addresses
176
+
177
+ For Active Record models, use:
178
+
179
+ ```rb
180
+ class User < ApplicationRecord
181
+ validates_address_format
182
+ end
183
+ ```
184
+
175
185
  ## Changelog
176
186
 
177
187
  Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.
@@ -203,5 +213,3 @@ Feel free to open an issue to get feedback on your idea before spending too much
203
213
  ## License
204
214
 
205
215
  The MIT License (MIT). Please see [License File](LICENSE.md) for more information.
206
-
207
- https://github.com/countries/countries/blob/eddb4af3889e5c8b66d897f9789d43c4a1ee0598/spec/thread_safety_spec.rb
data/data/country/zh.json CHANGED
@@ -35,7 +35,6 @@
35
35
  "MK": "北马其顿",
36
36
  "BJ": "贝宁",
37
37
  "BE": "比利时",
38
- "PE": "秘鲁",
39
38
  "IS": "冰岛",
40
39
  "PR": "波多黎各",
41
40
  "PL": "波兰",
@@ -149,6 +148,7 @@
149
148
  "MN": "蒙古",
150
149
  "MS": "蒙特塞拉特",
151
150
  "BD": "孟加拉国",
151
+ "PE": "秘鲁",
152
152
  "FM": "密克罗尼西亚",
153
153
  "MM": "缅甸",
154
154
  "MD": "摩尔多瓦",
@@ -18,6 +18,11 @@ module Addressing
18
18
  @subdivisions.any?
19
19
  end
20
20
 
21
+ def empty?
22
+ do_initialize unless @initialized
23
+ @subdivisions.empty?
24
+ end
25
+
21
26
  private
22
27
 
23
28
  def do_initialize
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Addressing
4
+ module Model
5
+ def validates_address_format(**options)
6
+ class_eval do
7
+ validate :verify_address_format, **options
8
+
9
+ define_method :verify_address_format do
10
+ fields = [:country_code, :administrative_area, :locality, :dependent_locality, :postal_code, :sorting_code, :address_line1, :address_line2, :organization, :given_name, :additional_name, :family_name, :locale].each_with_object({}) do |field, fields|
11
+ fields[field] = send(field)
12
+ end
13
+
14
+ address = Address.new(**fields)
15
+ return unless address.country_code.present?
16
+
17
+ address_format = AddressFormat.get(address.country_code)
18
+ address_format.used_fields
19
+
20
+ return unless address.country_code.present?
21
+
22
+ address_format = AddressFormat.get(address.country_code)
23
+ address_format.used_fields
24
+
25
+ # Validate the presence of required fields.
26
+ address_format.required_fields.each do |required_field|
27
+ next unless address.send(required_field).blank?
28
+
29
+ errors.add(required_field, "should not be blank")
30
+ end
31
+
32
+ # Validate the absence of unused fields.
33
+ unused_fields = AddressField.all.values - address_format.used_fields
34
+ unused_fields.each do |unused_field|
35
+ next if address.send(unused_field).blank?
36
+
37
+ errors.add(unused_field, "should be blank")
38
+ end
39
+
40
+ # Validate subdivisions.
41
+ subdivisions = verify_subdivisions(address, address_format)
42
+
43
+ # Validate postal code.
44
+ verify_postal_code(address.postal_code, subdivisions, address_format) if address_format.used_fields.include?(AddressField::POSTAL_CODE)
45
+ end
46
+
47
+ define_method :verify_subdivisions do |address, address_format|
48
+ # No predefined subdivisions exist, nothing to validate against.
49
+ return [] if address_format.subdivision_depth < 1
50
+
51
+ subdivisions, _parents = address_format.used_subdivision_fields.each_with_index.inject([[], []]) do |(subdivisions, parents), (field, index)|
52
+ # The field is empty or validation is disabled.
53
+ # break subdivisions if address.send(field).blank? || address_format.hidden_fields.include?(field)
54
+ break subdivisions if address.send(field).blank?
55
+
56
+ parents << (index > 0 ? address.send(address_format.used_subdivision_fields[index - 1]) : address_format.country_code)
57
+ subdivision = Subdivision.get(address.send(field), parents)
58
+ if subdivision.nil?
59
+ errors.add(field, "should be valid")
60
+ break [subdivisions, parents]
61
+ end
62
+
63
+ subdivisions << subdivision
64
+ # No predefined subdivisions below this level, stop here.
65
+ break [subdivisions, parents] if subdivision.children.empty?
66
+
67
+ [subdivisions, parents]
68
+ end
69
+
70
+ subdivisions
71
+ end
72
+
73
+ define_method :verify_postal_code do |postal_code, subdivisions, address_format|
74
+ # Nothing to validate.
75
+ return if postal_code.blank?
76
+
77
+ full_pattern, start_pattern = subdivisions.inject([address_format.postal_code_pattern, nil]) do |(full_pattern, start_pattern), subdivision|
78
+ pattern = subdivision.postal_code_pattern
79
+ next [full_pattern, start_pattern] if pattern.blank?
80
+ next [pattern, start_pattern] if subdivision.postal_code_pattern_type == PatternType::FULL
81
+
82
+ [full_pattern, pattern]
83
+ end
84
+
85
+ if full_pattern
86
+ # The pattern must match the provided value completely.
87
+ match = postal_code.match(Regexp.new(full_pattern.gsub("\\\\", "\\").to_s, "i"))
88
+ if match.nil? || match[0] != postal_code
89
+ errors.add(AddressField::POSTAL_CODE, "should be valid")
90
+ return
91
+ end
92
+ end
93
+
94
+ if start_pattern
95
+ # The pattern must match the start of the provided value.
96
+ match = postal_code.match(Regexp.new(start_pattern.gsub("\\\\", "\\").to_s, "i"))
97
+ if match.nil? || postal_code.index(match[0]) != 0
98
+ errors.add(AddressField::POSTAL_CODE, "should be valid")
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Addressing
4
- VERSION = "0.1.1"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/addressing.rb CHANGED
@@ -28,3 +28,10 @@ module Addressing
28
28
 
29
29
  class UnknownLocaleError < Error; end
30
30
  end
31
+
32
+ if defined?(ActiveSupport.on_load)
33
+ ActiveSupport.on_load(:active_record) do
34
+ require "addressing/model"
35
+ extend Addressing::Model
36
+ end
37
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: addressing
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robin van der Vleuten
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-02-21 00:00:00.000000000 Z
11
+ date: 2022-02-25 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: robinvdvleuten@gmail.com
@@ -684,7 +684,6 @@ files:
684
684
  - lib/addressing/address.rb
685
685
  - lib/addressing/address_field.rb
686
686
  - lib/addressing/address_format.rb
687
- - lib/addressing/address_format_validator.rb
688
687
  - lib/addressing/administrative_area_type.rb
689
688
  - lib/addressing/country.rb
690
689
  - lib/addressing/default_formatter.rb
@@ -693,6 +692,7 @@ files:
693
692
  - lib/addressing/lazy_subdivisions.rb
694
693
  - lib/addressing/locale.rb
695
694
  - lib/addressing/locality_type.rb
695
+ - lib/addressing/model.rb
696
696
  - lib/addressing/pattern_type.rb
697
697
  - lib/addressing/postal_code_type.rb
698
698
  - lib/addressing/postal_label_formatter.rb
File without changes