custom_currency 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/bank/custom_currency.rb +100 -0
- data/lib/rates_store/data_support.rb +60 -0
- metadata +60 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0b72dd400d3130ffd71a28334e87e94f64f4f7ef
|
4
|
+
data.tar.gz: 9b84dbbfed117f25d67237144175a8b101904dc7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d3d2d72bc9ddba2213992a86776f4b0e7d27f104b4edbcfbf1953c868fbf766e983fcb6bb8644fe8620fc7549ec0f475c4862ba8cb0269bbd4f80b72fe26e2ee
|
7
|
+
data.tar.gz: 12850c710164c0923984d493a2bcb02317dbca82fe5bbf127f19c6f2e4b0b72efe876cc181381f52ba9dd7fd2271743af21b788b8b94f2e2c2a7539020af3621
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'money'
|
2
|
+
require 'money/rates_store/data_support'
|
3
|
+
require 'open-uri'
|
4
|
+
|
5
|
+
class Money
|
6
|
+
module Bank
|
7
|
+
class CustomCurrency < Money::Bank::VariableExchange
|
8
|
+
ECB_RATES_URL = 'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml'.freeze
|
9
|
+
GOOGLE_RATES_URL = 'finance.google.com'.freeze
|
10
|
+
GOOGLE_RATES_PATH = '/finance/converter'.freeze
|
11
|
+
YAHOO_RATES_URL = 'download.finance.yahoo.com'.freeze
|
12
|
+
YAHOO_RATES_PATH = '/d/quotes.csv'.freeze
|
13
|
+
|
14
|
+
def initialize(*)
|
15
|
+
super
|
16
|
+
@store.extend Money::RatesStore::DataSupport
|
17
|
+
@currency_string = nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_rate(from, to)
|
21
|
+
from_iso_code = from.is_a?(Money::Currency) ? from.iso_code : from.to_s
|
22
|
+
to_iso_code = to.is_a?(Money::Currency) ? to.iso_code : to.to_s
|
23
|
+
|
24
|
+
g_rate = google_rate(from_iso_code, to_iso_code)
|
25
|
+
y_rate = yahoo_rate(from_iso_code, to_iso_code)
|
26
|
+
# We don't use euc_rate, I just leave this here
|
27
|
+
# because someday we can change to
|
28
|
+
# euc_rate = eu_central_rate(from, to)
|
29
|
+
g_rate ? g_rate : y_rate
|
30
|
+
end
|
31
|
+
|
32
|
+
def save_rates(cache, url = ECB_RATES_URL)
|
33
|
+
raise InvalidCache unless cache
|
34
|
+
File.open(cache, 'w') do |file|
|
35
|
+
io = open(url)
|
36
|
+
io.each_line { |line| file.puts line }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def update_rates(cache, url = ECB_RATES_URL)
|
41
|
+
rates_source = cache.nil? ? url : cache
|
42
|
+
rates = Nokogiri::XML(open(rates_source)).
|
43
|
+
xpath('gesmes:Envelope/xmlns:Cube/xmlns:Cube//xmlns:Cube')
|
44
|
+
|
45
|
+
store.transaction true do
|
46
|
+
rates.each do |exchange_rate|
|
47
|
+
rate = BigDecimal(exchange_rate.attribute('rate').value)
|
48
|
+
currency = exchange_rate.attribute('currency').value
|
49
|
+
set_rate('EUR', currency, rate)
|
50
|
+
end
|
51
|
+
set_rate('EUR', 'EUR', 1)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def google_rate(from, to)
|
58
|
+
query = "a=1&from=#{from}&to=#{to}"
|
59
|
+
uri = build_uri(GOOGLE_RATES_URL, GOOGLE_RATES_PATH, query)
|
60
|
+
rate = extract_rate(uri.read)
|
61
|
+
rate = (1 / extract_rate(uri.read)) if rate < 0.1
|
62
|
+
|
63
|
+
rate
|
64
|
+
rescue => ex
|
65
|
+
Logger.new(STDOUT).error("[CurrencyExchange][GOOGLE] #{ex.message}")
|
66
|
+
return nil
|
67
|
+
end
|
68
|
+
|
69
|
+
def yahoo_rate(from, to)
|
70
|
+
query = "s=#{from}#{to}=X&f=l1"
|
71
|
+
uri = build_uri(YAHOO_RATES_URL, YAHOO_RATES_PATH, query)
|
72
|
+
|
73
|
+
uri.read.to_d
|
74
|
+
rescue => ex
|
75
|
+
Logger.new(STDOUT).error("[CurrencyExchange][YAHOO] #{ex.message}")
|
76
|
+
return nil
|
77
|
+
end
|
78
|
+
|
79
|
+
def eu_central_rate(from, to)
|
80
|
+
from_base_rate = store.get_rate('EUR', from)
|
81
|
+
to_base_rate = store.get_rate('EUR', to)
|
82
|
+
|
83
|
+
to_base_rate / from_base_rate
|
84
|
+
end
|
85
|
+
|
86
|
+
def build_uri(url, path, query)
|
87
|
+
URI::HTTP.build(host: url, path: path, query: query)
|
88
|
+
end
|
89
|
+
|
90
|
+
def extract_rate(data)
|
91
|
+
case data
|
92
|
+
when %r{<span class=bld>(\d+\.?\d*) [A-Z]{3}<\/span}
|
93
|
+
BigDecimal(Regexp.last_match(1))
|
94
|
+
when /Could not convert\./
|
95
|
+
raise UnknownRate
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
class Money
|
2
|
+
module RatesStore
|
3
|
+
module DataSupport
|
4
|
+
INDEX_DATE_SEPARATOR = '_AT_'.freeze
|
5
|
+
|
6
|
+
def add_rate(currency_iso_from, currency_iso_to, rate, date = nil)
|
7
|
+
transaction do
|
8
|
+
index[rate_key_for(currency_iso_from, currency_iso_to, date)] = rate
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_rate(currency_iso_from, currency_iso_to, date = nil)
|
13
|
+
transaction do
|
14
|
+
index[rate_key_for(currency_iso_from, currency_iso_to, date)]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def transaction(force_sync = false, &block)
|
19
|
+
if @mutex.respond_to?(:owned?)
|
20
|
+
force_sync = false if @mutex.locked? && @mutex.owned?
|
21
|
+
else
|
22
|
+
force_sync = false
|
23
|
+
end
|
24
|
+
|
25
|
+
if !force_sync && (@in_transaction || options[:without_mutex])
|
26
|
+
yield self
|
27
|
+
else
|
28
|
+
@mutex.synchronize do
|
29
|
+
@in_transaction = true
|
30
|
+
result = yield
|
31
|
+
@in_transaction = false
|
32
|
+
result
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def each_rate(&block)
|
38
|
+
enum = Enumerator.new do |yielder|
|
39
|
+
index.each do |key, rate|
|
40
|
+
iso_from, iso_to = key.split(Memory::INDEX_KEY_SEPARATOR)
|
41
|
+
iso_to, date = iso_to.split(INDEX_DATE_SEPARATOR)
|
42
|
+
date = Date.parse(date) if date
|
43
|
+
yielder.yield iso_from, iso_to, rate, date
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
block_given? ? enum.each(&block) : enum
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def rate_key_for(currency_iso_from, currency_iso_to, date = nil)
|
53
|
+
key = [currency_iso_from, currency_iso_to].
|
54
|
+
join(Memory::INDEX_KEY_SEPARATOR)
|
55
|
+
key = [key, date.to_s].join(INDEX_DATE_SEPARATOR) if date
|
56
|
+
key.upcase
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
metadata
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: custom_currency
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Giordano Alves
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-10-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: money
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '6.7'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '6.7'
|
27
|
+
description: Extends Money::Bank::VariableExchange and gives you access to the current
|
28
|
+
exchange rates of various providers
|
29
|
+
email: giordanofalves@gmail.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- lib/bank/custom_currency.rb
|
35
|
+
- lib/rates_store/data_support.rb
|
36
|
+
homepage: https://github.com/giordanofalves/custom_currency
|
37
|
+
licenses:
|
38
|
+
- MIT
|
39
|
+
metadata: {}
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
requirements: []
|
55
|
+
rubyforge_project:
|
56
|
+
rubygems_version: 2.2.2
|
57
|
+
signing_key:
|
58
|
+
specification_version: 4
|
59
|
+
summary: Custom Currency!
|
60
|
+
test_files: []
|