countries 1.2.5 → 2.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/CHANGELOG.md +6 -2
  4. data/Gemfile +1 -0
  5. data/README.markdown +33 -7
  6. data/Rakefile +15 -20
  7. data/countries.gemspec +1 -1
  8. data/lib/countries/cache/countries +0 -0
  9. data/lib/countries/cache/locales/af +0 -0
  10. data/lib/countries/cache/locales/am +0 -0
  11. data/lib/countries/cache/locales/ar +0 -0
  12. data/lib/countries/cache/locales/as +0 -0
  13. data/lib/countries/cache/locales/az +0 -0
  14. data/lib/countries/cache/locales/be +0 -0
  15. data/lib/countries/cache/locales/bg +0 -0
  16. data/lib/countries/cache/locales/bn +0 -0
  17. data/lib/countries/cache/locales/br +0 -0
  18. data/lib/countries/cache/locales/bs +0 -0
  19. data/lib/countries/cache/locales/ca +0 -0
  20. data/lib/countries/cache/locales/cs +0 -0
  21. data/lib/countries/cache/locales/cy +0 -0
  22. data/lib/countries/cache/locales/da +0 -0
  23. data/lib/countries/cache/locales/de +0 -0
  24. data/lib/countries/cache/locales/dz +0 -0
  25. data/lib/countries/cache/locales/el +0 -0
  26. data/lib/countries/cache/locales/en +0 -0
  27. data/lib/countries/cache/locales/eo +0 -0
  28. data/lib/countries/cache/locales/es +0 -0
  29. data/lib/countries/cache/locales/et +0 -0
  30. data/lib/countries/cache/locales/eu +0 -0
  31. data/lib/countries/cache/locales/fa +0 -0
  32. data/lib/countries/cache/locales/fi +0 -0
  33. data/lib/countries/cache/locales/fo +0 -0
  34. data/lib/countries/cache/locales/fr +0 -0
  35. data/lib/countries/cache/locales/ga +0 -0
  36. data/lib/countries/cache/locales/gl +0 -0
  37. data/lib/countries/cache/locales/gu +0 -0
  38. data/lib/countries/cache/locales/he +0 -0
  39. data/lib/countries/cache/locales/hi +0 -0
  40. data/lib/countries/cache/locales/hr +0 -0
  41. data/lib/countries/cache/locales/hu +0 -0
  42. data/lib/countries/cache/locales/hy +0 -0
  43. data/lib/countries/cache/locales/ia +0 -0
  44. data/lib/countries/cache/locales/id +0 -0
  45. data/lib/countries/cache/locales/is +0 -0
  46. data/lib/countries/cache/locales/it +0 -0
  47. data/lib/countries/cache/locales/ja +0 -0
  48. data/lib/countries/cache/locales/ka +0 -0
  49. data/lib/countries/cache/locales/kk +0 -0
  50. data/lib/countries/cache/locales/km +0 -0
  51. data/lib/countries/cache/locales/kn +0 -0
  52. data/lib/countries/cache/locales/ko +0 -0
  53. data/lib/countries/cache/locales/ku +0 -0
  54. data/lib/countries/cache/locales/lt +0 -0
  55. data/lib/countries/cache/locales/lv +0 -0
  56. data/lib/countries/cache/locales/mi +0 -0
  57. data/lib/countries/cache/locales/mk +0 -0
  58. data/lib/countries/cache/locales/ml +0 -0
  59. data/lib/countries/cache/locales/mn +0 -0
  60. data/lib/countries/cache/locales/mr +0 -0
  61. data/lib/countries/cache/locales/ms +0 -0
  62. data/lib/countries/cache/locales/mt +0 -0
  63. data/lib/countries/cache/locales/nb +0 -0
  64. data/lib/countries/cache/locales/ne +0 -0
  65. data/lib/countries/cache/locales/nl +0 -0
  66. data/lib/countries/cache/locales/nn +0 -0
  67. data/lib/countries/cache/locales/oc +0 -0
  68. data/lib/countries/cache/locales/or +0 -0
  69. data/lib/countries/cache/locales/pa +0 -0
  70. data/lib/countries/cache/locales/pl +0 -0
  71. data/lib/countries/cache/locales/ps +0 -0
  72. data/lib/countries/cache/locales/pt +0 -0
  73. data/lib/countries/cache/locales/ro +0 -0
  74. data/lib/countries/cache/locales/ru +0 -0
  75. data/lib/countries/cache/locales/rw +0 -0
  76. data/lib/countries/cache/locales/si +0 -0
  77. data/lib/countries/cache/locales/sk +0 -0
  78. data/lib/countries/cache/locales/sl +0 -0
  79. data/lib/countries/cache/locales/so +0 -0
  80. data/lib/countries/cache/locales/sq +0 -0
  81. data/lib/countries/cache/locales/sr +0 -0
  82. data/lib/countries/cache/locales/sv +0 -0
  83. data/lib/countries/cache/locales/sw +0 -0
  84. data/lib/countries/cache/locales/ta +0 -0
  85. data/lib/countries/cache/locales/te +0 -0
  86. data/lib/countries/cache/locales/th +0 -0
  87. data/lib/countries/cache/locales/ti +0 -0
  88. data/lib/countries/cache/locales/tk +0 -0
  89. data/lib/countries/cache/locales/tl +0 -0
  90. data/lib/countries/cache/locales/tr +0 -0
  91. data/lib/countries/cache/locales/tt +0 -0
  92. data/lib/countries/cache/locales/ug +0 -0
  93. data/lib/countries/cache/locales/uk +0 -0
  94. data/lib/countries/cache/locales/ve +0 -0
  95. data/lib/countries/cache/locales/vi +0 -0
  96. data/lib/countries/cache/locales/wa +0 -0
  97. data/lib/countries/cache/locales/wo +0 -0
  98. data/lib/countries/cache/locales/xh +0 -0
  99. data/lib/countries/cache/locales/zh +0 -0
  100. data/lib/countries/cache/locales/zu +0 -0
  101. data/lib/countries/configuration.rb +37 -0
  102. data/lib/countries/country.rb +115 -159
  103. data/lib/countries/country/attr_readers.rb +49 -0
  104. data/lib/countries/data.rb +76 -13
  105. data/lib/countries/iso3166.rb +4 -2
  106. data/lib/countries/setup.rb +7 -7
  107. data/lib/countries/timezones.rb +11 -0
  108. data/lib/countries/version.rb +1 -1
  109. data/spec/configuration_spec.rb +43 -0
  110. data/spec/country_spec.rb +22 -36
  111. data/spec/data_spec.rb +73 -0
  112. data/spec/global_spec.rb +29 -0
  113. data/spec/mongoid_spec.rb +1 -1
  114. data/spec/spec_helper.rb +24 -0
  115. data/spec/timezone_spec.rb +32 -0
  116. metadata +110 -9
  117. data/spec/setup_spec.rb +0 -14
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2ee687bca4e24ba2898509688d95338b53b593bd
4
- data.tar.gz: cda7ae980090e58b83d2bcb7a47635019c9412d4
3
+ metadata.gz: e56e233e585a77d0e16537d69e5055d9db7f1201
4
+ data.tar.gz: 8e0d126fdd580391306a14f444b1cb1f767b088b
5
5
  SHA512:
6
- metadata.gz: b4a58a0e7b18602487f105c53e73d8fb94e0b400465ff7a021e3ce8429adfd7285da97ff0b3ed645d43be8f974034b795dc298de827e841cef665d365f6bea74
7
- data.tar.gz: 5c2f7e88a4969b272cedb5dad3bdd82c8716f8db98438f74b9fe0056e5b550df9b76881923fc963680bae828c1dd4435799b20522145dd2a1545ba78aa3d5645
6
+ metadata.gz: 1110e82fab2598d0242edcad19c73e398bda739bfd8cd8201dd9c2d6944a2edf2b789526cf42dcf8292ff8c661ce5247b39d94d69991693480a931ffcdc04aa9
7
+ data.tar.gz: 2dc3bf71824639180e6daba333f31ba15d7fc6ad74c0da9fdd0df9d884ba89259d2417a5c728baf823e39087eb6873bf32087963b2380e717b972506a9577dd7
data/.gitignore CHANGED
@@ -21,5 +21,5 @@ tmp
21
21
  .ruby-gemset
22
22
  .idea/
23
23
  Gemfile.lock
24
- rspec
24
+ bin/rspec
25
25
  examples.txt
@@ -2,8 +2,12 @@
2
2
  All notable changes to this project will be documented in this file.
3
3
  This project adheres to [Semantic Versioning](http://semver.org/).
4
4
 
5
- ## 1.2.5 @ 2016-01-22
6
- - Rebuilding cache
5
+ ## 2.0.0 (unreleased)
6
+ - Selective loading translations of countries
7
+ - Auto detect I18n locales to load
8
+ - Add Configuration methods to force locales to load
9
+ - Dropped currencies gem in favor of money
10
+ - Add Time Zone Support
7
11
 
8
12
  ## 1.2.4 @ 2016-01-21
9
13
  - Romanian Standard VAT rate is 20% as of 2016-01-01 #325 @dougal
data/Gemfile CHANGED
@@ -2,6 +2,7 @@ source 'https://rubygems.org'
2
2
  gem 'rake'
3
3
  gem 'geocoder'
4
4
  gem 'retryable'
5
+ gem 'tzinfo'
5
6
 
6
7
  # Specify your gem's dependencies in countries.gemspec
7
8
  gemspec
@@ -35,9 +35,6 @@ has become
35
35
  Basic Usage
36
36
  -----------
37
37
 
38
- Note that Country class still exist by default.
39
- (is inherited from ISO3166::Country to keep backward compatibility).
40
-
41
38
  Simply load a new country object using Country.new(*alpha2*) or the shortcut Country[*alpha2*]. An example works best.
42
39
 
43
40
  c = ISO3166::Country.new('US')
@@ -45,6 +42,24 @@ Simply load a new country object using Country.new(*alpha2*) or the shortcut Cou
45
42
  # with global Country Helper
46
43
  c = Country['US']
47
44
 
45
+ Configuration
46
+
47
+ As of 2.0 you can selectively load locales to reduce memory usage in production.
48
+
49
+ By default we load I18n.available_locales if I18n is present, otherwise only [:en]. This means almost any rails environment will only bring in it's supported translations.
50
+
51
+ You can add all the locales like this.
52
+
53
+ ISO3166.configure do |config|
54
+ config.locales = [:af, :am, :ar, :as, :az, :be, :bg, :bn, :br, :bs, :ca, :cs, :cy, :da, :de, :dz, :el, :en, :eo, :es, :et, :eu, :fa, :fi, :fo, :fr, :ga, :gl, :gu, :he, :hi, :hr, :hu, :hy, :ia, :id, :is, :it, :ja, :ka, :kk, :km, :kn, :ko, :ku, :lt, :lv, :mi, :mk, :ml, :mn, :mr, :ms, :mt, :nb, :ne, :nl, :nn, :oc, :or, :pa, :pl, :ps, :pt, :ro, :ru, :rw, :si, :sk, :sl, :so, :sq, :sr, :sv, :sw, :ta, :te, :th, :ti, :tk, :tl, :tr, :tt, :ug, :uk, :ve, :vi, :wa, :wo, :xh, :zh, :zu]
55
+ end
56
+
57
+ or something a bit more simple
58
+
59
+ ISO3166.configure do |config|
60
+ config.locales = [:en, :de, :fr, :es]
61
+ end
62
+
48
63
  Attribute-Based Finder Methods
49
64
  ------------
50
65
 
@@ -101,6 +116,17 @@ Country Info
101
116
  c.region #=> "Americas"
102
117
  c.subregion #=> "Northern America"
103
118
 
119
+ Timezones **(optional)**
120
+
121
+ Add tzinfo to your gemfile, ensure it's required, Countries will not do this for you.
122
+
123
+ gem 'tzinfo', '~> 1.2', '>= 1.2.2'
124
+
125
+ c.timezones.zone_identifiers #=> ["America/New_York", "America/Detroit", "America/Kentucky/Louisville", ...]
126
+ ```c.timezones.zone_info``` # see [tzinfo docs]( http://www.rubydoc.info/gems/tzinfo/TZInfo/CountryInfo)
127
+
128
+ ```c.timezones``` # see [tzinfo docs]( http://www.rubydoc.info/gems/tzinfo/TZInfo/Country)
129
+
104
130
  Telephone Routing (E164)
105
131
 
106
132
  c.country_code #=> "1"
@@ -123,11 +149,11 @@ Country Info
123
149
  Currencies
124
150
  ----------
125
151
 
126
- Countries now uses the [Currencies][] gem. What this means is you now get back a Currency object that gives you access to all the currency information. It acts the same as a hash so the same ['name'] methods still work.
152
+ Countries now uses the [Money](https://github.com/RubyMoney/money) gem. What this means is you now get back a Money::Currency object that gives you access to all the currency information.
127
153
 
128
- c.currency['code'] #=> 'USD'
129
- c.currency['name'] #=> 'Dollars'
130
- c.currency['symbol'] #=> '$'
154
+ c.currency.iso_code #=> 'USD'
155
+ c.currency.name #=> 'Dollars'
156
+ c.currency.symbol #=> '$'
131
157
 
132
158
  Address Formatting
133
159
  ------------------
data/Rakefile CHANGED
@@ -52,14 +52,11 @@ task :update_cache do
52
52
  end
53
53
  end
54
54
 
55
- codes.each do |alpha2|
56
- data[alpha2] ||= YAML.load_file(File.join(File.dirname(__FILE__), 'lib', 'countries', 'data', 'countries', "#{alpha2}.yaml"))[alpha2]
57
- data[alpha2]['translations'] ||= empty_translations_hash.dup
58
- data[alpha2]['translations'][locale] = local_names[alpha2]
59
- data[alpha2]['translated_names'] ||= []
60
- data[alpha2]['translated_names'] << local_names[alpha2]
61
- data[alpha2]['translated_names'] = data[alpha2]['translated_names'].uniq
62
- end
55
+ File.open(File.join(File.dirname(__FILE__), 'lib', 'countries', 'cache', 'locales', locale), 'wb') { |f| f.write(Marshal.dump(local_names)) }
56
+ end
57
+
58
+ codes.each do |alpha2|
59
+ data[alpha2] ||= YAML.load_file(File.join(File.dirname(__FILE__), 'lib', 'countries', 'data', 'countries', "#{alpha2}.yaml"))[alpha2]
63
60
  end
64
61
 
65
62
  File.open(File.join(File.dirname(__FILE__), 'lib', 'countries', 'cache', 'countries'), 'wb') { |f| f.write(Marshal.dump(data)) }
@@ -97,19 +94,17 @@ task :fetch_subdivisions do
97
94
  location = "#{data['name']} State, United States"
98
95
  end
99
96
 
100
- if (result = geocode(location))
101
- geometry = result.geometry
102
- if geometry['location']
103
- state_data[code]['latitude'] = geometry['location']['lat']
104
- state_data[code]['longitude'] = geometry['location']['lng']
105
- end
106
- if geometry['bounds']
107
- state_data[code]['min_latitude'] = geometry['bounds']['southwest']['lat']
108
- state_data[code]['min_longitude'] = geometry['bounds']['southwest']['lng']
109
- state_data[code]['max_latitude'] = geometry['bounds']['northeast']['lat']
110
- state_data[code]['max_longitude'] = geometry['bounds']['northeast']['lng']
111
- end
97
+ next unless (result = geocode(location))
98
+ geometry = result.geometry
99
+ if geometry['location']
100
+ state_data[code]['latitude'] = geometry['location']['lat']
101
+ state_data[code]['longitude'] = geometry['location']['lng']
112
102
  end
103
+ next unless geometry['bounds']
104
+ state_data[code]['min_latitude'] = geometry['bounds']['southwest']['lat']
105
+ state_data[code]['min_longitude'] = geometry['bounds']['southwest']['lng']
106
+ state_data[code]['max_latitude'] = geometry['bounds']['northeast']['lat']
107
+ state_data[code]['max_longitude'] = geometry['bounds']['northeast']['lng']
113
108
  end
114
109
  # Write updated YAML for current country
115
110
  File.open(File.join(File.dirname(__FILE__), 'lib', 'data', 'subdivisions', "#{c.alpha2}.yaml"), 'w+') { |f| f.write state_data.to_yaml }
@@ -16,7 +16,7 @@ Gem::Specification.new do |gem|
16
16
  gem.version = Countries::VERSION
17
17
 
18
18
  gem.add_dependency('i18n_data', '~> 0.7.0')
19
- gem.add_dependency('currencies', '~> 0.4.2')
19
+ gem.add_dependency('money', '~> 6.0')
20
20
  gem.add_development_dependency('rspec', '>= 3')
21
21
  gem.add_development_dependency('actionview', '>= 3')
22
22
  gem.add_development_dependency 'yard'
@@ -0,0 +1,37 @@
1
+ module ISO3166
2
+ class << self
3
+ attr_writer :configuration
4
+ end
5
+
6
+ def self.configuration
7
+ @configuration ||= Configuration.new
8
+ end
9
+
10
+ def self.reset
11
+ @configuration = Configuration.new
12
+ Data.reset
13
+ end
14
+
15
+ def self.configure
16
+ yield(configuration)
17
+ end
18
+
19
+ class Configuration
20
+ attr_accessor :locales, :loaded_locales
21
+
22
+ def initialize
23
+ @locales = default_locales
24
+ @loaded_locales = []
25
+ end
26
+
27
+ private
28
+
29
+ def default_locales
30
+ if Object.const_defined?('I18n') && I18n.respond_to?(:available_locales)
31
+ I18n.available_locales
32
+ else
33
+ [:en]
34
+ end
35
+ end
36
+ end
37
+ end
@@ -1,201 +1,157 @@
1
- module ISO3166; end
2
-
3
- class ISO3166::Country
4
- Setup = ISO3166::Setup.new
5
-
6
- AttrReaders = [
7
- :number,
8
- :alpha2,
9
- :alpha3,
10
- :name,
11
- :names,
12
- :latitude,
13
- :longitude,
14
- :continent,
15
- :region,
16
- :subregion,
17
- :world_region,
18
- :country_code,
19
- :national_destination_code_lengths,
20
- :national_number_lengths,
21
- :international_prefix,
22
- :national_prefix,
23
- :address_format,
24
- :translations,
25
- :translated_names,
26
- :ioc,
27
- :gec,
28
- :un_locode,
29
- :languages,
30
- :nationality,
31
- :dissolved_on,
32
- :eu_member,
33
- :alt_currency,
34
- :vat_rates,
35
- :postal_code,
36
- :min_longitude,
37
- :min_latitude,
38
- :max_longitude,
39
- :max_latitude,
40
- :latitude_dec,
41
- :longitude_dec
42
- ]
43
-
44
- AttrReaders.each do |meth|
45
- define_method meth do
46
- @data[meth.to_s]
47
- end
48
- end
49
-
50
- attr_reader :data
51
-
52
- def initialize(country_data)
53
- @data = country_data.is_a?(Hash) ? country_data : ISO3166::Data.new(country_data).call
54
- end
55
-
56
- def valid?
57
- !(@data.nil? || @data.empty?)
58
- end
1
+ module ISO3166
2
+ class Country
3
+ attr_reader :data
59
4
 
60
- alias_method :zip, :postal_code
61
- alias_method :zip?, :postal_code
62
- alias_method :postal_code?, :postal_code
63
-
64
- def ==(other)
65
- other == data
66
- end
67
-
68
- def <=>(other)
69
- to_s <=> other.to_s
70
- end
71
-
72
- def currency
73
- ISO4217::Currency.from_code(@data['currency'])
74
- end
5
+ include ISO3166::Countries::AttrReaders
75
6
 
76
- def currency_code
77
- @data['currency']
78
- end
7
+ def initialize(country_data)
8
+ @data = country_data.is_a?(Hash) ? country_data : ISO3166::Data.new(country_data).call
9
+ end
79
10
 
80
- def subdivisions
81
- @subdivisions ||= subdivisions? ? YAML.load_file(File.join(File.dirname(__FILE__), 'data', 'subdivisions', "#{alpha2}.yaml")) : {}
82
- end
11
+ def valid?
12
+ !(@data.nil? || @data.empty?)
13
+ end
83
14
 
84
- alias_method :states, :subdivisions
15
+ alias_method :zip, :postal_code
16
+ alias_method :zip?, :postal_code
17
+ alias_method :postal_code?, :postal_code
85
18
 
86
- def subdivisions?
87
- File.exist?(File.join(File.dirname(__FILE__), 'data', 'subdivisions', "#{alpha2}.yaml"))
88
- end
19
+ def ==(other)
20
+ other == data
21
+ end
89
22
 
90
- def in_eu?
91
- @data['eu_member'].nil? ? false : @data['eu_member']
92
- end
23
+ def <=>(other)
24
+ to_s <=> other.to_s
25
+ end
93
26
 
94
- def to_s
95
- @data['name']
96
- end
27
+ def currency
28
+ Money::Currency.find(@data['currency'])
29
+ end
97
30
 
98
- def translation(locale = 'en')
99
- @data['translations'][locale.downcase.to_s]
100
- end
31
+ def currency_code
32
+ @data['currency']
33
+ end
101
34
 
102
- def local_names
103
- @local_names ||= languages.map { |language| translations[language] }
104
- end
35
+ def subdivisions
36
+ @subdivisions ||= subdivisions? ? YAML.load_file(File.join(File.dirname(__FILE__), 'data', 'subdivisions', "#{alpha2}.yaml")) : {}
37
+ end
105
38
 
106
- def local_name
107
- @local_name ||= local_names.first
108
- end
39
+ alias_method :states, :subdivisions
109
40
 
110
- class << self
111
- def new(country_data)
112
- super if country_data.is_a?(Hash) || codes.include?(country_data.to_s.upcase)
41
+ def subdivisions?
42
+ File.exist?(File.join(File.dirname(__FILE__), 'data', 'subdivisions', "#{alpha2}.yaml"))
113
43
  end
114
44
 
115
- def codes
116
- Setup.codes
45
+ def in_eu?
46
+ @data['eu_member'].nil? ? false : @data['eu_member']
117
47
  end
118
48
 
119
- def all(&blk)
120
- blk ||= proc { |_alpha2, d| ISO3166::Country.new(d) }
121
- Setup.data.map(&blk)
49
+ def to_s
50
+ @data['name']
122
51
  end
123
52
 
124
- alias_method :countries, :all
125
-
126
- def all_translated(locale = 'en')
127
- translations(locale).values
53
+ def translation(locale = 'en')
54
+ @data['translations'][locale.to_s.downcase]
128
55
  end
129
56
 
130
- def all_names_with_codes(locale = 'en')
131
- ISO3166::Country.all.map do |c|
132
- [(c.translation(locale) || c.name).html_safe, c.alpha2]
133
- end.sort_by { |d| d[0] }
57
+ def local_names
58
+ @local_names ||= languages.map { |language| translations[language] }
134
59
  end
135
60
 
136
- def translations(locale = 'en')
137
- I18nData.countries(locale.upcase)
61
+ def local_name
62
+ @local_name ||= local_names.first
138
63
  end
139
64
 
140
- def search(query)
141
- country = new(query.to_s.upcase)
142
- (country && country.valid?) ? country : nil
143
- end
65
+ class << self
66
+ def new(country_data)
67
+ super if country_data.is_a?(Hash) || codes.include?(country_data.to_s.upcase)
68
+ end
144
69
 
145
- def [](query)
146
- search(query)
147
- end
70
+ def codes
71
+ ISO3166::Data.codes
72
+ end
148
73
 
149
- def method_missing(*m)
150
- regex = m.first.to_s.match(/^find_(all_)?(country_|countries_)?by_(.+)/)
151
- super unless regex
74
+ def all(&blk)
75
+ blk ||= proc { |_alpha2, d| ISO3166::Country.new(d) }
76
+ ISO3166::Data.cache.map(&blk)
77
+ end
152
78
 
153
- countries = find_by(Regexp.last_match[3], m[1], Regexp.last_match[2])
154
- Regexp.last_match[1] ? countries : countries.last
155
- end
79
+ alias_method :countries, :all
80
+
81
+ def all_translated(locale = 'en')
82
+ translations(locale).values
83
+ end
156
84
 
157
- def find_all_by(attribute, val)
158
- attributes, value = parse_attributes(attribute, val)
85
+ def all_names_with_codes(locale = 'en')
86
+ ISO3166::Country.all.map do |c|
87
+ [(c.translation(locale) || c.name).html_safe, c.alpha2]
88
+ end.sort_by { |d| d[0] }
89
+ end
159
90
 
160
- Setup.data.select do |_, v|
161
- attributes.map do |attr|
162
- Array(v[attr]).any? { |n| value === n.to_s.downcase }
163
- end.include?(true)
91
+ def translations(locale = 'en')
92
+ I18nData.countries(locale.upcase)
164
93
  end
165
- end
166
94
 
167
- protected
95
+ def search(query)
96
+ country = new(query.to_s.upcase)
97
+ (country && country.valid?) ? country : nil
98
+ end
99
+
100
+ def [](query)
101
+ search(query)
102
+ end
168
103
 
169
- def parse_attributes(attribute, val)
170
- fail "Invalid attribute name '#{attribute}'" unless instance_methods.include?(attribute.to_sym)
104
+ def method_missing(*m)
105
+ regex = m.first.to_s.match(/^find_(all_)?(country_|countries_)?by_(.+)/)
106
+ super unless regex
171
107
 
172
- attributes = Array(attribute.to_s)
173
- if attributes == ['name']
174
- attributes << 'names'
175
- # TODO: Revisit when better data from i18n_data
176
- # attributes << 'translated_names'
108
+ countries = find_by(Regexp.last_match[3], m[1], Regexp.last_match[2])
109
+ Regexp.last_match[1] ? countries : countries.last
177
110
  end
178
111
 
179
- val = (val.is_a?(Regexp) ? Regexp.new(val.source, 'i') : val.to_s.downcase)
112
+ def find_all_by(attribute, val)
113
+ attributes, value = parse_attributes(attribute, val)
180
114
 
181
- [attributes, val]
182
- end
115
+ ISO3166::Data.cache.select do |_, v|
116
+ attributes.map do |attr|
117
+ Array(v[attr]).any? { |n| value === n.to_s.downcase }
118
+ end.include?(true)
119
+ end
120
+ end
121
+
122
+ protected
123
+
124
+ def parse_attributes(attribute, val)
125
+ fail "Invalid attribute name '#{attribute}'" unless instance_methods.include?(attribute.to_sym)
183
126
 
184
- def find_by(attribute, value, obj = nil)
185
- find_all_by(attribute.downcase, value).map do |country|
186
- obj.nil? ? country : new(country.last)
127
+ attributes = Array(attribute.to_s)
128
+ if attributes == ['name']
129
+ attributes << 'names'
130
+ # TODO: Revisit when better data from i18n_data
131
+ # attributes << 'translated_names'
132
+ end
133
+
134
+ val = (val.is_a?(Regexp) ? Regexp.new(val.source, 'i') : val.to_s.downcase)
135
+
136
+ [attributes, val]
137
+ end
138
+
139
+ def find_by(attribute, value, obj = nil)
140
+ find_all_by(attribute.downcase, value).map do |country|
141
+ obj.nil? ? country : new(country.last)
142
+ end
187
143
  end
188
144
  end
189
145
  end
190
- end
191
146
 
192
- def ISO3166::Country(country_data_or_country)
193
- case country_data_or_country
194
- when ISO3166::Country
195
- country_data_or_country
196
- when String, Symbol
197
- ISO3166::Country.search(country_data_or_country)
198
- else
199
- fail TypeError, "can't convert #{country_data_or_country.class.name} into ISO3166::Country"
147
+ def ISO3166::Country(country_data_or_country)
148
+ case country_data_or_country
149
+ when ISO3166::Country
150
+ country_data_or_country
151
+ when String, Symbol
152
+ ISO3166::Country.search(country_data_or_country)
153
+ else
154
+ fail TypeError, "can't convert #{country_data_or_country.class.name} into ISO3166::Country"
155
+ end
200
156
  end
201
157
  end