File: data.rb

package info (click to toggle)
ruby-countries 4.2.2-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 11,196 kB
  • sloc: ruby: 2,085; makefile: 4
file content (178 lines) | stat: -rw-r--r-- 4,560 bytes parent folder | download
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