1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
|
module ISO3166
# Handles building the in memory store of countries data
class Data
@@cache_dir = [File.dirname(__FILE__), 'cache']
@@cache = {}
@@registered_data = {}
@@mutex = Mutex.new
def initialize(alpha2)
@alpha2 = alpha2.to_s.upcase
end
def call
self.class.update_cache[@alpha2]
end
class << self
def cache_dir
@@cache_dir
end
def cache_dir=(value)
@@cache_dir = value
end
# Registers a new Country with custom data.
# 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__.
# Overriding an existing country will also remove it from the internal management of translations.
def register(data)
alpha2 = data[:alpha2].upcase
@@registered_data[alpha2] = deep_stringify_keys(data)
@@registered_data[alpha2]['translations'] = \
Translations.new.merge(data['translations'] || {})
@@cache = cache.merge(@@registered_data)
end
# Removes a country from the loaded data
def unregister(alpha2)
alpha2 = alpha2.to_s.upcase
@@cache.delete(alpha2)
@@registered_data.delete(alpha2)
end
def cache
update_cache
end
# Resets the loaded data and cache
def reset
@@cache = {}
@@registered_data = {}
ISO3166.configuration.loaded_locales = []
end
def codes
load_data!
loaded_codes
end
def update_cache
load_data!
sync_translations!
@@cache
end
def load_data!
return @@cache unless load_required?
synchronized do
@@cache = load_cache %w(countries.json)
@@_country_codes = @@cache.keys
@@cache = @@cache.merge(@@registered_data)
@@cache
end
end
def sync_translations!
return unless cache_flush_required?
locales_to_remove.each do |locale|
unload_translations(locale)
end
locales_to_load.each do |locale|
load_translations(locale)
end
end
private
def synchronized(&block)
if use_mutex?
@@mutex.synchronize(&block)
else
block.call
end
end
def use_mutex?
# Stubbed in testing
true
end
def load_required?
synchronized do
@@cache.empty?
end
end
def loaded_codes
@@cache.keys
end
# Codes that we have translations for in dataset
def internal_codes
@@_country_codes - @@registered_data.keys
end
def cache_flush_required?
!locales_to_load.empty? || !locales_to_remove.empty?
end
def locales_to_load
requested_locales - loaded_locales
end
def locales_to_remove
loaded_locales - requested_locales
end
def requested_locales
ISO3166.configuration.locales.map { |l| l.to_s.downcase }
end
def loaded_locales
ISO3166.configuration.loaded_locales.map { |l| l.to_s.downcase }
end
def load_translations(locale)
synchronized do
locale_names = load_cache(['locales', "#{locale}.json"])
internal_codes.each do |alpha2|
@@cache[alpha2]['translations'] ||= Translations.new
@@cache[alpha2]['translations'][locale] = locale_names[alpha2].freeze
@@cache[alpha2]['translated_names'] = @@cache[alpha2]['translations'].values.freeze
end
ISO3166.configuration.loaded_locales << locale
end
end
def unload_translations(locale)
synchronized do
internal_codes.each do |alpha2|
@@cache[alpha2]['translations'].delete(locale)
@@cache[alpha2]['translated_names'] = @@cache[alpha2]['translations'].values.freeze
end
ISO3166.configuration.loaded_locales.delete(locale)
end
end
def load_cache(file_array)
file_path = datafile_path(file_array)
File.exist?(file_path) ? JSON.parse(File.binread(file_path)) : {}
end
def datafile_path(file_array)
File.join([@@cache_dir] + file_array)
end
def deep_stringify_keys(data)
data.transform_keys!(&:to_s)
data.transform_values! do |v|
v.is_a?(Hash) ? deep_stringify_keys(v) : v
end
return data
end
end
end
end
|