fafx 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 93feca2af8fb931f0c8e62b0f3aea2bf24eaaf9c
4
- data.tar.gz: 4bcdfbf6645958ed69b014d6d5f737728b6e36b0
3
+ metadata.gz: 00740a9067c4044fd55665b0c61059c090cb1657
4
+ data.tar.gz: 61dc5c53fc2d376d850efe43e3397d43f5ab6be5
5
5
  SHA512:
6
- metadata.gz: 1e52c5a8b4c5c7895ff69da56cb93c8807e8fd8b47dbcbc8636254e9772c99c216b7518eb05295ed02750e34a6202c303de81e3518d598ed4d5676a99e393f9f
7
- data.tar.gz: 240f24101ace83b8f0829d77bfb14896490b227ac4e8aa61a38b8374f38d464dfc14c60c3e877f44596d60e7b76b92bf3e778477e0e7e34ce048fc00cb50f0c6
6
+ metadata.gz: 7c3a0cea20e949601b2115f9fd533922d5a81565f576a9903a6d62d0fa237553645d5d423d88f1b4000f172462342560baec3225dccf37d6698dd2cd9c4dda70
7
+ data.tar.gz: b22882852ddb68ce273973f90e17b67be2ecfdfcd7a23d8543c048c63193d64ffca22ce9e801a1b9cef71cd0f2252aaea388c289acb810926a5180e778a26b21
data/README.md CHANGED
@@ -2,13 +2,15 @@
2
2
 
3
3
  [![Build Status](https://travis-ci.org/FrankKair/fafx.svg?branch=master)](https://travis-ci.org/FrankKair/fafx)
4
4
 
5
- ### Installation
5
+ FAFX fetches data from the 90 day European Central Bank (ECB) feed and offers a simple CLI and API to interect with.
6
6
 
7
- `$ gem install fafx`
7
+ ## Installation
8
8
 
9
- ### CLI
9
+ $ gem install fafx
10
10
 
11
- `$ fafx`
11
+ ## CLI
12
+
13
+ $ fafx
12
14
 
13
15
  ```
14
16
  Usage: fafx [options]
@@ -18,42 +20,47 @@ Usage: fafx [options]
18
20
  --update Fetches new data from the web
19
21
  ```
20
22
 
21
- ### Example of client usage
23
+ ## Example of client usage
22
24
 
23
25
  ```ruby
24
26
  require 'Date'
25
27
  require 'fafx'
26
28
 
27
- puts Fafx::ExchangeRate.at(Date.today, 'GBP', 'USD')
28
- puts Fafx::ExchangeRate.currencies_available
29
- puts Fafx::ExchangeRate.dates_available
30
- puts Fafx::ExchangeRate.most_recent
31
- ```
29
+ Fafx::ExchangeRate.at(Date.today, 'GBP', 'USD')
30
+ # => 1.2951645399597045
31
+
32
+ Fafx::ExchangeRate.currencies_available
33
+ # => ["USD", "JPY", "BGN", "CZK", ...]
32
34
 
33
- This code outputs:
35
+ Fafx::ExchangeRate.dates_available
36
+ # => ["2018-09-10", "2018-09-07", "2018-09-06", "2018-09-05", ...]
34
37
 
38
+ Fafx::ExchangeRate.most_recent
39
+ # => {"USD"=>1.1571, "JPY"=>128.54, "BGN"=>1.9558, "CZK"=>25.648, ...}
35
40
  ```
36
- 1.2951995012468827
37
41
 
38
- USD
39
- JPY
40
- BGN
41
- CZK
42
- ...
42
+ The `at` function may raise a `KeyError` exception, should the date or currency be unavailable.
43
+
44
+ ## Updating the exchange rates data
45
+
46
+ You can update the exchange rates values either via the **CLI**, **Rake task** or **programmatically**:
47
+
48
+ $ fafx --update
43
49
 
44
- 2018-09-07
45
- 2018-09-06
46
- 2018-09-05
47
- 2018-09-04
48
- ...
50
+ $ rake update_data
49
51
 
50
- {"USD"=>1.1615, "JPY"=>128.74, "BGN"=>1.9558, "CZK"=>25.697 ... }
52
+ ```ruby
53
+ require 'fafx'
54
+
55
+ Fafx::ExchangeRate.fetch_data_and_save_to_disk
51
56
  ```
52
57
 
53
- ### Updating the exchange rates data
58
+ ---
54
59
 
55
- You can update the exchange rates values via the CLI using:
60
+ One can also schedule a **cron job** (the following example fetches the data every minute):
56
61
 
57
- `$ fafx --update`
62
+ ```
63
+ * * * * * . ~/.zshrc; fafx -u
64
+ ```
58
65
 
59
- One can also use the `$ rake update_data` task as well.
66
+ Note: `. ~/.zshrc` is used to load the environment with the Ruby gems path, because cron uses `PATH=/usr/bin:/usr/sbin` and `SHELL=/usr/bin/sh by default`. Fonts: [here](http://man7.org/linux/man-pages/man5/crontab.5.html) and [here](http://www.adminschoice.com/crontab-quick-reference)
data/Rakefile CHANGED
@@ -7,5 +7,6 @@ RSpec::Core::RakeTask.new(:spec)
7
7
  task default: :spec
8
8
 
9
9
  task :update_data do
10
- Fafx::DataFetcher.save_to_disk
10
+ Fafx::ExchangeRate.fetch_data_and_save_to_disk
11
+ puts 'Exchange rates data updated!'
11
12
  end
data/bin/fafx CHANGED
@@ -3,14 +3,24 @@ require 'optparse'
3
3
  require 'fafx'
4
4
 
5
5
  ARGV[0] = '--help' if ARGV.empty?
6
- puts "invalid option: #{ARGV[0]}" unless ARGV[0].include?('--') || ARGV[0].include?('-')
6
+ unless ARGV[0].include?('--') || ARGV[0].include?('-')
7
+ puts "invalid option: #{ARGV[0]}"
8
+ end
7
9
 
8
10
  options = {}
9
11
  opt_parser = OptionParser.new do |opt|
10
- opt.on('--recent', 'Lists most recent rates') { |o| options[:recent] = o }
11
- opt.on('--currencies', 'Lists available currencies') { |o| options[:currencies] = o }
12
- opt.on('--dates', 'Lists available dates') { |o| options[:dates] = o }
13
- opt.on('--update', 'Fetches new data from the web') { |o| options[:update] = o }
12
+ opt.on('--recent', 'Lists most recent rates') do |o|
13
+ options[:recent] = o
14
+ end
15
+ opt.on('--currencies', 'Lists available currencies') do |o|
16
+ options[:currencies] = o
17
+ end
18
+ opt.on('--dates', 'Lists available dates') do |o|
19
+ options[:dates] = o
20
+ end
21
+ opt.on('--update', 'Fetches new data from the web') do |o|
22
+ options[:update] = o
23
+ end
14
24
  end
15
25
 
16
26
  begin
@@ -26,9 +36,10 @@ begin
26
36
  when :dates
27
37
  puts Fafx::ExchangeRate.dates_available
28
38
  when :update
29
- Fafx::DataFetcher.save_to_disk
39
+ Fafx::ExchangeRate.fetch_data_and_save_to_disk
40
+ puts 'Exchange rates data updated!'
30
41
  end
31
42
  end
32
- rescue Exception => e
43
+ rescue StandardError => e
33
44
  puts e.to_s unless e.message == 'exit'
34
45
  end
@@ -1,4 +1,3 @@
1
-
2
1
  lib = File.expand_path('lib', __dir__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
3
  require 'fafx/version'
@@ -11,23 +10,12 @@ Gem::Specification.new do |spec|
11
10
 
12
11
  spec.summary = 'Exchange Rates from the European Central Bank'
13
12
  spec.description = 'Lib and CLI to get exchange rates from the European Central Bank'
14
- spec.homepage = "https://github.com/frankkair/fafx"
13
+ spec.homepage = 'https://github.com/frankkair/fafx'
15
14
  spec.license = 'MIT'
16
15
 
17
- # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
- # to allow pushing to a single host or delete this section to allow pushing to any host.
19
- # if spec.respond_to?(:metadata)
20
- # spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
21
- # else
22
- # raise 'RubyGems 2.0 or newer is required to protect against ' \
23
- # 'public gem pushes.'
24
- # end
25
-
26
16
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
27
17
  f.match(%r{^(test|spec|features)/})
28
18
  end
29
- # spec.bindir = "exe"
30
- # spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
31
19
  spec.executables = ['fafx']
32
20
  spec.require_paths = ['lib']
33
21
 
@@ -1,31 +1,28 @@
1
1
  require 'open-uri'
2
2
  require 'nokogiri'
3
3
 
4
- module Fafx
5
- module DataFetcher
6
- def save_to_disk
7
- url = 'https://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist-90d.xml'
8
- doc = Nokogiri::XML(open(url))
9
- rates = process_currencies_xml(doc)
10
- dir = "#{File.join(File.dirname(__FILE__))}/rates.yaml"
11
- File.open(dir, 'w') { |f| f << rates.to_yaml }
12
- end
4
+ module DataFetcher
5
+ def save_to_disk
6
+ url = 'https://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist-90d.xml'
7
+ doc = Nokogiri::XML(open(url))
8
+ rates = process_currencies_xml(doc)
9
+ dir = "#{File.join(File.dirname(__FILE__))}/rates.yaml"
10
+ File.open(dir, 'w') { |f| f << rates.to_yaml }
11
+ end
13
12
 
14
- private
13
+ private
15
14
 
16
- def process_currencies_xml(doc)
17
- rates = {}
18
- doc.css('Cube>Cube[time]').each do |day|
19
- time = day[:time]
20
- rates[time] = {}
21
- day.css('Cube').each do |currency|
22
- # TODO: Think about float value - type safety
23
- rates[time][currency[:currency]] = currency[:rate].to_f
24
- end
15
+ def process_currencies_xml(doc)
16
+ rates = {}
17
+ doc.css('Cube>Cube[time]').each do |day|
18
+ time = day[:time]
19
+ rates[time] = {}
20
+ day.css('Cube').each do |currency|
21
+ rates[time][currency[:currency]] = currency[:rate].to_f
25
22
  end
26
- rates
27
23
  end
28
-
29
- module_function :save_to_disk, :process_currencies_xml
24
+ rates
30
25
  end
26
+
27
+ module_function :save_to_disk, :process_currencies_xml
31
28
  end
@@ -1,29 +1,25 @@
1
1
  require 'yaml'
2
2
 
3
- # TODO: Create a currency class?
4
- module Fafx
5
- class ER
6
- attr_reader :rates, :dates, :currencies
7
- def initialize
8
- data = load_data
9
- @rates = data
10
- @dates = data.keys
11
- @currencies = @rates[@dates.first].keys
12
- end
3
+ class ER
4
+ attr_reader :rates, :dates, :currencies
5
+ def initialize
6
+ data = load_data
7
+ @rates = data
8
+ @dates = data.keys
9
+ @currencies = @rates[@dates.first].keys
10
+ end
13
11
 
14
- def rates_at(date, curr)
15
- raise KeyError, 'Date not available' unless @dates.include?(date)
16
- raise KeyError, "#{curr} not found" unless @currencies.include?(curr)
17
- @rates[date][curr]
18
- end
12
+ def rates_at(date, curr)
13
+ raise KeyError, 'Date not available' unless @dates.include?(date)
14
+ raise KeyError, "#{curr} not found" unless @currencies.include?(curr)
15
+ @rates[date][curr]
16
+ end
19
17
 
20
- private
18
+ private
21
19
 
22
- # -> Hash[String => Float]
23
- def load_data
24
- rates = "#{File.join(File.dirname(__FILE__))}/rates.yaml"
25
- DataFetcher.save_to_disk unless File.exist?(rates)
26
- YAML.load_file(rates)
27
- end
20
+ def load_data
21
+ rates = "#{File.join(File.dirname(__FILE__))}/rates.yaml"
22
+ Fafx::ExchangeRate.fetch_data_and_save_to_disk unless File.exist?(rates)
23
+ YAML.load_file(rates)
28
24
  end
29
25
  end
@@ -1,9 +1,9 @@
1
1
  module Fafx
2
2
  module ExchangeRate
3
3
  def at(date, base, other)
4
- er = ER.new
5
- base = er.rates_at(date.to_s, base)
6
- other = er.rates_at(date.to_s, other)
4
+ ex_rates = ER.new
5
+ base = ex_rates.rates_at(date.to_s, base)
6
+ other = ex_rates.rates_at(date.to_s, other)
7
7
  other / base
8
8
  end
9
9
 
@@ -16,10 +16,18 @@ module Fafx
16
16
  end
17
17
 
18
18
  def most_recent
19
- er = ER.new
20
- k = er.dates.first
21
- er.rates[k]
19
+ ex_rates = ER.new
20
+ first_date = ex_rates.dates.first
21
+ ex_rates.rates[first_date]
22
22
  end
23
- module_function :at, :currencies_available, :dates_available, :most_recent
23
+
24
+ def fetch_data_and_save_to_disk
25
+ DataFetcher.save_to_disk
26
+ end
27
+ module_function :at,
28
+ :currencies_available,
29
+ :dates_available,
30
+ :most_recent,
31
+ :fetch_data_and_save_to_disk
24
32
  end
25
33
  end
@@ -1,3 +1,3 @@
1
1
  module Fafx
2
- VERSION = '0.1.0'.freeze
2
+ VERSION = '0.1.1'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fafx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Frank Kair
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-11 00:00:00.000000000 Z
11
+ date: 2018-09-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler