countries 4.2.3 → 5.0.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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/codeql-analysis.yml +70 -0
  3. data/.github/workflows/tests.yml +1 -5
  4. data/.rubocop.yml +40 -1
  5. data/.rubocop_todo.yml +8 -41
  6. data/CHANGELOG.md +7 -2
  7. data/Gemfile +5 -3
  8. data/README.markdown +22 -5
  9. data/Rakefile +13 -31
  10. data/bin/console +1 -0
  11. data/countries.gemspec +7 -5
  12. data/lib/countries/cache/countries.json +1 -1
  13. data/lib/countries/configuration.rb +2 -0
  14. data/lib/countries/country/class_methods.rb +12 -97
  15. data/lib/countries/country/currency_methods.rb +2 -0
  16. data/lib/countries/country/emoji.rb +2 -3
  17. data/lib/countries/country/finder_methods.rb +81 -0
  18. data/lib/countries/country.rb +3 -40
  19. data/lib/countries/data/countries/KN.yaml +0 -1
  20. data/lib/countries/data.rb +34 -37
  21. data/lib/countries/global.rb +2 -0
  22. data/lib/countries/iso3166.rb +3 -0
  23. data/lib/countries/kwarg_struct.rb +2 -0
  24. data/lib/countries/mongoid.rb +2 -0
  25. data/lib/countries/sources/cldr/downloader.rb +8 -8
  26. data/lib/countries/sources/cldr/subdivision.rb +3 -0
  27. data/lib/countries/sources/cldr/subdivision_updater.rb +23 -17
  28. data/lib/countries/sources/local/cached_loader.rb +3 -0
  29. data/lib/countries/sources/local/subdivision.rb +5 -2
  30. data/lib/countries/sources.rb +2 -0
  31. data/lib/countries/structure.rb +1 -1
  32. data/lib/countries/subdivision.rb +2 -0
  33. data/lib/countries/tasks/geocoding.rake +15 -6
  34. data/lib/countries/tasks/postal_codes.rake +5 -3
  35. data/lib/countries/timezones.rb +5 -2
  36. data/lib/countries/translations.rb +2 -0
  37. data/lib/countries/version.rb +3 -1
  38. data/lib/countries.rb +2 -0
  39. data/spec/00_global_spec.rb +2 -0
  40. data/spec/configuration_spec.rb +11 -5
  41. data/spec/country_spec.rb +71 -22
  42. data/spec/data_spec.rb +24 -18
  43. data/spec/mongoid_spec.rb +2 -2
  44. data/spec/perf_spec.rb +16 -16
  45. data/spec/spec_helper.rb +2 -0
  46. data/spec/subdivision_spec.rb +6 -4
  47. data/spec/thread_safety_spec.rb +4 -3
  48. data/spec/timezone_spec.rb +2 -0
  49. metadata +14 -12
  50. data/lib/countries/setup.rb +0 -18
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ISO3166
2
4
  class << self
3
5
  attr_writer :configuration
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'sixarm_ruby_unaccent'
2
4
 
3
5
  module ISO3166
4
6
  UNSEARCHABLE_METHODS = [:translations].freeze
5
7
 
6
- def self::Country(country_data_or_country)
8
+ def self.Country(country_data_or_country)
7
9
  case country_data_or_country
8
10
  when ISO3166::Country
9
11
  country_data_or_country
@@ -15,9 +17,6 @@ module ISO3166
15
17
  end
16
18
 
17
19
  module CountryClassMethods
18
- FIND_BY_REGEX = /^find_(all_)?(country_|countries_)?by_(.+)/
19
- SEARCH_TERM_FILTER_REGEX = /\(|\)|\[\]|,/
20
-
21
20
  def new(country_data)
22
21
  super if country_data.is_a?(Hash) || codes.include?(country_data.to_s.upcase)
23
22
  end
@@ -33,10 +32,6 @@ module ISO3166
33
32
 
34
33
  alias countries all
35
34
 
36
- def all_translated(locale = 'en')
37
- translations(locale).values
38
- end
39
-
40
35
  def all_names_with_codes(locale = 'en')
41
36
  Country.all.map do |c|
42
37
  lc = (c.translation(locale) || c.iso_short_name)
@@ -50,6 +45,10 @@ module ISO3166
50
45
  end
51
46
  end
52
47
 
48
+ def all_translated(locale = 'en')
49
+ translations(locale).values
50
+ end
51
+
53
52
  def translations(locale = 'en')
54
53
  i18n_data_countries = I18nData.countries(locale.upcase)
55
54
 
@@ -62,54 +61,6 @@ module ISO3166
62
61
  i18n_data_countries.merge(custom_countries)
63
62
  end
64
63
 
65
- def search(query)
66
- country = new(query.to_s.upcase)
67
- country && country.valid? ? country : nil
68
- end
69
-
70
- def [](query)
71
- search(query)
72
- end
73
-
74
- def method_missing(method_name, *arguments)
75
- matches = method_name.to_s.match(FIND_BY_REGEX)
76
- return_all = matches[1]
77
- super unless matches
78
-
79
- if matches[3] == 'names'
80
- if RUBY_VERSION =~ /^3\.\d\.\d/
81
- warn "DEPRECATION WARNING: 'find_by_name' and 'find_*_by_name' methods are deprecated, please refer to the README file for more information on this change.", uplevel: 1, category: :deprecated
82
- else
83
- warn "DEPRECATION WARNING: 'find_by_name' and 'find_*_by_name' methods are deprecated, please refer to the README file for more information on this change.", uplevel: 1
84
- end
85
- end
86
-
87
- countries = find_by(matches[3], arguments[0], matches[2])
88
- return_all ? countries : countries.last
89
- end
90
-
91
- def respond_to_missing?(method_name, include_private = false)
92
- matches = method_name.to_s.match(FIND_BY_REGEX)
93
- if matches && matches[3]
94
- instance_methods.include?(matches[3].to_sym)
95
- else
96
- super
97
- end
98
- end
99
-
100
- def find_all_by(attribute, val)
101
- attributes, lookup_value = parse_attributes(attribute, val)
102
-
103
- ISO3166::Data.cache.select do |_, v|
104
- country = Country.new(v)
105
- attributes.any? do |attr|
106
- Array(country.send(attr)).any? do |n|
107
- lookup_value === cached(n) { parse_value(n) }
108
- end
109
- end
110
- end
111
- end
112
-
113
64
  def subdivisions(alpha2)
114
65
  @subdivisions ||= {}
115
66
  @subdivisions[alpha2] ||= create_subdivisions(subdivision_data(alpha2))
@@ -124,51 +75,14 @@ module ISO3166
124
75
 
125
76
  protected
126
77
 
127
- def strip_accents(v)
128
- if v.is_a?(Regexp)
129
- Regexp.new(v.source.unaccent, 'i')
78
+ def strip_accents(string)
79
+ if string.is_a?(Regexp)
80
+ Regexp.new(string.source.unaccent, 'i')
130
81
  else
131
- v.to_s.unaccent.downcase
132
- end
133
- end
134
-
135
- def parse_attributes(attribute, val)
136
- raise "Invalid attribute name '#{attribute}'" unless searchable_attribute?(attribute.to_sym)
137
-
138
- attributes = Array(attribute.to_s)
139
- if attribute.to_s == 'name'
140
- if RUBY_VERSION =~ /^3\.\d\.\d/
141
- warn "DEPRECATION WARNING: 'find_by_name' and 'find_*_by_name' methods are deprecated, please refer to the README file for more information on this change.", uplevel: 1, category: :deprecated
142
- else
143
- warn "DEPRECATION WARNING: 'find_by_name' and 'find_*_by_name' methods are deprecated, please refer to the README file for more information on this change.", uplevel: 1
144
- end
145
- # 'find_by_name' and 'find_*_by_name' will be changed for 5.0
146
- # The addition of 'iso_short_name' here ensures the behaviour of 4.1 is kept for 4.2
147
- attributes = %w[iso_short_name unofficial_names translated_names]
148
- end
149
-
150
- [attributes, parse_value(val)]
151
- end
152
-
153
- def searchable_attribute?(attribute)
154
- searchable_attributes.include?(attribute.to_sym)
155
- end
156
-
157
- def searchable_attributes
158
- instance_methods - UNSEARCHABLE_METHODS
159
- end
160
-
161
- def find_by(attribute, value, obj = nil)
162
- find_all_by(attribute.downcase, value).map do |country|
163
- obj.nil? ? country : new(country.last)
82
+ string.to_s.unaccent.downcase
164
83
  end
165
84
  end
166
85
 
167
- def parse_value(value)
168
- value = value.gsub(SEARCH_TERM_FILTER_REGEX, '') if value.respond_to?(:gsub)
169
- strip_accents(value)
170
- end
171
-
172
86
  def subdivision_data(alpha2)
173
87
  file = subdivision_file_path(alpha2)
174
88
  File.exist?(file) ? YAML.load_file(file) : {}
@@ -190,6 +104,7 @@ module ISO3166
190
104
  def cached(value)
191
105
  @_parsed_values_cache ||= {}
192
106
  return @_parsed_values_cache[value] if @_parsed_values_cache[value]
107
+
193
108
  @_parsed_values_cache[value] = yield
194
109
  end
195
110
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'money'
2
4
 
3
5
  module ISO3166
@@ -1,5 +1,4 @@
1
- #!/bin/env ruby
2
- # encoding: utf-8
1
+ # frozen_string_literal: true
3
2
 
4
3
  module ISO3166
5
4
  module Emoji
@@ -36,7 +35,7 @@ module ISO3166
36
35
  #
37
36
  # The emoji flag for this country, using Unicode Regional Indicator characters. e.g: "U+1F1FA U+1F1F8" for 🇺🇸
38
37
  def emoji_flag
39
- alpha2.downcase.chars.map { |c| CODE_POINTS[c] }.join('')
38
+ alpha2.downcase.chars.map { |c| CODE_POINTS[c] }.join
40
39
  end
41
40
  end
42
41
  end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ISO3166
4
+ module CountryFinderMethods
5
+ FIND_BY_REGEX = /^find_(all_)?(country_|countries_)?by_(.+)/.freeze
6
+ SEARCH_TERM_FILTER_REGEX = /\(|\)|\[\]|,/.freeze
7
+
8
+ def search(query)
9
+ country = new(query.to_s.upcase)
10
+ country&.valid? ? country : nil
11
+ end
12
+
13
+ def [](query)
14
+ search(query)
15
+ end
16
+
17
+ def find_all_by(attribute, val)
18
+ attributes, lookup_value = parse_attributes(attribute, val)
19
+
20
+ ISO3166::Data.cache.select do |_, v|
21
+ country = Country.new(v)
22
+ attributes.any? do |attr|
23
+ Array(country.send(attr)).any? do |n|
24
+ lookup_value === cached(n) { parse_value(n) }
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ def method_missing(method_name, *arguments)
31
+ matches = method_name.to_s.match(FIND_BY_REGEX)
32
+ return_all = matches[1]
33
+ super unless matches
34
+
35
+ countries = find_by(matches[3], arguments[0], matches[2])
36
+ return_all ? countries : countries.last
37
+ end
38
+
39
+ def respond_to_missing?(method_name, include_private = false)
40
+ matches = method_name.to_s.match(FIND_BY_REGEX)
41
+ if matches && matches[3]
42
+ instance_methods.include?(matches[3].to_sym)
43
+ else
44
+ super
45
+ end
46
+ end
47
+
48
+ protected
49
+
50
+ def find_by(attribute, value, obj = nil)
51
+ find_all_by(attribute.downcase, value).map do |country|
52
+ obj.nil? ? country : new(country.last)
53
+ end
54
+ end
55
+
56
+ def parse_attributes(attribute, val)
57
+ raise "Invalid attribute name '#{attribute}'" unless searchable_attribute?(attribute.to_sym)
58
+
59
+ attributes = Array(attribute.to_s)
60
+ if attribute.to_s == 'any_name'
61
+ attributes = %w[iso_long_name iso_short_name unofficial_names translated_names]
62
+ end
63
+
64
+ [attributes, parse_value(val)]
65
+ end
66
+
67
+ def parse_value(value)
68
+ value = value.gsub(SEARCH_TERM_FILTER_REGEX, '') if value.respond_to?(:gsub)
69
+ strip_accents(value)
70
+ end
71
+
72
+ def searchable_attribute?(attribute)
73
+ searchable_attributes.include?(attribute.to_sym)
74
+ end
75
+
76
+ def searchable_attributes
77
+ # Add name and names until we complete the deprecation of the finders
78
+ instance_methods - UNSEARCHABLE_METHODS + [:name, :names, :any_name]
79
+ end
80
+ end
81
+ end
@@ -1,6 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ISO3166
2
4
  class Country
3
5
  extend CountryClassMethods
6
+ extend CountryFinderMethods
4
7
  include Emoji
5
8
  attr_reader :data
6
9
 
@@ -31,24 +34,6 @@ module ISO3166
31
34
  alias zip_format postal_code_format
32
35
  alias languages languages_official
33
36
 
34
- def latitude_dec
35
- if RUBY_VERSION =~ /^3\.\d\.\d/
36
- warn "DEPRECATION WARNING: The Country#latitude_dec method has been deprecated and will be removed in 5.0. Please use Country#latitude instead.", uplevel: 1, category: :deprecated
37
- else
38
- warn "DEPRECATION WARNING: The Country#latitude_dec method has been deprecated and will be removed in 5.0. Please use Country#latitude instead.", uplevel: 1
39
- end
40
- latitude
41
- end
42
-
43
- def longitude_dec
44
- if RUBY_VERSION =~ /^3\.\d\.\d/
45
- warn "DEPRECATION WARNING: The Country#longitude_dec method has been deprecated and will be removed in 5.0. Please use Country#longitude instead.", uplevel: 1, category: :deprecated
46
- else
47
- warn "DEPRECATION WARNING: The Country#longitude_dec method has been deprecated and will be removed in 5.0. Please use Country#longitude instead.", uplevel: 1
48
- end
49
- longitude
50
- end
51
-
52
37
  def ==(other)
53
38
  other.respond_to?(:alpha2) && other.alpha2 == alpha2
54
39
  end
@@ -136,28 +121,6 @@ module ISO3166
136
121
  @local_name ||= local_names.first
137
122
  end
138
123
 
139
- # @return [String] This Country's ISO Short Name
140
- # @deprecated Use {#iso_short_name} instead.
141
- def name
142
- if RUBY_VERSION =~ /^3\.\d\.\d/
143
- warn "DEPRECATION WARNING: The Country#name method has been deprecated. Please use Country#iso_short_name instead or refer to the README file for more information on this change.", uplevel: 1, category: :deprecated
144
- else
145
- warn "DEPRECATION WARNING: The Country#name method has been deprecated. Please use Country#iso_short_name instead or refer to the README file for more information on this change.", uplevel: 1
146
- end
147
- iso_short_name
148
- end
149
-
150
- # @return [Array<String>] Array of unofficial, slang names or aliases for this Country
151
- # @deprecated Use {#unofficial_names} instead.
152
- def names
153
- if RUBY_VERSION =~ /^3\.\d\.\d/
154
- warn "DEPRECATION WARNING: The Country#names method has been deprecated. Please use Country#unofficial_names instead or refer to the README file for more information on this change.", uplevel: 1, category: :deprecated
155
- else
156
- warn "DEPRECATION WARNING: The Country#names method has been deprecated. Please use Country#unofficial_names instead or refer to the README file for more information on this change.", uplevel: 1
157
- end
158
- unofficial_names
159
- end
160
-
161
124
  # @!attribute alpha2
162
125
  # @return [String] the ISO3166 alpha-2 code for this Country
163
126
  #
@@ -9,7 +9,6 @@ KN:
9
9
  geo:
10
10
  latitude: 17.357822
11
11
  longitude: -62.782998
12
- longitude_dec: "-62.643184661865234"
13
12
  max_latitude: 17.4205891
14
13
  max_longitude: -62.52369989999999
15
14
  min_latitude: 17.07861
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ISO3166
2
4
  # Handles building the in memory store of countries data
3
5
  class Data
4
- @@cache_dir = [File.dirname(__FILE__), 'cache']
5
- @@cache = {}
6
- @@registered_data = {}
7
- @@mutex = Mutex.new
6
+ @cache_dir = [File.dirname(__FILE__), 'cache']
7
+ @cache = {}
8
+ @registered_data = {}
9
+ @mutex = Mutex.new
8
10
 
9
11
  def initialize(alpha2)
10
12
  @alpha2 = alpha2.to_s.upcase
@@ -15,30 +17,23 @@ module ISO3166
15
17
  end
16
18
 
17
19
  class << self
18
- def cache_dir
19
- @@cache_dir
20
- end
21
-
22
- def cache_dir=(value)
23
- @@cache_dir = value
24
- end
25
20
 
26
21
  # Registers a new Country with custom data.
27
22
  # If you are overriding an existing country, this does not perform a deep merge so you will need to __bring in all data you wish to be available__.
28
23
  # Overriding an existing country will also remove it from the internal management of translations.
29
24
  def register(data)
30
25
  alpha2 = data[:alpha2].upcase
31
- @@registered_data[alpha2] = deep_stringify_keys(data)
32
- @@registered_data[alpha2]['translations'] = \
26
+ @registered_data[alpha2] = deep_stringify_keys(data)
27
+ @registered_data[alpha2]['translations'] = \
33
28
  Translations.new.merge(data['translations'] || {})
34
- @@cache = cache.merge(@@registered_data)
29
+ @cache = cache.merge(@registered_data)
35
30
  end
36
31
 
37
32
  # Removes a country from the loaded data
38
33
  def unregister(alpha2)
39
34
  alpha2 = alpha2.to_s.upcase
40
- @@cache.delete(alpha2)
41
- @@registered_data.delete(alpha2)
35
+ @cache.delete(alpha2)
36
+ @registered_data.delete(alpha2)
42
37
  end
43
38
 
44
39
  def cache
@@ -47,8 +42,8 @@ module ISO3166
47
42
 
48
43
  # Resets the loaded data and cache
49
44
  def reset
50
- @@cache = {}
51
- @@registered_data = {}
45
+ @cache = {}
46
+ @registered_data = {}
52
47
  ISO3166.configuration.loaded_locales = []
53
48
  end
54
49
 
@@ -60,16 +55,19 @@ module ISO3166
60
55
  def update_cache
61
56
  load_data!
62
57
  sync_translations!
63
- @@cache
58
+ @cache
64
59
  end
65
60
 
61
+ private
62
+
66
63
  def load_data!
67
- return @@cache unless load_required?
64
+ return @cache unless load_required?
65
+
68
66
  synchronized do
69
- @@cache = load_cache %w(countries.json)
70
- @@_country_codes = @@cache.keys
71
- @@cache = @@cache.merge(@@registered_data)
72
- @@cache
67
+ @cache = load_cache %w[countries.json]
68
+ @_country_codes = @cache.keys
69
+ @cache = @cache.merge(@registered_data)
70
+ @cache
73
71
  end
74
72
  end
75
73
 
@@ -85,11 +83,9 @@ module ISO3166
85
83
  end
86
84
  end
87
85
 
88
- private
89
-
90
86
  def synchronized(&block)
91
87
  if use_mutex?
92
- @@mutex.synchronize(&block)
88
+ @mutex.synchronize(&block)
93
89
  else
94
90
  block.call
95
91
  end
@@ -102,17 +98,17 @@ module ISO3166
102
98
 
103
99
  def load_required?
104
100
  synchronized do
105
- @@cache.empty?
101
+ @cache.empty?
106
102
  end
107
103
  end
108
104
 
109
105
  def loaded_codes
110
- @@cache.keys
106
+ @cache.keys
111
107
  end
112
108
 
113
109
  # Codes that we have translations for in dataset
114
110
  def internal_codes
115
- @@_country_codes - @@registered_data.keys
111
+ @_country_codes - @registered_data.keys
116
112
  end
117
113
 
118
114
  def cache_flush_required?
@@ -139,9 +135,9 @@ module ISO3166
139
135
  synchronized do
140
136
  locale_names = load_cache(['locales', "#{locale}.json"])
141
137
  internal_codes.each do |alpha2|
142
- @@cache[alpha2]['translations'] ||= Translations.new
143
- @@cache[alpha2]['translations'][locale] = locale_names[alpha2].freeze
144
- @@cache[alpha2]['translated_names'] = @@cache[alpha2]['translations'].values.freeze
138
+ @cache[alpha2]['translations'] ||= Translations.new
139
+ @cache[alpha2]['translations'][locale] = locale_names[alpha2].freeze
140
+ @cache[alpha2]['translated_names'] = @cache[alpha2]['translations'].values.freeze
145
141
  end
146
142
  ISO3166.configuration.loaded_locales << locale
147
143
  end
@@ -150,8 +146,8 @@ module ISO3166
150
146
  def unload_translations(locale)
151
147
  synchronized do
152
148
  internal_codes.each do |alpha2|
153
- @@cache[alpha2]['translations'].delete(locale)
154
- @@cache[alpha2]['translated_names'] = @@cache[alpha2]['translations'].values.freeze
149
+ @cache[alpha2]['translations'].delete(locale)
150
+ @cache[alpha2]['translated_names'] = @cache[alpha2]['translations'].values.freeze
155
151
  end
156
152
  ISO3166.configuration.loaded_locales.delete(locale)
157
153
  end
@@ -163,7 +159,7 @@ module ISO3166
163
159
  end
164
160
 
165
161
  def datafile_path(file_array)
166
- File.join([@@cache_dir] + file_array)
162
+ File.join([@cache_dir] + file_array)
167
163
  end
168
164
 
169
165
  def deep_stringify_keys(data)
@@ -171,7 +167,8 @@ module ISO3166
171
167
  data.transform_values! do |v|
172
168
  v.is_a?(Hash) ? deep_stringify_keys(v) : v
173
169
  end
174
- return data
170
+
171
+ data
175
172
  end
176
173
  end
177
174
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'countries'
2
4
 
3
5
  # Some apps might not want to constantly call +ISO3166::Country+. This gem has a helper that can provide a Country class
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'yaml'
2
4
  require 'json'
3
5
  require 'i18n_data'
@@ -8,6 +10,7 @@ require 'countries/data'
8
10
  require 'countries/structure'
9
11
  require 'countries/translations'
10
12
  require 'countries/country/class_methods'
13
+ require 'countries/country/finder_methods'
11
14
  require 'countries/country/emoji'
12
15
  require 'countries/country'
13
16
  require 'countries/subdivision'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ISO3166
2
4
  class KwargStruct < Struct
3
5
  # Override the initialize to handle hashes of named parameters
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ISO3166
2
4
  class Country
3
5
  def mongoize
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'uri'
2
4
  require 'net/http'
3
5
  require 'nokogiri'
@@ -19,19 +21,17 @@ module Sources
19
21
  def download_folder(type)
20
22
  folder = File.join(ISO3166_ROOT_PATH, 'tmp', 'cldr', 'trunk', 'common', type)
21
23
  FileUtils.mkdir_p(folder)
22
- url = URI.parse("https://api.github.com/repos/unicode-org/cldr/contents/common/" + type)
24
+ url = URI.parse("https://api.github.com/repos/unicode-org/cldr/contents/common/#{type}")
23
25
  path_listing = JSON.parse(Net::HTTP.get_response(url).body)
24
26
  path_listing.each do |path|
25
- if path['name'] =~ /\.xml$/
26
- File.open(File.join(folder, path['name']), 'w') do |f|
27
- raw_url = URI.parse(path['download_url'])
28
- f.write(Net::HTTP.get_response(raw_url).body)
29
- end
27
+ next unless path['name'] =~ /\.xml$/
28
+
29
+ File.open(File.join(folder, path['name']), 'w') do |f|
30
+ raw_url = URI.parse(path['download_url'])
31
+ f.write(Net::HTTP.get_response(raw_url).body)
30
32
  end
31
33
  end
32
34
  end
33
-
34
35
  end
35
36
  end
36
37
  end
37
-
@@ -1,8 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sources
2
4
  module CLDR
3
5
  # Auxiliary Subdivision class to support loading Unicode CLDR data to update local files
4
6
  class Subdivision
5
7
  attr_reader :xml, :language_code
8
+
6
9
  def initialize(language_code:, xml:)
7
10
  @language_code = language_code
8
11
  @xml = xml
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_support'
2
4
  require 'active_support/core_ext/hash/deep_merge'
3
5
  require 'nokogiri'
@@ -9,25 +11,29 @@ module Sources
9
11
  class SubdivisionUpdater
10
12
  def call
11
13
  d = Dir['./tmp/cldr/trunk/common/subdivisions/*.xml']
12
- loader = Sources::Local::CachedLoader.new(Sources::Local::Subdivision)
13
- d.each do |file_path|
14
- language_data = Nokogiri::XML(File.read(file_path))
15
- language_code = File.basename(file_path, '.*')
16
- subdivisions = language_data.css('subdivision')
17
- next if subdivisions.empty?
18
- last_country_code_seen = nil
14
+ @loader = Sources::Local::CachedLoader.new(Sources::Local::Subdivision)
15
+ d.each { |file_path| update_locale(file_path) }
16
+ end
17
+
18
+ def update_locale(file_path)
19
+ language_data = Nokogiri::XML(File.read(file_path))
20
+ language_code = File.basename(file_path, '.*')
21
+ subdivisions = language_data.css('subdivision')
22
+ next if subdivisions.empty?
23
+
24
+ last_country_code_seen = nil
19
25
 
20
- subdivisions.each_with_index do |subdivision, index|
21
- subdivision = Sources::CLDR::Subdivision.new(language_code: language_code, xml: subdivision)
22
- data = loader.load(subdivision.country_code)
23
- data[subdivision.code] ||= {}
24
- data[subdivision.code] = data[subdivision.code].deep_merge(subdivision.to_h)
25
- if (last_country_code_seen && last_country_code_seen != subdivision.country_code) || index == subdivisions.size - 1
26
- puts "Updated #{subdivision.country_code} with language_code #{language_code}"
27
- loader.save(subdivision.country_code, data)
28
- end
29
- last_country_code_seen = subdivision.country_code
26
+ subdivisions.each_with_index do |subdivision, index|
27
+ subdivision = Sources::CLDR::Subdivision.new(language_code: language_code, xml: subdivision)
28
+ data = @loader.load(subdivision.country_code)
29
+ data[subdivision.code] ||= {}
30
+ data[subdivision.code] = data[subdivision.code].deep_merge(subdivision.to_h)
31
+ if (last_country_code_seen && last_country_code_seen != subdivision.country_code) ||
32
+ index == subdivisions.size - 1
33
+ puts "Updated #{subdivision.country_code} with language_code #{language_code}"
34
+ @loader.save(subdivision.country_code, data)
30
35
  end
36
+ last_country_code_seen = subdivision.country_code
31
37
  end
32
38
  end
33
39
  end
@@ -1,9 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sources
2
4
  # Support code to allow updating subdivision data from the Unicode CLDR repository
3
5
  module Local
4
6
  # Loader for locally-cached data, to allow merging Unicode CLDR data with existing local data
5
7
  class CachedLoader
6
8
  attr_reader :klass
9
+
7
10
  def initialize(klass)
8
11
  @klass = klass
9
12
  @loaded_countries = {}
@@ -1,8 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sources
2
4
  module Local
3
5
  # Auxiliary Subdivision class to support loading the local subdivision data to be updated with Unicode CLDR data
4
6
  class Subdivision
5
7
  attr_reader :code
8
+
6
9
  def initialize(code)
7
10
  @code = code
8
11
  end
@@ -16,8 +19,8 @@ module Sources
16
19
  end
17
20
 
18
21
  def save(data)
19
- File.open(file_path, 'w') { |f| f.write data.to_yaml }
20
- rescue
22
+ File.write(file_path, data.to_yaml)
23
+ rescue StandardError
21
24
  puts "failed to read #{file}: #{$ERROR_INFO}"
22
25
  end
23
26