addressing 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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