addressing 0.1.0 → 0.3.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 +4 -4
- data/CHANGELOG.md +15 -1
- data/README.md +18 -2
- data/data/address_formats.dump +0 -0
- data/data/address_formats.json +1 -1
- data/data/country/zh.json +1 -1
- data/data/library_customizations.rb +1 -1
- data/lib/addressing/address_field.rb +0 -2
- data/lib/addressing/address_format.rb +21 -0
- data/lib/addressing/administrative_area_type.rb +0 -2
- data/lib/addressing/dependent_locality_type.rb +0 -2
- data/lib/addressing/enum.rb +2 -0
- data/lib/addressing/field_override.rb +33 -0
- data/lib/addressing/lazy_subdivisions.rb +7 -0
- data/lib/addressing/locality_type.rb +0 -2
- data/lib/addressing/model.rb +111 -0
- data/lib/addressing/pattern_type.rb +0 -2
- data/lib/addressing/postal_code_type.rb +0 -2
- data/lib/addressing/subdivision.rb +1 -1
- data/lib/addressing/version.rb +1 -1
- data/lib/addressing.rb +10 -0
- metadata +4 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: b46d807aa97c2e089222447115d7862105246f37f850e65f824f8599af5d714d
         | 
| 4 | 
            +
              data.tar.gz: b2f82f834eb10ead8e14e9b63083093b94a27bdec7a157a7102ee6c01eb15e6a
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: fb86d0f70a24db611837a597b3f8846a545f9c16d0df2099d6baab0235cc27ff0730b97f55b138b1d946715e3a9a671b6af23544ba59851d6f10b1cde428d9e5
         | 
| 7 | 
            +
              data.tar.gz: 4b4c5ce9982c8faaf53a6eab5117b8250d17fc3e11ffb34e24e3765ad931b5ad1fbd4031633a132c23c7c4d489131ff5364af22a0d695acad02e349b23414d25
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -2,6 +2,20 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            All notable changes to `addressing` will be documented in this file.
         | 
| 4 4 |  | 
| 5 | 
            -
            ## 0. | 
| 5 | 
            +
            ## 0.3.0 (04-04-2022)
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            - Allow field validation to be overridden
         | 
| 8 | 
            +
            - Only verify address when one of the field changes
         | 
| 9 | 
            +
            - Allow used address fields to be configured
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            ## 0.2.0 (25-02-2022)
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            - Add ActiveRecord validations
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            ## 0.1.1 (21-02-2022)
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            - Fix typo in DE custom format
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            ## 0.1.0 (07-02-2022)
         | 
| 6 20 |  | 
| 7 21 | 
             
            - Initial release
         | 
    
        data/README.md
    CHANGED
    
    | @@ -172,6 +172,24 @@ 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 | 
            +
             | 
| 185 | 
            +
            For performance, the address is only verified if at least one of the fields changes. Set your own condition with:
         | 
| 186 | 
            +
             | 
| 187 | 
            +
            ```rb
         | 
| 188 | 
            +
            class User < ApplicationRecord
         | 
| 189 | 
            +
              validates_address if: -> { something_changed? }, ...
         | 
| 190 | 
            +
            end
         | 
| 191 | 
            +
            ```
         | 
| 192 | 
            +
             | 
| 175 193 | 
             
            ## Changelog
         | 
| 176 194 |  | 
| 177 195 | 
             
            Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.
         | 
| @@ -203,5 +221,3 @@ Feel free to open an issue to get feedback on your idea before spending too much | |
| 203 221 | 
             
            ## License
         | 
| 204 222 |  | 
| 205 223 | 
             
            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/address_formats.dump
    CHANGED
    
    | Binary file | 
    
        data/data/address_formats.json
    CHANGED
    
    | @@ -42,7 +42,7 @@ | |
| 42 42 | 
             
            {"country_code": "CX","format": "%organization\n%given_name %family_name\n%address_line1\n%address_line2\n%locality %administrative_area %postal_code","uppercase_fields": ["locality","administrative_area"],"postal_code_pattern": "6798"}
         | 
| 43 43 | 
             
            {"country_code": "CY","format": "%given_name %family_name\n%organization\n%address_line1\n%address_line2\n%postal_code %locality","postal_code_pattern": "\\d{4}"}
         | 
| 44 44 | 
             
            {"country_code": "CZ","format": "%given_name %family_name\n%organization\n%address_line1\n%address_line2\n%postal_code %locality","required_fields": ["address_line1","locality","postal_code"],"postal_code_pattern": "\\d{3} ?\\d{2}"}
         | 
| 45 | 
            -
            {"country_code": "DE","format": "%organization\n%given_name %family_name\n%address_line1\n%address_line2\n% | 
| 45 | 
            +
            {"country_code": "DE","format": "%organization\n%given_name %family_name\n%address_line1\n%address_line2\n%postal_code %locality","required_fields": ["address_line1","locality","postal_code"],"postal_code_pattern": "\\d{5}"}
         | 
| 46 46 | 
             
            {"country_code": "DK","format": "%given_name %family_name\n%organization\n%address_line1\n%address_line2\n%postal_code %locality","required_fields": ["address_line1","locality","postal_code"],"postal_code_pattern": "\\d{4}"}
         | 
| 47 47 | 
             
            {"country_code": "DO","format": "%given_name %family_name\n%organization\n%address_line1\n%address_line2\n%postal_code %locality","postal_code_pattern": "\\d{5}"}
         | 
| 48 48 | 
             
            {"country_code": "DZ","format": "%given_name %family_name\n%organization\n%address_line1\n%address_line2\n%postal_code %locality","postal_code_pattern": "\\d{5}"}
         | 
    
        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": "摩尔多瓦",
         | 
| @@ -24,7 +24,7 @@ def address_format_customizations(country_code) | |
| 24 24 | 
             
              # Switch %organization and %recipient.
         | 
| 25 25 | 
             
              # https://github.com/googlei18n/libaddressinput/issues/83
         | 
| 26 26 | 
             
              format_customizations["DE"] = {
         | 
| 27 | 
            -
                "format" => "%organization\n%given_name %family_name\n%address_line1\n%address_line2\n% | 
| 27 | 
            +
                "format" => "%organization\n%given_name %family_name\n%address_line1\n%address_line2\n%postal_code %locality"
         | 
| 28 28 | 
             
              }
         | 
| 29 29 |  | 
| 30 30 | 
             
              # Revert the removal of %sortingCode.
         | 
| @@ -141,4 +141,25 @@ module Addressing | |
| 141 141 | 
             
                  fields & used_fields
         | 
| 142 142 | 
             
                end
         | 
| 143 143 | 
             
              end
         | 
| 144 | 
            +
             | 
| 145 | 
            +
              class AddressFormatHelper
         | 
| 146 | 
            +
                class << self
         | 
| 147 | 
            +
                  # Gets the required fields.
         | 
| 148 | 
            +
                  #
         | 
| 149 | 
            +
                  # Applies field overrides to the required fields
         | 
| 150 | 
            +
                  # specified by the address format.
         | 
| 151 | 
            +
                  def required_fields(address_format, field_overrides)
         | 
| 152 | 
            +
                    required_fields = address_format.required_fields
         | 
| 153 | 
            +
                    required_fields = required_fields - field_overrides.optional_fields
         | 
| 154 | 
            +
                    required_fields = required_fields - field_overrides.hidden_fields
         | 
| 155 | 
            +
             | 
| 156 | 
            +
                    if field_overrides.required_fields
         | 
| 157 | 
            +
                      required_fields = required_fields + field_overrides.required_fields
         | 
| 158 | 
            +
                      required_fields = required_fields.uniq
         | 
| 159 | 
            +
                    end
         | 
| 160 | 
            +
             | 
| 161 | 
            +
                    required_fields
         | 
| 162 | 
            +
                  end
         | 
| 163 | 
            +
                end
         | 
| 164 | 
            +
              end
         | 
| 144 165 | 
             
            end
         | 
    
        data/lib/addressing/enum.rb
    CHANGED
    
    
| @@ -0,0 +1,33 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Addressing
         | 
| 4 | 
            +
              class FieldOverride < Enum
         | 
| 5 | 
            +
                HIDDEN = "hidden"
         | 
| 6 | 
            +
                OPTIONAL = "optional"
         | 
| 7 | 
            +
                REQUIRED = "required"
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              class FieldOverrides
         | 
| 11 | 
            +
                attr_reader :hidden_fields, :optional_fields, :required_fields
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                def initialize(definition)
         | 
| 14 | 
            +
                  AddressField.assert_all_exist(definition.keys)
         | 
| 15 | 
            +
                  FieldOverride.assert_all_exist(definition.values)
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  @hidden_fields = []
         | 
| 18 | 
            +
                  @optional_fields = []
         | 
| 19 | 
            +
                  @required_fields = []
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  definition.each do |field, override|
         | 
| 22 | 
            +
                    case override
         | 
| 23 | 
            +
                    when FieldOverride::HIDDEN
         | 
| 24 | 
            +
                      @hidden_fields << field
         | 
| 25 | 
            +
                    when FieldOverride::OPTIONAL
         | 
| 26 | 
            +
                      @optional_fields << field
         | 
| 27 | 
            +
                    when FieldOverride::REQUIRED
         | 
| 28 | 
            +
                      @required_fields << field
         | 
| 29 | 
            +
                    end
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
            end
         | 
| @@ -1,3 +1,5 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            module Addressing
         | 
| 2 4 | 
             
              class LazySubdivisions
         | 
| 3 5 | 
             
                def initialize(parents)
         | 
| @@ -16,6 +18,11 @@ module Addressing | |
| 16 18 | 
             
                  @subdivisions.any?
         | 
| 17 19 | 
             
                end
         | 
| 18 20 |  | 
| 21 | 
            +
                def empty?
         | 
| 22 | 
            +
                  do_initialize unless @initialized
         | 
| 23 | 
            +
                  @subdivisions.empty?
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
             | 
| 19 26 | 
             
                private
         | 
| 20 27 |  | 
| 21 28 | 
             
                def do_initialize
         | 
| @@ -0,0 +1,111 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Addressing
         | 
| 4 | 
            +
              module Model
         | 
| 5 | 
            +
                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, **options)
         | 
| 7 | 
            +
                  fields = Array(fields)
         | 
| 8 | 
            +
                  field_overrides ||= FieldOverrides.new({})
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  options[:if] ||= -> { fields.any? { |f| changes.key?(f.to_s) } } unless options[:unless]
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  class_eval do
         | 
| 13 | 
            +
                    validate :verify_address_format, **options
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                    define_method :verify_address_format do
         | 
| 16 | 
            +
                      values = fields.each_with_object({}) { |f, v| v[f] = send(f) }
         | 
| 17 | 
            +
                      address = Address.new(**values)
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                      return unless address.country_code.present?
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                      address_format = AddressFormat.get(address.country_code)
         | 
| 22 | 
            +
                      address_format.used_fields
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                      return unless address.country_code.present?
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                      address_format = AddressFormat.get(address.country_code)
         | 
| 27 | 
            +
                      address_format.used_fields
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                      # Validate the presence of required fields.
         | 
| 30 | 
            +
                      AddressFormatHelper::required_fields(address_format, field_overrides).each do |required_field|
         | 
| 31 | 
            +
                        next unless address.send(required_field).blank?
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                        errors.add(required_field, "should not be blank")
         | 
| 34 | 
            +
                      end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                      used_fields = address_format.used_fields - field_overrides.hidden_fields
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                      # Validate the absence of unused fields.
         | 
| 39 | 
            +
                      unused_fields = AddressField.all.values - used_fields
         | 
| 40 | 
            +
                      unused_fields.each do |unused_field|
         | 
| 41 | 
            +
                        next if address.send(unused_field).blank?
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                        errors.add(unused_field, "should be blank")
         | 
| 44 | 
            +
                      end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                      # Validate subdivisions.
         | 
| 47 | 
            +
                      subdivisions = verify_subdivisions(address, address_format)
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                      # Validate postal code.
         | 
| 50 | 
            +
                      verify_postal_code(address.postal_code, subdivisions, address_format) if used_fields.include?(AddressField::POSTAL_CODE)
         | 
| 51 | 
            +
                    end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                    define_method :verify_subdivisions do |address, address_format|
         | 
| 54 | 
            +
                      # No predefined subdivisions exist, nothing to validate against.
         | 
| 55 | 
            +
                      return [] if address_format.subdivision_depth < 1
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                      subdivisions, _parents = address_format.used_subdivision_fields.each_with_index.inject([[], []]) do |(subdivisions, parents), (field, index)|
         | 
| 58 | 
            +
                        # The field is empty or validation is disabled.
         | 
| 59 | 
            +
                        # break subdivisions if address.send(field).blank? || address_format.hidden_fields.include?(field)
         | 
| 60 | 
            +
                        break subdivisions if address.send(field).blank?
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                        parents << (index > 0 ? address.send(address_format.used_subdivision_fields[index - 1]) : address_format.country_code)
         | 
| 63 | 
            +
                        subdivision = Subdivision.get(address.send(field), parents)
         | 
| 64 | 
            +
                        if subdivision.nil?
         | 
| 65 | 
            +
                          errors.add(field, "should be valid")
         | 
| 66 | 
            +
                          break [subdivisions, parents]
         | 
| 67 | 
            +
                        end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                        subdivisions << subdivision
         | 
| 70 | 
            +
                        # No predefined subdivisions below this level, stop here.
         | 
| 71 | 
            +
                        break [subdivisions, parents] if subdivision.children.empty?
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                        [subdivisions, parents]
         | 
| 74 | 
            +
                      end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                      subdivisions
         | 
| 77 | 
            +
                    end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                    define_method :verify_postal_code do |postal_code, subdivisions, address_format|
         | 
| 80 | 
            +
                      # Nothing to validate.
         | 
| 81 | 
            +
                      return if postal_code.blank?
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                      full_pattern, start_pattern = subdivisions.inject([address_format.postal_code_pattern, nil]) do |(full_pattern, start_pattern), subdivision|
         | 
| 84 | 
            +
                        pattern = subdivision.postal_code_pattern
         | 
| 85 | 
            +
                        next [full_pattern, start_pattern] if pattern.blank?
         | 
| 86 | 
            +
                        next [pattern, start_pattern] if subdivision.postal_code_pattern_type == PatternType::FULL
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                        [full_pattern, pattern]
         | 
| 89 | 
            +
                      end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                      if full_pattern
         | 
| 92 | 
            +
                        # The pattern must match the provided value completely.
         | 
| 93 | 
            +
                        match = postal_code.match(Regexp.new(full_pattern.gsub("\\\\", "\\").to_s, "i"))
         | 
| 94 | 
            +
                        if match.nil? || match[0] != postal_code
         | 
| 95 | 
            +
                          errors.add(AddressField::POSTAL_CODE, "should be valid")
         | 
| 96 | 
            +
                          return
         | 
| 97 | 
            +
                        end
         | 
| 98 | 
            +
                      end
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                      if start_pattern
         | 
| 101 | 
            +
                        # The pattern must match the start of the provided value.
         | 
| 102 | 
            +
                        match = postal_code.match(Regexp.new(start_pattern.gsub("\\\\", "\\").to_s, "i"))
         | 
| 103 | 
            +
                        if match.nil? || postal_code.index(match[0]) != 0
         | 
| 104 | 
            +
                          errors.add(AddressField::POSTAL_CODE, "should be valid")
         | 
| 105 | 
            +
                        end
         | 
| 106 | 
            +
                      end
         | 
| 107 | 
            +
                    end
         | 
| 108 | 
            +
                  end
         | 
| 109 | 
            +
                end
         | 
| 110 | 
            +
              end
         | 
| 111 | 
            +
            end
         | 
    
        data/lib/addressing/version.rb
    CHANGED
    
    
    
        data/lib/addressing.rb
    CHANGED
    
    | @@ -1,8 +1,10 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 3 | 
             
            require "cgi"
         | 
| 4 | 
            +
            require "digest"
         | 
| 4 5 | 
             
            require "json"
         | 
| 5 6 |  | 
| 7 | 
            +
            require "addressing/enum"
         | 
| 6 8 | 
             
            require "addressing/address"
         | 
| 7 9 | 
             
            require "addressing/address_field"
         | 
| 8 10 | 
             
            require "addressing/address_format"
         | 
| @@ -10,6 +12,7 @@ require "addressing/administrative_area_type" | |
| 10 12 | 
             
            require "addressing/country"
         | 
| 11 13 | 
             
            require "addressing/default_formatter"
         | 
| 12 14 | 
             
            require "addressing/dependent_locality_type"
         | 
| 15 | 
            +
            require "addressing/field_override"
         | 
| 13 16 | 
             
            require "addressing/lazy_subdivisions"
         | 
| 14 17 | 
             
            require "addressing/locale"
         | 
| 15 18 | 
             
            require "addressing/locality_type"
         | 
| @@ -26,3 +29,10 @@ module Addressing | |
| 26 29 |  | 
| 27 30 | 
             
              class UnknownLocaleError < Error; end
         | 
| 28 31 | 
             
            end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            if defined?(ActiveSupport.on_load)
         | 
| 34 | 
            +
              ActiveSupport.on_load(:active_record) do
         | 
| 35 | 
            +
                require "addressing/model"
         | 
| 36 | 
            +
                extend Addressing::Model
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
            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. | 
| 4 | 
            +
              version: 0.3.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- | 
| 11 | 
            +
            date: 2022-04-04 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies: []
         | 
| 13 13 | 
             
            description:
         | 
| 14 14 | 
             
            email: robinvdvleuten@gmail.com
         | 
| @@ -689,9 +689,11 @@ files: | |
| 689 689 | 
             
            - lib/addressing/default_formatter.rb
         | 
| 690 690 | 
             
            - lib/addressing/dependent_locality_type.rb
         | 
| 691 691 | 
             
            - lib/addressing/enum.rb
         | 
| 692 | 
            +
            - lib/addressing/field_override.rb
         | 
| 692 693 | 
             
            - lib/addressing/lazy_subdivisions.rb
         | 
| 693 694 | 
             
            - lib/addressing/locale.rb
         | 
| 694 695 | 
             
            - lib/addressing/locality_type.rb
         | 
| 696 | 
            +
            - lib/addressing/model.rb
         | 
| 695 697 | 
             
            - lib/addressing/pattern_type.rb
         | 
| 696 698 | 
             
            - lib/addressing/postal_code_type.rb
         | 
| 697 699 | 
             
            - lib/addressing/postal_label_formatter.rb
         |