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 +4 -4
- data/README.md +34 -27
- data/Rakefile +2 -1
- data/bin/fafx +18 -7
- data/fafx.gemspec +1 -13
- data/lib/fafx/data_fetcher.rb +19 -22
- data/lib/fafx/er.rb +18 -22
- data/lib/fafx/exchange_rate.rb +15 -7
- data/lib/fafx/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 00740a9067c4044fd55665b0c61059c090cb1657
|
4
|
+
data.tar.gz: 61dc5c53fc2d376d850efe43e3397d43f5ab6be5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
-
|
7
|
+
## Installation
|
8
8
|
|
9
|
-
|
9
|
+
$ gem install fafx
|
10
10
|
|
11
|
-
|
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
|
-
|
23
|
+
## Example of client usage
|
22
24
|
|
23
25
|
```ruby
|
24
26
|
require 'Date'
|
25
27
|
require 'fafx'
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
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
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
-
|
45
|
-
2018-09-06
|
46
|
-
2018-09-05
|
47
|
-
2018-09-04
|
48
|
-
...
|
50
|
+
$ rake update_data
|
49
51
|
|
50
|
-
|
52
|
+
```ruby
|
53
|
+
require 'fafx'
|
54
|
+
|
55
|
+
Fafx::ExchangeRate.fetch_data_and_save_to_disk
|
51
56
|
```
|
52
57
|
|
53
|
-
|
58
|
+
---
|
54
59
|
|
55
|
-
|
60
|
+
One can also schedule a **cron job** (the following example fetches the data every minute):
|
56
61
|
|
57
|
-
|
62
|
+
```
|
63
|
+
* * * * * . ~/.zshrc; fafx -u
|
64
|
+
```
|
58
65
|
|
59
|
-
|
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
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
|
-
|
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')
|
11
|
-
|
12
|
-
|
13
|
-
opt.on('--
|
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::
|
39
|
+
Fafx::ExchangeRate.fetch_data_and_save_to_disk
|
40
|
+
puts 'Exchange rates data updated!'
|
30
41
|
end
|
31
42
|
end
|
32
|
-
rescue
|
43
|
+
rescue StandardError => e
|
33
44
|
puts e.to_s unless e.message == 'exit'
|
34
45
|
end
|
data/fafx.gemspec
CHANGED
@@ -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 =
|
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
|
|
data/lib/fafx/data_fetcher.rb
CHANGED
@@ -1,31 +1,28 @@
|
|
1
1
|
require 'open-uri'
|
2
2
|
require 'nokogiri'
|
3
3
|
|
4
|
-
module
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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
|
-
|
13
|
+
private
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
data/lib/fafx/er.rb
CHANGED
@@ -1,29 +1,25 @@
|
|
1
1
|
require 'yaml'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
-
|
18
|
+
private
|
21
19
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
data/lib/fafx/exchange_rate.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
module Fafx
|
2
2
|
module ExchangeRate
|
3
3
|
def at(date, base, other)
|
4
|
-
|
5
|
-
base =
|
6
|
-
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
|
-
|
20
|
-
|
21
|
-
|
19
|
+
ex_rates = ER.new
|
20
|
+
first_date = ex_rates.dates.first
|
21
|
+
ex_rates.rates[first_date]
|
22
22
|
end
|
23
|
-
|
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
|
data/lib/fafx/version.rb
CHANGED
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.
|
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
|
+
date: 2018-09-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|