custom_currency 0.0.1

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