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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 83997f221c62c400d5001080e4e48c18e363ad3b
4
- data.tar.gz: 892766a23ef320afc209b67ea20ca455c2f6fa00
3
+ metadata.gz: a4cb467fb704f4094f128b541ca44495c6341334
4
+ data.tar.gz: 3b3b527b160a2a526f36b7ab0a9d85041cd86742
5
5
  SHA512:
6
- metadata.gz: 89a873e3f7f92ecbd8b89a2e9a8f02bc464b6434944c155b9aabdae284c83ec12fab024fb613c369fbaac73133c688c8c93b5e6c216c045e430777b5411e5b72
7
- data.tar.gz: 66a0b0af4c780900e7d6b67a3e0b704bbbeeb0e5a9997226fadc168e730fad0e8a5f62427076a32a23877eed47bab35625da456e8426396a231c50db1dfa1f56
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
@@ -5,37 +5,20 @@ module VlatkoDawanda
5
5
  include Comparable
6
6
 
7
7
  class << self
8
- def conversion_rates(base_currency, currencies)
9
- @currencies = parse_currencies(base_currency, currencies)
10
- end
11
-
12
- def currencies
13
- @currencies ||= {}
14
- end
8
+ attr_writer :bank
15
9
 
16
- private
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 validate_rate(value)
30
- rate = value.to_d rescue 0.to_d
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[:iso_code]
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(iso_code)
54
- amount = (@amount / @currency[:rate]) * find_currency(iso_code)[:rate]
55
- self.class.new(amount, iso_code)
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 find_currency(iso_code)
69
- currency = self.class.currencies[iso_code.downcase.to_sym]
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
@@ -1,3 +1,3 @@
1
1
  module VlatkoDawanda
2
- VERSION = "1.0.1"
2
+ VERSION = "2.0.0"
3
3
  end
@@ -3,6 +3,8 @@ require "bigdecimal/util"
3
3
  require "vlatko_dawanda/version"
4
4
  require 'vlatko_dawanda/error_classes'
5
5
  require 'vlatko_dawanda/arithmetic'
6
+ require 'vlatko_dawanda/currency'
7
+ require 'vlatko_dawanda/bank'
6
8
  require 'vlatko_dawanda/money'
7
9
 
8
10
  begin
@@ -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
- context '#conversion_rates parsing' do
6
- let(:hash_currency_input){{'USD' => 1.11, 'Bitcoin' => 0.0047}}
7
- let(:currencies){described_class.conversion_rates('EUR', hash_currency_input)}
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
- it 'equals the same rates as the input hash' do
38
- expect(currencies[:usd][:rate]).to eq hash_currency_input[currencies[:usd][:iso_code]]
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 'instantation of objects' do
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
- let(:existing_currency){described_class.new(50, 'EUR')}
49
- let(:non_existing_currency){described_class.new(50, 'MKD')}
50
- let(:float_currency){described_class.new(50.50, 'USD')}
51
-
52
- it 'is valid when existing currency is in input' do
53
- expect{ existing_currency }.to_not raise_error VlatkoDawanda::UnknownCurrency
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
- it 'is raises UnknownCurrency error when non existing currency is in input' do
57
- expect{ non_existing_currency }.to raise_error VlatkoDawanda::UnknownCurrency
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 'depending of the amount input' do
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 50' do
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 50.50' do
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
- end
73
-
74
- it 'outputs iso code for currency' do
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
- it 'outputs the amount and currency iso code when inspected' do
79
- expect(existing_currency.inspect).to eq "50.00 EUR"
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
- @currencies = described_class.conversion_rates('EUR', {'USD' => 1.11, 'Bitcoin' => 0.0047})
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: 1.0.1
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