mgd_money 0.0.2

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.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/mgd_money.rb +178 -0
  3. metadata +45 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c4c10d10675064445a34fb24ab6efeb6e30146b9
4
+ data.tar.gz: aa2d1e3d3cd53bd2c690b06656e2c8cb44c837fe
5
+ SHA512:
6
+ metadata.gz: 18b054083240cbf6538d0d52f4ddf4ad6192646807ef6b15fbccd55334c5cace2bd64df1c2d0678c070e04722a444f6a1b5bf13e743d7ce64916f234363cd1a6
7
+ data.tar.gz: d961cc6071bf268f2ba391b28d6d9169fc440ea898e4004ad5059fac6f08e413524fc4a4e5a7f2b3e9d1fd6d59d9fabbf13963ea39dc32b3a52ba05369c97fb6
data/lib/mgd_money.rb ADDED
@@ -0,0 +1,178 @@
1
+ class MGDMoney
2
+ include Comparable # for implementing custom comparing methods for MGDMoney objects
3
+
4
+ # initialize the instance variables for the singleton class.
5
+ # this allows the user to configure the desired conversion rates
6
+ # with respect to a base currency
7
+ class << self
8
+ attr_accessor :base_currency, :conversion_factors
9
+ end
10
+
11
+ attr_reader :amount, :currency # each MGDMoney object will have these attributes
12
+
13
+ # instantiate new MGDMoney objects.
14
+ # @param [Numeric] amount, the amount of the given currency
15
+ # @param [String] currency, the user-defined currency string
16
+ # @return [MGDMoney] the resulting MGDMoney object
17
+ # @example fifty_eur = MGDMoney.new(50, 'EUR') #=> 50 EUR
18
+ def initialize(amount, currency)
19
+ unless amount.is_a?(Numeric) # the amount entered wasn't empty, but we still have to make sure it's a number
20
+ raise UnknownObjectError, 'Amount must be a number'
21
+ end
22
+
23
+ if currency.empty?
24
+ raise InvalidDeclarationError, 'Currency must be specified'
25
+ end
26
+
27
+ @amount = amount # input is OK, so set the attributes
28
+ @currency = currency
29
+ end
30
+
31
+ # configure the currency rates on the singleton class with respect to a base currency
32
+ # @param [String] base_currency, the currency used to determine conversion rates
33
+ # @param [Hash] conversion_factors, the conversion rates for supported currencies
34
+ # @return [nil]
35
+ # @example
36
+ # MGDMoney.conversion_rates("EUR", {
37
+ # "USD" => 1.11,
38
+ # "Bitcoin" => 0.0047
39
+ # })
40
+ def self.conversion_rates(base_currency, conversion_factors)
41
+ self.base_currency = base_currency
42
+ self.conversion_factors = conversion_factors
43
+ end
44
+
45
+ # convert to a different currency, returning a new MGDMoney object.
46
+ # requires both source and destination currency to be defined by
47
+ # MGDMoney.conversion_rates (otherwise rate not known)
48
+ # @param [String] currency, the desired currency after conversion
49
+ # @return [MGDMoney] the new MGDMoney object representing the converted currency
50
+ # @example fifty_eur.convert_to('USD') # => 55.50 USD
51
+ def convert_to(currency)
52
+ if currency == self.currency # source and destination currencies match
53
+ self # no conversion needed
54
+ else
55
+ factors = MGDMoney.conversion_factors # get the user-specified conversion rates
56
+
57
+ if self.currency == MGDMoney.base_currency # user specified this currency as the base currency
58
+ if factors.keys.include?(currency) # ensures user did actually specify this conversion
59
+ conversion_factor = factors["#{currency}"] # look up the conversion rate from the Hash
60
+ MGDMoney.new(self.amount*conversion_factor, currency) # return the converted value as a new MGDMoney object
61
+ else # conversion rate wasn't specified, so raise an error
62
+ raise UnknownConversionError, 'Conversion rate not specified for this currency'
63
+ end
64
+ elsif currency == MGDMoney.base_currency # user specified desired currency as the base currency
65
+ if factors.keys.include?(self.currency) # look for the source currency in the user-specified Hash
66
+ conversion_factor = 1 / factors["#{self.currency}"] # if found, invert that b/c the Hash is specified in opposite way
67
+ MGDMoney.new(self.amount*conversion_factor, currency) # return the converted value as a new MGDMoney object
68
+ else # conversion rate wasn't specified, so raise an error
69
+ raise UnknownConversionError, 'Conversion rate not specified for this currency'
70
+ end
71
+ else
72
+ if factors.keys.include?(currency) # neither source nor desired currency are the base currency
73
+ conversion_factor = factors["#{self.currency}"] * factors["#{currency}"] # compare them to each other
74
+ MGDMoney.new(self.amount*conversion_factor, currency) # return the converted value as a new MGDMoney object
75
+ else # conversion rate wasn't specified, so raise an error
76
+ raise UnknownConversionError, 'Conversion rate not specified for this currency'
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ # get amount and currency of MGDMoney object
83
+ # @example
84
+ # fifty_eur.amount => 50
85
+ # fifty_eur.currency => 'EUR'
86
+ # fifty_eur.inspect => "50.00 EUR"
87
+ def amount
88
+ @amount
89
+ end
90
+
91
+ def currency
92
+ @currency
93
+ end
94
+
95
+ # format the default output string format
96
+ def inspect
97
+ "#{(convert_to_float(@amount)).to_s + " " + currency}"
98
+ end
99
+
100
+ # convert the given number to its float representation.
101
+ # this makes all the arithmetic possible
102
+ # @param [Numeric] amount, the amount to convert
103
+ # @return [BigDecimal]
104
+ # @example convert_to_float(twenty_dollars.amount)
105
+ def convert_to_float(amount)
106
+ if amount.to_s.empty? # entered amount was "" (empty string), return 0
107
+ 0
108
+ else
109
+ '%.2f' % amount
110
+ end
111
+ end
112
+
113
+ # perform arithmetic operations in two different currencies
114
+ # @param [MGDMoney] other_object, the MGDMoney object we're doing the operation with
115
+ # @return [MGDMoney]
116
+ # @example fifty_eur + twenty_dollars = 68.02 EUR
117
+ # @example fifty_eur / 2 = 25 EUR
118
+ def +(other_object)
119
+ if other_object.is_a?(MGDMoney)
120
+ other_object = other_object.convert_to(currency)
121
+ self.class.new(amount + other_object.amount, currency)
122
+ else
123
+ raise UnsupportedOperationError, '#{other_object} must be of type MGDMoney to compute a sum'
124
+ end
125
+ end
126
+
127
+ def -(other_object)
128
+ if other_object.is_a?(MGDMoney)
129
+ other_object = other_object.convert_to(currency)
130
+ self.class.new(amount - other_object.amount, currency)
131
+ else
132
+ raise UnsupportedOperationError, '#{other_object} must be of type MGDMoney to compute a difference'
133
+ end
134
+ end
135
+
136
+ def *(val)
137
+ if val.is_a?(Numeric)
138
+ self.class.new(amount * val, currency)
139
+ else
140
+ raise UnsupportedOperationError, 'Can only multiply an MGDMoney object by a number'
141
+ end
142
+ end
143
+
144
+ def /(val)
145
+ if val.is_a?(Numeric)
146
+ self.class.new(amount / val, currency)
147
+ else
148
+ raise UnsupportedOperationError, 'Can only divide an MGDMoney object by a number'
149
+ end
150
+ end
151
+
152
+ # compare different currencies (using Comparable)
153
+ # in this case, we only care about comparing the amounts of each MGDMoney object
154
+ # @param [MGDMoney] other_object, the object to compare to
155
+ # @return [FixNum]
156
+ # @example twenty_dollars == MGDMoney.new(20, 'USD') # => true
157
+ # @example twenty_dollars == MGDMoney.new(30, 'USD') # => false
158
+ # @example fifty_eur_in_usd = fifty_eur.convert_to('USD')
159
+ # @example fifty_eur_in_usd == fifty_eur => true
160
+ def <=>(other_object)
161
+ if other_object.is_a?(MGDMoney)
162
+ other_object = other_object.convert_to(currency)
163
+ amount <=> other_object.amount
164
+ else
165
+ raise UnknownObjectError, 'Unknown destination object type (must be type MGDMoney)'
166
+ end
167
+ end
168
+
169
+ # provide some useful error messages to the user
170
+ class UnknownConversionError < StandardError
171
+ end
172
+
173
+ class UnknownObjectError < StandardError
174
+ end
175
+
176
+ class UnsupportedOperationError < StandardError
177
+ end
178
+ end
metadata ADDED
@@ -0,0 +1,45 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mgd_money
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Matt Davis
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-04-06 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A simple gem to enable conversion and arithmetic operations between different
14
+ currencies
15
+ email: davismattg@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/mgd_money.rb
21
+ homepage: http://www.mattgdavis.com
22
+ licenses:
23
+ - MIT
24
+ metadata: {}
25
+ post_install_message:
26
+ rdoc_options: []
27
+ require_paths:
28
+ - lib
29
+ required_ruby_version: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ required_rubygems_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ requirements: []
40
+ rubyforge_project:
41
+ rubygems_version: 2.0.14.1
42
+ signing_key:
43
+ specification_version: 4
44
+ summary: MGDMoney
45
+ test_files: []