address_concern 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 54db12d5f83e9438e61c47552eba316511be4cbc69200bee3e51568a10c2c41e
4
+ data.tar.gz: 73a84002eeafb49d0536d2bf5de94391410b3b4d873633ba62f2fd3e42df8ab5
5
+ SHA512:
6
+ metadata.gz: ac7f541ac00b56b64c9a6e8f6cc7a49ee423cce621c90a13173ddc7e4c852883d5f5a2ad14bca967b2d7c7fcc9678a7b8062bb580c30baa43bb656e681b7fed9
7
+ data.tar.gz: 305160aabeca32990a9aa74aa2519b6b58b54c7354985ccbb1677fc1ec370b5c0f104319541834c33865f86079f10d4f45b31342be2d2656e90ade6eb42a85fa
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ spec/test.log
6
+ .byebug_history
7
+ Gemfile.lock
8
+ tmp/
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.7.4
data/CHANGELOG ADDED
@@ -0,0 +1,3 @@
1
+ Tue, Mar 8, 2011
2
+ - - - - - - - - -
3
+ - Initial Release
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in address_concern.gemspec
4
+ gemspec
5
+
6
+ gem 'pry'
7
+ gem 'byebug'
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2011 Paul Campbell
2
+ Copyright (c) 2011-2018 Tyler Rick
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ #---------------------------------------------------------------------------------------------------
4
+ require 'rspec/core'
5
+ require 'rspec/core/rake_task'
6
+ RSpec::Core::RakeTask.new(:spec) do |spec|
7
+ spec.pattern = FileList['spec/**/*_spec.rb']
8
+ end
9
+
10
+ desc "Start a console with this version of library loaded"
11
+ task :console do
12
+ require 'bundler/setup'
13
+ require 'address_concern'
14
+ require 'irb'
15
+ ARGV.clear
16
+ IRB.start
17
+ end
18
+
19
+ task :default => :spec
data/Readme.md ADDED
@@ -0,0 +1,231 @@
1
+ # Address Concern
2
+
3
+ A reusable polymorphic `Address` model concern for your Rails apps.
4
+
5
+ # Installation
6
+
7
+ Add `address_concern` to your `Gemfile`:
8
+
9
+ gem 'address_concern'
10
+
11
+ Then run the generator to create your addresses table:
12
+
13
+ rails generate address_concern:install
14
+ rake db:migrate
15
+
16
+ You now have an `Address` model that you can use in your app just as if it were in your `app/models` directory.
17
+
18
+ # Usage
19
+
20
+ ## Base usage
21
+
22
+ ```ruby
23
+ class Address < ApplicationRecord
24
+ include AddressConcern::Address
25
+ end
26
+ ```
27
+
28
+ ## `belongs_to_address`
29
+
30
+ `AddressConcern::AddressAssociations` is automatically included into `ActiveRecord::Base` and
31
+ provides a few macros for defining associations with your app's Address model.
32
+
33
+ ```ruby
34
+ class Person < ApplicationRecord
35
+ belongs_to_address
36
+ end
37
+
38
+ person = Person.new
39
+ person.build_address(address: '...')
40
+ ```
41
+
42
+ ## Multiple addresses on same model
43
+
44
+ ```ruby
45
+ class User < ApplicationRecord
46
+ belongs_to_address :shipping_address
47
+ belongs_to_address :billing_address
48
+ end
49
+
50
+ user = User.new
51
+ shipping_address = user.build_shipping_address(address: '...')
52
+ billing_address = user.build_billing_address( address: '...')
53
+ ```
54
+
55
+ See "Adding an `address` association to your ActiveRecord models" section for more examples of
56
+ configuration your associations.
57
+
58
+
59
+ # Adding an `address` association to your ActiveRecord models
60
+
61
+ You can add an address association (or multiple) to any model that has an address.
62
+
63
+ You can associate with the address via a `belongs_to`, `has_one`, or `has_many` — whichever makes
64
+ the most sense for your use case.
65
+
66
+ You can either use standard ActiveRecord association macros, like this:
67
+
68
+ ```ruby
69
+ class Person < ApplicationRecord
70
+ belongs_to :address
71
+ end
72
+ ```
73
+
74
+ ... or use the provided macros:
75
+
76
+ ## `belongs_to_address`
77
+
78
+ ```ruby
79
+ class Person < ApplicationRecord
80
+ belongs_to_address
81
+ end
82
+
83
+ person = Person.new
84
+ person.build_address(address: '...')
85
+ ```
86
+
87
+ If needed, you can pass a name as well as options for the `belongs_to` and (optional) inverse `has_one`
88
+ associations.
89
+
90
+ ```ruby
91
+ class Child < ApplicationRecord
92
+ belongs_to_address inverse: false
93
+ belongs_to_address :secret_hideout, inverse: {name: :child_for_secret_hideout}
94
+ end
95
+
96
+ child = Child.new
97
+ child.build_secret_hideout(address: '...')
98
+ ```
99
+
100
+ ## `has_address`
101
+
102
+ `has_address` creates a `has_one :address` association:
103
+
104
+ ```ruby
105
+ class Company < ApplicationRecord
106
+ has_address
107
+ end
108
+ ```
109
+
110
+ ```
111
+ company = company.new
112
+ address = company.build_address(address: '...')
113
+ ```
114
+
115
+ This also adds a polymorphic `addressable` association on the Address model (not available if you're
116
+ using `belongs_to :address` on your addressable models):
117
+
118
+ ```ruby
119
+ belongs_to :addressable, :polymorphic => true
120
+ ```
121
+
122
+ ## `has_addresses`
123
+
124
+ `has_addresses` creates a `has_many :addresses` association:
125
+
126
+ ```ruby
127
+ class User < ApplicationRecord
128
+ has_addresses
129
+ end
130
+ ```
131
+
132
+ If you want to have several *individually accessible* addresses associated with a single model (such
133
+ as a separate shipping and billing address), you can do something like this:
134
+
135
+ ```ruby
136
+ class User < ApplicationRecord
137
+ has_addresses :types => [:physical, :shipping, :billing]
138
+ end
139
+ ```
140
+
141
+ Then you can refer to them by name, like this:
142
+
143
+ ```ruby
144
+ shipping_address = user.build_shipping_address(address: 'Some address')
145
+ user.shipping_address # => shipping_address
146
+ ```
147
+
148
+ Note that you aren't *limited* to only the address types you specifically list in your
149
+ `has_addresses` declaration; you can still add and retrieve other addresses using the `has_many
150
+ :addresses` association:
151
+
152
+ ```ruby
153
+ vacation_address = user.addresses.build(address: 'Vacation', :address_type => 'Vacation')
154
+ user.addresses # => [shipping_address, vacation_address]
155
+ ```
156
+
157
+ # Country/state database
158
+
159
+ Country/state data comes from the [`carmen`](https://github.com/carmen-ruby/carmen) gem.
160
+
161
+ - You can set the country either by using the `country=` writer (if you want to use a country name
162
+ as input in your frontend) or the `country_code=` writer (if you want to use a country code as
163
+ input). It will automatically update the other column for you and keep both of them up-to-date.
164
+ - The country name is stored in the `country` attribute (most common use case).
165
+ - Country codes can be optionally get/set via the `country_code2` (ISO 3166-1 alpha-2 codes)
166
+ (aliased as `country_code`) or `country_code3` attributes.
167
+ - Be aware that if the country you entered isn't recognized (in Carmen's database), it will be
168
+ rejected and the country field reset to nil. This should probably be considered a bug and be fixed
169
+ in a later release (using validations instead).
170
+
171
+ Other notes regarding country:
172
+
173
+ - Added some special handling of UK countries, since Carmen doesn't recognize 'England', etc. as
174
+ countries but we want to allow those country names to be stored since they may be a part of the
175
+ address you want to preserve.
176
+
177
+ # View helpers
178
+
179
+ Because this gem depends on [`carmen`](https://github.com/carmen-ruby/carmen), you have access to
180
+ its `country_select` and `state_select` helpers.
181
+
182
+ # Related Projects
183
+
184
+ (Along with some feature/API ideas that we may want to incorporate (pull requests welcome!).)
185
+
186
+ - https://github.com/ankane/mainstreet — A standard US address model for Rails
187
+ - Use `alias_attribute` to map existing field names
188
+ - Add new fields like `original_attributes` and `verification_info`
189
+ - Uses `SmartyStreets` to verify addresses (`valid?` returns false).
190
+ - [`acts_as_address` association macro](https://github.com/ankane/mainstreet/blob/master/lib/mainstreet.rb)
191
+ - [`Address` model generator](https://github.com/ankane/mainstreet/blob/master/lib/generators/mainstreet/address_generator.rb)
192
+ - `acts_as_address` could potentially be included into our `Address` model and both gems used together
193
+
194
+ - https://github.com/yrgoldteeth/whereabouts — A simple rails plugin that adds a polymorphic address model
195
+ - `has_whereabouts :location, {:geocode => true}`
196
+ - `has_whereabouts :location, {:validate => [:city, :state, :zip]}`
197
+ - [`has_whereabouts` association macro](https://github.com/yrgoldteeth/whereabouts/blob/master/lib/whereabouts_methods.rb)
198
+ - [`Address` model generator](https://github.com/yrgoldteeth/whereabouts/blob/master/lib/generators/address/templates/address.rb)
199
+
200
+ - https://github.com/wilbert/addresses — An Address engine to use Country, State, City and Neighborhood models
201
+ - Allows you use these models: `Country`, `State` (belongs to country), `City` (belongs to State), `Neighborhood` (belongs to city), `Address` (Belongs to `Neighborhood` and `City`, because neighborhood is not required)
202
+ - `address.city = Address::City.find(city_id)`
203
+ - `mount Addresses::Engine => "/addresses"`
204
+ - [`Address` model](https://github.com/wilbert/addresses/blob/master/app/models/addresses/address.rb)
205
+
206
+ - https://github.com/huerlisi/has_vcards — Rails plugin providing VCard like contact and address models and helpers
207
+ - [`Address` model](https://github.com/huerlisi/has_vcards/blob/master/app/models/has_vcards/address.rb)
208
+
209
+ Not maintained for 3+ years:
210
+ - https://github.com/mobilityhouse/acts_as_addressable — Make your models addressable
211
+ - `acts_as_addressable :postal, :billing`
212
+ - [`acts_as_addressable` association macro](https://github.com/mobilityhouse/acts_as_addressable/blob/master/lib/acts_as_addressable/addressable.rb)
213
+ - [`Address` model generator](https://github.com/mobilityhouse/acts_as_addressable/blob/master/lib/generators/acts_as_addressable/templates/address.rb)
214
+ - https://github.com/mariusz360/postally_addressable — Add postal addresses to your models
215
+ - [`has_postal_address` association macro](https://github.com/mariusz360/postally_addressable/blob/master/lib/postally_addressable/has_postal_address.rb)
216
+ - [`PostalAddress` model](https://github.com/mariusz360/postally_addressable/blob/master/app/models/postal_address.rb)
217
+ - `alias_attribute :state, :province`
218
+ - https://github.com/nybblr/somewhere — Serialized address class for use with Rails models. Like it should be.
219
+ - `address :billing, :postal_code => :zip, :include_prefix => false`
220
+ - `address.to_hash :exclude => [:country]`
221
+ - `address.to_s :country => false`
222
+ - [`Address` model](https://github.com/nybblr/somewhere/blob/master/lib/address.rb)
223
+ - [`address` association macro](https://github.com/nybblr/somewhere/blob/master/lib/somewhere.rb)
224
+ - https://github.com/rumblelabs/is_addressable
225
+
226
+ # License
227
+
228
+ Licensed under the MIT License.
229
+
230
+ See LICENSE.txt for further details.
231
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.1
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "address_concern/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "address_concern"
7
+ s.version = AddressConcern.version
8
+ s.authors = ["Paul Campbell", "Tyler Rick"]
9
+ s.email = ["paul@rslw.com", "tyler@tylerrick.com"]
10
+ s.homepage = %q{http://github.com/TylerRick/address_concern}
11
+ s.summary = %q{A reusable Address model for your Rails apps}
12
+ s.description = s.summary
13
+ s.licenses = ["MIT"]
14
+
15
+ s.add_dependency "rake"
16
+ s.add_dependency "cucumber"
17
+ s.add_dependency "rails", ">= 4.0"
18
+ s.add_dependency "activerecord", ">= 4.0"
19
+ s.add_dependency "activesupport", ">= 4.0"
20
+ s.add_dependency "carmen", '>= 1.1.1'
21
+ s.add_dependency "attribute_normalizer"
22
+ s.add_dependency "active_record_ignored_attributes"
23
+ s.add_dependency "facets"
24
+
25
+ s.add_development_dependency 'rspec'
26
+ s.add_development_dependency 'sqlite3'
27
+ #s.add_development_dependency 'mysql2', '~>0.2.11'
28
+
29
+ s.files = `git ls-files`.split("\n")
30
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
31
+ #s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
32
+ s.require_paths = ["lib"]
33
+ end
data/bin/console ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'address_concern'
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ require_relative "../spec/spec_helper"
11
+ require "pry"
12
+ Pry.start
@@ -0,0 +1,8 @@
1
+ ---
2
+ en:
3
+ world:
4
+ id:
5
+ jw:
6
+ jk:
7
+ #name: Jakarta Raya
8
+ name: DKI Jakarta
@@ -0,0 +1,306 @@
1
+ module AddressConcern::Address
2
+ extend ActiveSupport::Concern
3
+ included do
4
+
5
+ #validates_presence_of :name
6
+ #validates_presence_of :address
7
+ #validates_presence_of :state, :if => :state_required?
8
+ #validates_presence_of :country
9
+ #validates_format_of :phone, :with => /^[0-9\-\+ ]*$/
10
+ #validates_format_of :email, :with => /^[^@]*@.*\.[^\.]*$/, :message => 'is invalid. Please enter an address in the format of you@company.com'
11
+ #validates_presence_of :phone, :message => ' is required.'
12
+
13
+ #-------------------------------------------------------------------------------------------------
14
+ normalize_attributes :name, :city, :state, :postal_code, :country
15
+ normalize_attribute :address, :with => [:cleanlines, :strip]
16
+
17
+ #-------------------------------------------------------------------------------------------------
18
+ # Country code
19
+
20
+ def country_alpha2=(code)
21
+ if code.blank?
22
+ write_attribute(:country, nil)
23
+ write_attribute(:country_alpha2, nil)
24
+ write_attribute(:country_alpha3, nil)
25
+
26
+ elsif (country = Carmen::Country.alpha_2_coded(code))
27
+ # Only set it if it's a recognized country code
28
+ write_attribute(:country, country.name)
29
+ write_attribute(:country_alpha2, code)
30
+ end
31
+ end
32
+
33
+ # Aliases
34
+ def country_code
35
+ country_alpha2
36
+ end
37
+ def country_code=(code)
38
+ self.country_alpha2 = code
39
+ end
40
+ def state_code
41
+ state
42
+ end
43
+
44
+ def carmen_country
45
+ Carmen::Country.alpha_2_coded(country_alpha2)
46
+ end
47
+
48
+ def carmen_state
49
+ if (country = carmen_country)
50
+ Address.states_for_country(country).coded(state_code)
51
+ end
52
+ end
53
+
54
+ #-------------------------------------------------------------------------------------------------
55
+ # Country name
56
+
57
+ def country=(name)
58
+ if name.blank?
59
+ write_attribute(:country, nil)
60
+ write_attribute(:country_alpha2, nil)
61
+ write_attribute(:country_alpha3, nil)
62
+ else
63
+ name = recognize_country_name_alias(name)
64
+ if (country = Carmen::Country.named(name))
65
+ write_attribute(:country, country.name)
66
+ write_attribute(:country_alpha2, country.alpha_2_code)
67
+ write_attribute(:country_alpha3, country.alpha_3_code)
68
+ else
69
+ write_attribute(:country, nil)
70
+ write_attribute(:country_alpha2, nil)
71
+ write_attribute(:country_alpha3, nil)
72
+ end
73
+ end
74
+ end
75
+
76
+ def recognize_country_name_alias(name)
77
+ name = case name
78
+ when 'USA'
79
+ when 'The Democratic Republic of the Congo', 'Democratic Republic of the Congo'
80
+ 'Congo, the Democratic Republic of the'
81
+ when 'Republic of Macedonia', 'Macedonia, Republic of', 'Macedonia'
82
+ 'Macedonia, Republic of'
83
+ else
84
+ name
85
+ end
86
+ end
87
+
88
+ # This should not be different from the value stored in the country attribute, but allows you to
89
+ # look it up just to make sure they match (or to update country field to match this).
90
+ def country_name_from_code
91
+ if (country = Carmen::Country.alpha_2_coded(country_alpha2))
92
+ country.name
93
+ end
94
+ end
95
+
96
+ # Aliases
97
+ def country_name
98
+ country
99
+ end
100
+ def country_name=(name)
101
+ self.country = name
102
+ end
103
+
104
+ #════════════════════════════════════════════════════════════════════════════════════════════════════
105
+ # State/province options for country
106
+
107
+ # This is useful if want to list the state options allowed for a country in a select box and
108
+ # restrict entry to only officially listed state options.
109
+ # It is not required in the postal address for all countries, however. If you only want to show it
110
+ # if it's required in the postal address, you can make it conditional based on
111
+ # state_included_in_postal_address?.
112
+ def self.states_for_country(country)
113
+ return [] unless country
114
+ raise ArgumentError.new('expected a Carmen::Country') unless country.is_a? Carmen::Country
115
+ Carmen::RegionCollection.new(
116
+ if country.name == 'Kenya'
117
+ # https://github.com/jim/carmen/issues/227
118
+ # https://en.wikipedia.org/wiki/Provinces_of_Kenya
119
+ # Kenya's provinces were replaced by a system of counties in 2013.
120
+ # https://en.wikipedia.org/wiki/ISO_3166-2:KE confirms that they are "former" provinces.
121
+ # At the time of this writing, however, it doesn't look like Carmen has been updated to
122
+ # include the 47 counties listed under https://en.wikipedia.org/wiki/ISO_3166-2:KE.
123
+ country.subregions.typed('county')
124
+ elsif country.name == 'France'
125
+ # https://github.com/jim/carmen/issues/228
126
+ # https://en.wikipedia.org/wiki/Regions_of_France
127
+ # In 2016 what had been 27 regions was reduced to 18.
128
+ # France is divided into 18 administrative regions, including 13 metropolitan regions and 5 overseas regions.
129
+ # https://en.wikipedia.org/wiki/ISO_3166-2:FR
130
+ []
131
+ else # Needed for New Zealand, Philippines, Indonesia, and possibly others
132
+ country.subregions.map {|_| _.subregions.any? ? _.subregions : _ }.flatten
133
+ end
134
+ )
135
+ end
136
+ def states_for_country
137
+ self.class.states_for_country(carmen_country)
138
+ end
139
+ alias_method :state_options, :states_for_country
140
+
141
+ def country_with_states?
142
+ states_for_country.any?
143
+ end
144
+
145
+ # Is the state/province required in a postal address?
146
+ # If no, perhaps you want to collect it for other reasons (like seeing which people/things are in
147
+ # the same region). Or for countries where it *may* be included in a postal address but is not
148
+ # required to be included.
149
+ def state_required_in_postal_address?
150
+ [
151
+ 'Australia',
152
+ 'Brazil',
153
+ 'Canada',
154
+ 'Mexico',
155
+ 'United States',
156
+ 'Italy',
157
+ 'Venezuela',
158
+ ].include? country_name
159
+ end
160
+ def state_possibly_included_in_postal_address?
161
+ # https://ux.stackexchange.com/questions/64665/address-form-field-for-region
162
+ # http://www.bitboost.com/ref/international-address-formats/denmark/
163
+ # http://www.bitboost.com/ref/international-address-formats/poland/
164
+ return true if state_required_in_postal_address?
165
+ return false if [
166
+ 'Algeria',
167
+ 'Argentina',
168
+ 'Austria',
169
+ 'Denmark',
170
+ 'France',
171
+ 'Germany',
172
+ 'Indonesia',
173
+ 'Ireland',
174
+ 'Israel',
175
+ 'Netherlands',
176
+ 'New Zealand',
177
+ 'Poland',
178
+ 'Sweden',
179
+ 'United Kingdom',
180
+ ].include? country_name
181
+ # Default:
182
+ country_with_states?
183
+ end
184
+
185
+ # It's not called a "State" in all countries.
186
+ # In some countries, it could technically be multiple different types of regions:
187
+ # - In United States, it could be a state or an outlying region or a district or an APO
188
+ # - In Canada, it could be a province or a territory.
189
+ # This attempts to return the most common, expected name for this field.
190
+ # See also: https://ux.stackexchange.com/questions/64665/address-form-field-for-region
191
+ #
192
+ # To see what it should be called in all countries known to Carmen:
193
+ # Country.countries_with_states.map {|country| [country.name, Address.new(country_name: country.name).state_label] }.to_h
194
+ # => {"Afghanistan"=>"Province",
195
+ # "Armenia"=>"Province",
196
+ # "Angola"=>"Province",
197
+ # "Argentina"=>"Province",
198
+ # "Austria"=>"State",
199
+ # "Australia"=>"State",
200
+ # ...
201
+ def state_label
202
+ # In UK, it looks like they (optionally) include the *county* in their addresses. They don't actually have "states" per se.
203
+ # Reference: http://bitboost.com/ref/international-address-formats/united-kingdom/
204
+ # Could also limit to Countries (England, Scotland, Wales) and Provinces (Northern Ireland).
205
+ # Who knows. The UK's subregions are a mess.
206
+ # If allowing the full list of subregions from https://en.wikipedia.org/wiki/ISO_3166-2:GB,
207
+ # perhaps Region is a better, more inclusive term.
208
+ if country_name.in? ['United Kingdom']
209
+ 'Region'
210
+ elsif state_options.any?
211
+ state_options[0].type.capitalize
212
+ end
213
+ end
214
+
215
+ def state_name
216
+ carmen_state ? carmen_state.name : state
217
+ end
218
+
219
+ #════════════════════════════════════════════════════════════════════════════════════════════════════
220
+
221
+ def empty?
222
+ [:address, :city, :state, :postal_code, :country].all? {|_|
223
+ !self[_].present?
224
+ }
225
+ end
226
+
227
+ def started_filling_out?
228
+ [:address, :city, :state, :postal_code, :country].any? {|_|
229
+ self[_].present?
230
+ }
231
+ end
232
+
233
+ #════════════════════════════════════════════════════════════════════════════════════════════════════
234
+ # Formatting for humans
235
+
236
+ # Lines of a postal address
237
+ def lines
238
+ [
239
+ name,
240
+ address.to_s.lines.to_a,
241
+ city_line,
242
+ country_name,
243
+ ].flatten.reject(&:blank?)
244
+ end
245
+
246
+ # Used by #lines
247
+ #
248
+ # Instead of using `state` method (which is really state_code). That's fine for some countries
249
+ # like US, Canada, Australia but not other countries (presumably).
250
+ #
251
+ # TODO: Put postal code and city in a different order, as that countries conventions dictate.
252
+ # See http://bitboost.com/ref/international-address-formats/new-zealand/
253
+ #
254
+ def city_line
255
+ [
256
+ #[city, state].reject(&:blank?).join(', '),
257
+ [city, state_for_postal_address].reject(&:blank?).join(', '),
258
+ postal_code,
259
+ ].reject(&:blank?).join(' ')
260
+ end
261
+
262
+ def city_state_code
263
+ [city, state].reject(&:blank?).join(', ')
264
+ end
265
+
266
+ def city_state_name
267
+ [city, state_name].reject(&:blank?).join(', ')
268
+ end
269
+
270
+ def city_state_country
271
+ [city_state_name, country_name].join(', ')
272
+ end
273
+
274
+ def state_for_postal_address
275
+ # Possibly others use a code? But seems safer to default to a name until confirmed that they use
276
+ # a code.
277
+ if country_name.in? ['United States', 'Canada', 'Australia']
278
+ state_code
279
+ elsif state_possibly_included_in_postal_address?
280
+ state_name
281
+ else
282
+ ''
283
+ end
284
+ end
285
+
286
+ #════════════════════════════════════════════════════════════════════════════════════════════════════
287
+ # Misc. output
288
+
289
+ def parts
290
+ [
291
+ name,
292
+ address.to_s.lines.to_a,
293
+ city,
294
+ state_name,
295
+ postal_code,
296
+ country_name,
297
+ ].flatten.reject(&:blank?)
298
+ end
299
+
300
+ def inspect
301
+ inspect_with([:id, :name, :address, :city, :state, :postal_code, :country], ['{', '}'])
302
+ end
303
+
304
+ #-------------------------------------------------------------------------------------------------
305
+ end
306
+ end