Module: Timeprice::DataLoader

Defined in:
lib/timeprice/data_loader.rb

Overview

Loads and caches the bundled JSON data files. Override the search root by setting ‘TIMEPRICE_DATA_ROOT` in the environment or assigning DataLoader.data_root=.

Constant Summary collapse

DEFAULT_DATA_ROOT =
File.expand_path("../../data", __dir__)

Class Method Summary collapse

Class Method Details

.clear_cache!void

This method returns an undefined value.

Drop in-memory caches of parsed data files.



30
31
32
33
34
35
# File 'lib/timeprice/data_loader.rb', line 30

def clear_cache!
  @cpi_cache = {}
  @fx_cache = {}
  @manifest_cache = {}
  @annual_fallback_cache = {}
end

.data_rootString

Returns absolute path to the directory containing ‘cpi/`, `fx/`, `manifest.json`.

Returns:

  • (String)

    absolute path to the directory containing ‘cpi/`, `fx/`, `manifest.json`.



16
17
18
# File 'lib/timeprice/data_loader.rb', line 16

def data_root
  ENV["TIMEPRICE_DATA_ROOT"] || @data_root || DEFAULT_DATA_ROOT
end

.data_root=(path) ⇒ void

This method returns an undefined value.

Override the data root and clear caches. Mostly useful in tests.

Parameters:

  • path (String)


23
24
25
26
# File 'lib/timeprice/data_loader.rb', line 23

def data_root=(path)
  @data_root = path
  clear_cache!
end

.load_cpi(country) ⇒ Hash

Load the CPI series for a supported country.

Parameters:

  • country (String)

Returns:

  • (Hash)

    parsed JSON with “series” / “index” / “provenance” / “providers”

Raises:



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/timeprice/data_loader.rb', line 58

def load_cpi(country)
  key = country.to_s.downcase
  code = country.to_s.upcase
  cpi_cache[[data_root, key]] ||= begin
    fail UnsupportedCountry, code unless Supported.country?(code)

    path = File.join(data_root, "cpi", "#{key}.json")
    unless File.exist?(path)
      fail DataNotFound, "CPI data file missing for #{code} (looked in #{path}). " \
                         "Check TIMEPRICE_DATA_ROOT or reinstall the gem."
    end

    parse_with_schema(path)
  end
end

.load_fx_annual_fallbackHash?

Load the sparse historical FX annual-only fallback file, if present. Returns nil when no fallback file ships with this data root.

Returns:

  • (Hash, nil)


91
92
93
94
95
96
97
# File 'lib/timeprice/data_loader.rb', line 91

def load_fx_annual_fallback
  return @annual_fallback_cache[data_root] if @annual_fallback_cache&.key?(data_root)

  @annual_fallback_cache ||= {}
  path = File.join(data_root, "fx", "usd", "_annual.json")
  @annual_fallback_cache[data_root] = File.exist?(path) ? parse_with_schema(path) : nil
end

.load_fx_year(year) ⇒ Hash

Load the FX rates for a year.

Parameters:

  • year (Integer, String)

Returns:

  • (Hash)

    parsed JSON with ‘rates` (and optional `annual`) blocks

Raises:



78
79
80
81
82
83
84
85
86
# File 'lib/timeprice/data_loader.rb', line 78

def load_fx_year(year)
  key = year.to_i
  fx_cache[[data_root, key]] ||= begin
    path = File.join(data_root, "fx", "usd", "#{key}.json")
    fail DataNotFound, "No FX data for year #{key}" unless File.exist?(path)

    parse_with_schema(path)
  end
end

.load_manifestHash

Load the top-level manifest describing the bundled dataset.

Returns:

  • (Hash)

Raises:



40
41
42
43
44
45
46
47
48
49
50
# File 'lib/timeprice/data_loader.rb', line 40

def load_manifest
  manifest_cache[data_root] ||= begin
    path = File.join(data_root, "manifest.json")
    unless File.exist?(path)
      fail DataNotFound, "manifest.json missing (looked in #{path}). " \
                         "Check TIMEPRICE_DATA_ROOT or reinstall the gem."
    end

    parse_with_schema(path)
  end
end