vlatko_dawanda 1.0.1 → 2.0.0
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 +4 -4
- data/lib/vlatko_dawanda/bank.rb +40 -0
- data/lib/vlatko_dawanda/currency.rb +24 -0
- data/lib/vlatko_dawanda/money.rb +18 -32
- data/lib/vlatko_dawanda/version.rb +1 -1
- data/lib/vlatko_dawanda.rb +2 -0
- data/spec/vlatko_dawanda/bank_spec.rb +63 -0
- data/spec/vlatko_dawanda/currency_spec.rb +43 -0
- data/spec/vlatko_dawanda/money_spec.rb +28 -56
- metadata +5 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a4cb467fb704f4094f128b541ca44495c6341334
|
|
4
|
+
data.tar.gz: 3b3b527b160a2a526f36b7ab0a9d85041cd86742
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1b11457a61d48cc3bc772e4a0da2ba5eda39a4bfb14a88da7267a85d5f1054937e53ae47f238ea5c95c32ba4039588f3b8a1887ab7caf3ded402bdcf2a449ff8
|
|
7
|
+
data.tar.gz: 3a0e74e15ca39816c148050cc5eb8b094c39722e2d601c04671b765d7399934bb56141d971f45c238de1ba47c1dad36661144f7bc31bec7fe948bc056abac0ef
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module VlatkoDawanda
|
|
2
|
+
class Bank
|
|
3
|
+
|
|
4
|
+
def conversion_rates(base_currency, currencies)
|
|
5
|
+
@currencies = parse_currencies(base_currency, currencies)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def currencies
|
|
9
|
+
@currencies ||= {}
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def find_currency(search)
|
|
13
|
+
currency = case search
|
|
14
|
+
when ::String, ::Symbol
|
|
15
|
+
currencies[currency_id(search)]
|
|
16
|
+
when Currency
|
|
17
|
+
found = currencies[currency_id(search.iso_code)]
|
|
18
|
+
raise UnknownCurrency.new('currency not matching the rate') unless found == search
|
|
19
|
+
found
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
raise UnknownCurrency.new('currency not found') if currency.nil?
|
|
23
|
+
currency
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def parse_currencies(base_currency, currencies)
|
|
29
|
+
currencies.merge({base_currency => 1}).inject({}) do |memo, (key,value)|
|
|
30
|
+
memo[currency_id(key)] = Currency.new({iso_code: key, rate: value})
|
|
31
|
+
memo
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def currency_id(value)
|
|
36
|
+
value.downcase.to_sym
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module VlatkoDawanda
|
|
2
|
+
class Currency
|
|
3
|
+
include Comparable
|
|
4
|
+
|
|
5
|
+
attr_reader :iso_code, :rate
|
|
6
|
+
|
|
7
|
+
def initialize(options = {})
|
|
8
|
+
@iso_code = options[:iso_code]
|
|
9
|
+
@rate = validate_rate(options[:rate])
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def <=>(other)
|
|
13
|
+
rate <=> other.rate
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def validate_rate(value)
|
|
19
|
+
rate = value.to_d rescue 0.to_d
|
|
20
|
+
raise InvalidRate.new('please enter a positive float or integer as a rate') if rate <= 0
|
|
21
|
+
rate
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
data/lib/vlatko_dawanda/money.rb
CHANGED
|
@@ -5,37 +5,20 @@ module VlatkoDawanda
|
|
|
5
5
|
include Comparable
|
|
6
6
|
|
|
7
7
|
class << self
|
|
8
|
-
|
|
9
|
-
@currencies = parse_currencies(base_currency, currencies)
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def currencies
|
|
13
|
-
@currencies ||= {}
|
|
14
|
-
end
|
|
8
|
+
attr_writer :bank
|
|
15
9
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
# I'm doing this instead of simple merge with the input hash
|
|
19
|
-
# cause I prefer working with symbols as keys whenever possible
|
|
20
|
-
# and the garbage collector is not that polluted
|
|
21
|
-
def parse_currencies(base_currency, currencies)
|
|
22
|
-
currencies.merge({base_currency => 1}).inject({}) do |memo, (key,value)|
|
|
23
|
-
rate = validate_rate(value)
|
|
24
|
-
memo[key.downcase.to_sym] = {iso_code: key, rate: rate}
|
|
25
|
-
memo
|
|
26
|
-
end
|
|
10
|
+
def bank
|
|
11
|
+
@bank ||= Bank.new
|
|
27
12
|
end
|
|
28
13
|
|
|
29
|
-
def
|
|
30
|
-
|
|
31
|
-
raise InvalidRate.new('please enter a positive float as a rate') if rate <= 0
|
|
32
|
-
rate
|
|
14
|
+
def conversion_rates(base_currency, currencies)
|
|
15
|
+
bank.conversion_rates(base_currency, currencies)
|
|
33
16
|
end
|
|
34
17
|
end
|
|
35
18
|
|
|
36
19
|
def initialize(amount, iso_code)
|
|
37
20
|
@amount = amount.to_d
|
|
38
|
-
@currency = find_currency(iso_code)
|
|
21
|
+
@currency = bank.find_currency(iso_code)
|
|
39
22
|
end
|
|
40
23
|
|
|
41
24
|
def amount
|
|
@@ -43,16 +26,21 @@ module VlatkoDawanda
|
|
|
43
26
|
end
|
|
44
27
|
|
|
45
28
|
def currency
|
|
46
|
-
@currency
|
|
29
|
+
@currency.iso_code
|
|
47
30
|
end
|
|
48
31
|
|
|
49
32
|
def inspect
|
|
50
33
|
"#{"%.2f" % amount} #{currency}"
|
|
51
34
|
end
|
|
52
35
|
|
|
53
|
-
def convert_to(
|
|
54
|
-
|
|
55
|
-
|
|
36
|
+
def convert_to(currency)
|
|
37
|
+
to_currency = bank.find_currency(currency)
|
|
38
|
+
amount = if @currency == to_currency
|
|
39
|
+
@amount
|
|
40
|
+
else
|
|
41
|
+
(@amount / @currency.rate) * to_currency.rate
|
|
42
|
+
end
|
|
43
|
+
self.class.new(amount, to_currency.iso_code)
|
|
56
44
|
end
|
|
57
45
|
|
|
58
46
|
def <=>(other)
|
|
@@ -65,10 +53,8 @@ module VlatkoDawanda
|
|
|
65
53
|
|
|
66
54
|
private
|
|
67
55
|
|
|
68
|
-
def
|
|
69
|
-
|
|
70
|
-
raise UnknownCurrency.new('currency not found') if currency.nil?
|
|
71
|
-
currency
|
|
56
|
+
def bank
|
|
57
|
+
self.class.bank
|
|
72
58
|
end
|
|
73
59
|
|
|
74
60
|
def to_f_or_i(v)
|
|
@@ -76,4 +62,4 @@ module VlatkoDawanda
|
|
|
76
62
|
end
|
|
77
63
|
|
|
78
64
|
end
|
|
79
|
-
end
|
|
65
|
+
end
|
data/lib/vlatko_dawanda.rb
CHANGED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe VlatkoDawanda::Bank do
|
|
4
|
+
it 'has currencies attribute that is a dictionary hash' do
|
|
5
|
+
expect(subject).to respond_to(:currencies)
|
|
6
|
+
expect(subject.currencies).to be_an_instance_of Hash
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
context 'conversion rates' do
|
|
10
|
+
before(:example) do
|
|
11
|
+
subject.conversion_rates('EUR', {'USD' => 1.11, 'Bitcoin' => 0.0047})
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'parses all the currencies values into Currency objects' do
|
|
15
|
+
expect(subject.currencies.values).to all(be_an_instance_of(VlatkoDawanda::Currency))
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'parses all the currencies keys to symbols of downcased iso codes' do
|
|
19
|
+
expect(subject.currencies.keys).to contain_exactly(:eur,:usd,:bitcoin)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'parses the base currency with rate 1' do
|
|
23
|
+
expect(subject.currencies[:eur].rate).to eq 1
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
context 'find currency' do
|
|
28
|
+
before(:example) do
|
|
29
|
+
subject.conversion_rates('EUR', {'USD' => 1.11, 'Bitcoin' => 0.0047})
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
let(:currency_by_iso_code){subject.find_currency('Bitcoin')}
|
|
33
|
+
|
|
34
|
+
context 'by iso code' do
|
|
35
|
+
it 'returns the approriate Currency object if the iso code is registered' do
|
|
36
|
+
expect(currency_by_iso_code).to be_an_instance_of(VlatkoDawanda::Currency)
|
|
37
|
+
expect(currency_by_iso_code.iso_code).to eq 'Bitcoin'
|
|
38
|
+
expect(currency_by_iso_code.rate).to eq 0.0047
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'raises an error when currency is not found' do
|
|
42
|
+
expect{subject.find_currency('MKD')}.to raise_error VlatkoDawanda::UnknownCurrency
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context 'by currency object' do
|
|
47
|
+
let(:currency_by_object){subject.find_currency(currency_by_iso_code)}
|
|
48
|
+
|
|
49
|
+
it 'returns the approriate Currency object if the iso code is registered' do
|
|
50
|
+
expect(currency_by_object).to be_an_instance_of(VlatkoDawanda::Currency)
|
|
51
|
+
expect(currency_by_object.iso_code).to eq 'Bitcoin'
|
|
52
|
+
expect(currency_by_object.rate).to eq 0.0047
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it 'raises an error when currency is not found' do
|
|
56
|
+
invalid_currency = currency_by_object.instance_variable_set('@rate', currency_by_object.rate + 1)
|
|
57
|
+
expect{subject.find_currency(invalid_currency)}.to raise_error VlatkoDawanda::UnknownCurrency
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe VlatkoDawanda::Currency do
|
|
4
|
+
let(:currency){described_class.new({iso_code: 'EUR', rate: rand(0.1..5.0)})}
|
|
5
|
+
let(:invalid_currency){described_class.new({iso_code: 'USD', rate: rand(-5.0..0)})}
|
|
6
|
+
|
|
7
|
+
context 'valid' do
|
|
8
|
+
specify 'to have rate' do
|
|
9
|
+
expect(currency).to respond_to(:rate)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
specify 'to have iso_code' do
|
|
13
|
+
expect(currency).to respond_to(:iso_code)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
specify 'when the rate is a positive float or integer' do
|
|
17
|
+
expect{currency}.to_not raise_error(VlatkoDawanda::InvalidRate)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
specify 'rate is BigDecimal' do
|
|
21
|
+
expect(currency.rate).to be_an_instance_of(BigDecimal)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
context 'invalid' do
|
|
26
|
+
specify 'when the rate is not a positive float or integer' do
|
|
27
|
+
expect{invalid_currency}.to raise_error(VlatkoDawanda::InvalidRate)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
context 'comparable' do
|
|
32
|
+
let(:equal_currency){currency.dup}
|
|
33
|
+
it 'should be equal if the rate of the other is equal' do
|
|
34
|
+
expect(currency).to eq equal_currency
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'should not equal if the rate of the other is different' do
|
|
38
|
+
diff_currency = described_class.new({iso_code: equal_currency.iso_code, rate: equal_currency.rate + 1 })
|
|
39
|
+
|
|
40
|
+
expect(currency).to_not eq diff_currency
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -1,88 +1,61 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
describe VlatkoDawanda::Money do
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
it 'includes the right currencies from input' do
|
|
10
|
-
expect(currencies.keys).to contain_exactly(:eur, :usd, :bitcoin)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
it 'does not include a currency that is not in the input' do
|
|
14
|
-
expect(currencies.keys).to_not include(:mkd)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
context 'raises an InvalidRate' do
|
|
18
|
-
specify 'rate is zero' do
|
|
19
|
-
invalid_hash = {'MKD' => 0}
|
|
20
|
-
expect{described_class.conversion_rates('EUR', invalid_hash)}.to raise_error VlatkoDawanda::InvalidRate
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
specify 'rate is negative number' do
|
|
24
|
-
invalid_hash = {'MKD' => -1}
|
|
25
|
-
expect{described_class.conversion_rates('EUR', invalid_hash)}.to raise_error VlatkoDawanda::InvalidRate
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
it 'parses the base currency with rate 1' do
|
|
30
|
-
expect(currencies[:eur][:rate]).to eq 1
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
it 'parses the currencies with bigdecimal classes' do
|
|
34
|
-
expect(currencies.map{|k,v| v[:rate]}).to all(be_an_instance_of(BigDecimal))
|
|
4
|
+
context 'bank' do
|
|
5
|
+
it 'is configurable for all money objects' do
|
|
6
|
+
expect(described_class).to respond_to(:bank=)
|
|
7
|
+
expect(described_class).to respond_to(:bank)
|
|
35
8
|
end
|
|
36
9
|
|
|
37
|
-
|
|
38
|
-
expect(
|
|
39
|
-
expect(currencies[:bitcoin][:rate]).to eq hash_currency_input[currencies[:bitcoin][:iso_code]]
|
|
10
|
+
specify 'its default bank to be the Bank class' do
|
|
11
|
+
expect(described_class.bank).to be_an_instance_of(VlatkoDawanda::Bank)
|
|
40
12
|
end
|
|
41
13
|
end
|
|
42
14
|
|
|
43
|
-
context '
|
|
15
|
+
context 'instantiate an object' do
|
|
44
16
|
before(:context) do
|
|
45
17
|
described_class.conversion_rates('EUR', {'USD' => 1.11, 'Bitcoin' => 0.0047})
|
|
46
18
|
end
|
|
47
19
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
end
|
|
20
|
+
context 'validation' do
|
|
21
|
+
specify 'when the currency is registered' do
|
|
22
|
+
euro = described_class.new(50, 'USD')
|
|
23
|
+
expect{euro}.to_not raise_error VlatkoDawanda::UnknownCurrency
|
|
24
|
+
expect(euro.instance_variable_get('@currency')).to be_an_instance_of(VlatkoDawanda::Currency)
|
|
25
|
+
end
|
|
55
26
|
|
|
56
|
-
|
|
57
|
-
|
|
27
|
+
it 'raises UnknownCurrency error when the currency is not registered' do
|
|
28
|
+
expect{described_class.new(50, 'MKD')}.to raise_error VlatkoDawanda::UnknownCurrency
|
|
29
|
+
end
|
|
58
30
|
end
|
|
59
31
|
|
|
60
|
-
context '
|
|
32
|
+
context 'parsed outputs for attributes' do
|
|
33
|
+
let(:existing_currency){described_class.new(50, 'EUR')}
|
|
34
|
+
let(:float_currency){described_class.new(50.50, 'USD')}
|
|
61
35
|
|
|
62
|
-
it 'outputs the amount in integer when
|
|
36
|
+
it 'outputs the amount in integer when integer input' do
|
|
63
37
|
expect(existing_currency.amount).to eq 50
|
|
64
38
|
expect(existing_currency.amount).to be_an(Integer)
|
|
65
39
|
end
|
|
66
40
|
|
|
67
|
-
it 'outputs the amount in float when
|
|
41
|
+
it 'outputs the amount in float when float input' do
|
|
68
42
|
expect(float_currency.amount).to eq 50.50
|
|
69
43
|
expect(float_currency.amount).to be_an(Float)
|
|
70
44
|
end
|
|
71
45
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
expect(existing_currency.currency).to eq 'EUR'
|
|
76
|
-
end
|
|
46
|
+
it 'outputs iso code for currency' do
|
|
47
|
+
expect(existing_currency.currency).to eq 'EUR'
|
|
48
|
+
end
|
|
77
49
|
|
|
78
|
-
|
|
79
|
-
|
|
50
|
+
it 'outputs the amount and currency iso code when inspected' do
|
|
51
|
+
expect(existing_currency.inspect).to eq "50.00 EUR"
|
|
52
|
+
end
|
|
80
53
|
end
|
|
81
54
|
end
|
|
82
55
|
|
|
83
56
|
context 'conversion to different currency' do
|
|
84
57
|
before(:context) do
|
|
85
|
-
|
|
58
|
+
described_class.conversion_rates('EUR', {'USD' => 1.11, 'Bitcoin' => 0.0047})
|
|
86
59
|
end
|
|
87
60
|
|
|
88
61
|
let(:euro){described_class.new(50,'EUR')}
|
|
@@ -137,5 +110,4 @@ describe VlatkoDawanda::Money do
|
|
|
137
110
|
expect(twenty_usd).to be < fifty_eur
|
|
138
111
|
end
|
|
139
112
|
end
|
|
140
|
-
|
|
141
113
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: vlatko_dawanda
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 2.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Vlatko Ristovski
|
|
@@ -85,11 +85,15 @@ files:
|
|
|
85
85
|
- bin/setup
|
|
86
86
|
- lib/vlatko_dawanda.rb
|
|
87
87
|
- lib/vlatko_dawanda/arithmetic.rb
|
|
88
|
+
- lib/vlatko_dawanda/bank.rb
|
|
89
|
+
- lib/vlatko_dawanda/currency.rb
|
|
88
90
|
- lib/vlatko_dawanda/error_classes.rb
|
|
89
91
|
- lib/vlatko_dawanda/money.rb
|
|
90
92
|
- lib/vlatko_dawanda/version.rb
|
|
91
93
|
- spec/spec_helper.rb
|
|
92
94
|
- spec/vlatko_dawanda/arithmetic_spec.rb
|
|
95
|
+
- spec/vlatko_dawanda/bank_spec.rb
|
|
96
|
+
- spec/vlatko_dawanda/currency_spec.rb
|
|
93
97
|
- spec/vlatko_dawanda/money_spec.rb
|
|
94
98
|
- spec/vlatko_dawanda_spec.rb
|
|
95
99
|
- vlatko_dawanda.gemspec
|