custom_currency 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|