money 4.0.1 → 4.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,246 +1,257 @@
1
- class Money
2
- module Arithmetic
3
-
4
- # Checks whether two money objects have the same currency and the same
5
- # amount. Checks against money objects with a different currency and checks
6
- # against objects that do not respond to #to_money will always return false.
7
- #
8
- # @param [Money] other_money Value to compare with.
9
- #
10
- # @return [Boolean]
11
- #
12
- # @example
13
- # Money.new(100) == Money.new(101) #=> false
14
- # Money.new(100) == Money.new(100) #=> true
15
- def ==(other_money)
16
- if other_money.respond_to?(:to_money)
17
- other_money = other_money.to_money
18
- cents == other_money.cents && self.currency == other_money.currency
19
- else
20
- false
21
- end
22
- end
23
-
24
- # Synonymous with +#==+.
25
- #
26
- # @param [Money] other_money Value to compare with.
27
- #
28
- # @return [Money]
29
- #
30
- # @see #==
31
- def eql?(other_money)
32
- self == other_money
33
- end
34
-
35
- def <=>(other_money)
36
- if other_money.respond_to?(:to_money)
37
- other_money = other_money.to_money
38
- if self.currency == other_money.currency
39
- cents <=> other_money.cents
40
- else
41
- cents <=> other_money.exchange_to(currency).cents
42
- end
43
- else
44
- raise ArgumentError, "Comparison of #{self.class} with #{other_money.inspect} failed"
45
- end
46
- end
47
-
48
- # Returns a new Money object containing the sum of the two operands' monetary
49
- # values. If +other_money+ has a different currency then its monetary value
50
- # is automatically exchanged to this object's currency using +exchange_to+.
51
- #
52
- # @param [Money] other_money Other +Money+ object to add.
53
- #
54
- # @return [Money]
55
- #
56
- # @example
57
- # Money.new(100) + Money.new(100) #=> #<Money @cents=200>
58
- def +(other_money)
59
- if currency == other_money.currency
60
- Money.new(cents + other_money.cents, other_money.currency)
61
- else
62
- Money.new(cents + other_money.exchange_to(currency).cents, currency)
63
- end
64
- end
65
-
66
- # Returns a new Money object containing the difference between the two
67
- # operands' monetary values. If +other_money+ has a different currency then
68
- # its monetary value is automatically exchanged to this object's currency
69
- # using +exchange_to+.
70
- #
71
- # @param [Money] other_money Other +Money+ object to subtract.
72
- #
73
- # @return [Money]
74
- #
75
- # @example
76
- # Money.new(100) - Money.new(99) #=> #<Money @cents=1>
77
- def -(other_money)
78
- if currency == other_money.currency
79
- Money.new(cents - other_money.cents, other_money.currency)
80
- else
81
- Money.new(cents - other_money.exchange_to(currency).cents, currency)
82
- end
83
- end
84
-
85
- # Multiplies the monetary value with the given number and returns a new
86
- # +Money+ object with this monetary value and the same currency.
87
- #
88
- # Note that you can't multiply a Money object by an other +Money+ object.
89
- #
90
- # @param [Numeric] value Number to multiply by.
91
- #
92
- # @return [Money] The resulting money.
93
- #
94
- # @raise [ArgumentError] If +value+ is a Money instance.
95
- #
96
- # @example
97
- # Money.new(100) * 2 #=> #<Money @cents=200>
98
- #
99
- def *(value)
100
- if value.is_a?(Money)
101
- raise ArgumentError, "Can't multiply a Money by a Money"
102
- else
103
- Money.new(cents * value, currency)
104
- end
105
- end
106
-
107
- # Divides the monetary value with the given number and returns a new +Money+
108
- # object with this monetary value and the same currency.
109
- # Can also divide by another +Money+ object to get a ratio.
110
- #
111
- # +Money/Numeric+ returns +Money+. +Money/Money+ returns +Float+.
112
- #
113
- # @param [Money, Numeric] value Number to divide by.
114
- #
115
- # @return [Money] The resulting money if you divide Money by a number.
116
- # @return [Float] The resulting number if you divide Money by a Money.
117
- #
118
- # @example
119
- # Money.new(100) / 10 #=> #<Money @cents=10>
120
- # Money.new(100) / Money.new(10) #=> 10.0
121
- #
122
- def /(value)
123
- if value.is_a?(Money)
124
- if currency == value.currency
125
- (cents / BigDecimal.new(value.cents.to_s)).to_f
126
- else
127
- (cents / BigDecimal(value.exchange_to(currency).cents.to_s)).to_f
128
- end
129
- else
130
- Money.new(cents / value, currency)
131
- end
132
- end
133
-
134
- # Synonym for +#/+.
135
- #
136
- # @param [Money, Numeric] value Number to divide by.
137
- #
138
- # @return [Money] The resulting money if you divide Money by a number.
139
- # @return [Float] The resulting number if you divide Money by a Money.
140
- #
141
- # @see #/
142
- #
143
- def div(value)
144
- self / value
145
- end
146
-
147
- # Divide money by money or fixnum and return array containing quotient and
148
- # modulus.
149
- #
150
- # @param [Money, Fixnum] val Number to divmod by.
151
- #
152
- # @return [Array<Money,Money>,Array<Fixnum,Money>]
153
- #
154
- # @example
155
- # Money.new(100).divmod(9) #=> [#<Money @cents=11>, #<Money @cents=1>]
156
- # Money.new(100).divmod(Money.new(9)) #=> [11, #<Money @cents=1>]
157
- def divmod(val)
158
- if val.is_a?(Money)
159
- a = self.cents
160
- b = self.currency == val.currency ? val.cents : val.exchange_to(self.currency).cents
161
- q, m = a.divmod(b)
162
- return [q, Money.new(m, self.currency)]
163
- else
164
- return [self.div(val), Money.new(self.cents.modulo(val), self.currency)]
165
- end
166
- end
167
-
168
- # Equivalent to +self.divmod(val)[1]+
169
- #
170
- # @param [Money, Fixnum] val Number take modulo with.
171
- #
172
- # @return [Money]
173
- #
174
- # @example
175
- # Money.new(100).modulo(9) #=> #<Money @cents=1>
176
- # Money.new(100).modulo(Money.new(9)) #=> #<Money @cents=1>
177
- def modulo(val)
178
- self.divmod(val)[1]
179
- end
180
-
181
- # Synonym for +#modulo+.
182
- #
183
- # @param [Money, Fixnum] val Number take modulo with.
184
- #
185
- # @return [Money]
186
- #
187
- # @see #modulo
188
- def %(val)
189
- self.modulo(val)
190
- end
191
-
192
- # If different signs +self.modulo(val) - val+ otherwise +self.modulo(val)+
193
- #
194
- # @param [Money, Fixnum] val Number to rake remainder with.
195
- #
196
- # @return [Money]
197
- #
198
- # @example
199
- # Money.new(100).remainder(9) #=> #<Money @cents=1>
200
- def remainder(val)
201
- a, b = self, val
202
- b = b.exchange_to(a.currency) if b.is_a?(Money) and a.currency != b.currency
203
-
204
- a_sign, b_sign = :pos, :pos
205
- a_sign = :neg if a.cents < 0
206
- b_sign = :neg if (b.is_a?(Money) and b.cents < 0) or (b < 0)
207
-
208
- return a.modulo(b) if a_sign == b_sign
209
- a.modulo(b) - (b.is_a?(Money) ? b : Money.new(b, a.currency))
210
- end
211
-
212
- # Return absolute value of self as a new Money object.
213
- #
214
- # @return [Money]
215
- #
216
- # @example
217
- # Money.new(-100).abs #=> #<Money @cents=100>
218
- def abs
219
- Money.new(self.cents.abs, self.currency)
220
- end
221
-
222
- # Test if the money amount is zero.
223
- #
224
- # @return [Boolean]
225
- #
226
- # @example
227
- # Money.new(100).zero? #=> false
228
- # Money.new(0).zero? #=> true
229
- def zero?
230
- cents == 0
231
- end
232
-
233
- # Test if the money amount is non-zero. Returns this money object if it is
234
- # non-zero, or nil otherwise, like +Numeric#nonzero?+.
235
- #
236
- # @return [Money, nil]
237
- #
238
- # @example
239
- # Money.new(100).nonzero? #=> #<Money @cents=100>
240
- # Money.new(0).nonzero? #=> nil
241
- def nonzero?
242
- cents != 0 ? self : nil
243
- end
244
-
245
- end
246
- end
1
+ class Money
2
+ module Arithmetic
3
+
4
+ # Returns a money object with changed polarity.
5
+ #
6
+ # @return [Money]
7
+ #
8
+ # @example
9
+ # - Money.new(100) #=> #<Money @cents=-100>
10
+ def -@
11
+ Money.new(-cents, currency)
12
+ end
13
+
14
+
15
+ # Checks whether two money objects have the same currency and the same
16
+ # amount. Checks against money objects with a different currency and checks
17
+ # against objects that do not respond to #to_money will always return false.
18
+ #
19
+ # @param [Money] other_money Value to compare with.
20
+ #
21
+ # @return [Boolean]
22
+ #
23
+ # @example
24
+ # Money.new(100) == Money.new(101) #=> false
25
+ # Money.new(100) == Money.new(100) #=> true
26
+ def ==(other_money)
27
+ if other_money.respond_to?(:to_money)
28
+ other_money = other_money.to_money
29
+ cents == other_money.cents && self.currency == other_money.currency
30
+ else
31
+ false
32
+ end
33
+ end
34
+
35
+ # Synonymous with +#==+.
36
+ #
37
+ # @param [Money] other_money Value to compare with.
38
+ #
39
+ # @return [Money]
40
+ #
41
+ # @see #==
42
+ def eql?(other_money)
43
+ self == other_money
44
+ end
45
+
46
+ def <=>(other_money)
47
+ if other_money.respond_to?(:to_money)
48
+ other_money = other_money.to_money
49
+ if self.currency == other_money.currency
50
+ cents <=> other_money.cents
51
+ else
52
+ cents <=> other_money.exchange_to(currency).cents
53
+ end
54
+ else
55
+ raise ArgumentError, "Comparison of #{self.class} with #{other_money.inspect} failed"
56
+ end
57
+ end
58
+
59
+ # Returns a new Money object containing the sum of the two operands' monetary
60
+ # values. If +other_money+ has a different currency then its monetary value
61
+ # is automatically exchanged to this object's currency using +exchange_to+.
62
+ #
63
+ # @param [Money] other_money Other +Money+ object to add.
64
+ #
65
+ # @return [Money]
66
+ #
67
+ # @example
68
+ # Money.new(100) + Money.new(100) #=> #<Money @cents=200>
69
+ def +(other_money)
70
+ if currency == other_money.currency
71
+ Money.new(cents + other_money.cents, other_money.currency)
72
+ else
73
+ Money.new(cents + other_money.exchange_to(currency).cents, currency)
74
+ end
75
+ end
76
+
77
+ # Returns a new Money object containing the difference between the two
78
+ # operands' monetary values. If +other_money+ has a different currency then
79
+ # its monetary value is automatically exchanged to this object's currency
80
+ # using +exchange_to+.
81
+ #
82
+ # @param [Money] other_money Other +Money+ object to subtract.
83
+ #
84
+ # @return [Money]
85
+ #
86
+ # @example
87
+ # Money.new(100) - Money.new(99) #=> #<Money @cents=1>
88
+ def -(other_money)
89
+ if currency == other_money.currency
90
+ Money.new(cents - other_money.cents, other_money.currency)
91
+ else
92
+ Money.new(cents - other_money.exchange_to(currency).cents, currency)
93
+ end
94
+ end
95
+
96
+ # Multiplies the monetary value with the given number and returns a new
97
+ # +Money+ object with this monetary value and the same currency.
98
+ #
99
+ # Note that you can't multiply a Money object by an other +Money+ object.
100
+ #
101
+ # @param [Numeric] value Number to multiply by.
102
+ #
103
+ # @return [Money] The resulting money.
104
+ #
105
+ # @raise [ArgumentError] If +value+ is a Money instance.
106
+ #
107
+ # @example
108
+ # Money.new(100) * 2 #=> #<Money @cents=200>
109
+ #
110
+ def *(value)
111
+ if value.is_a?(Money)
112
+ raise ArgumentError, "Can't multiply a Money by a Money"
113
+ else
114
+ Money.new(cents * value, currency)
115
+ end
116
+ end
117
+
118
+ # Divides the monetary value with the given number and returns a new +Money+
119
+ # object with this monetary value and the same currency.
120
+ # Can also divide by another +Money+ object to get a ratio.
121
+ #
122
+ # +Money/Numeric+ returns +Money+. +Money/Money+ returns +Float+.
123
+ #
124
+ # @param [Money, Numeric] value Number to divide by.
125
+ #
126
+ # @return [Money] The resulting money if you divide Money by a number.
127
+ # @return [Float] The resulting number if you divide Money by a Money.
128
+ #
129
+ # @example
130
+ # Money.new(100) / 10 #=> #<Money @cents=10>
131
+ # Money.new(100) / Money.new(10) #=> 10.0
132
+ #
133
+ def /(value)
134
+ if value.is_a?(Money)
135
+ if currency == value.currency
136
+ (cents / BigDecimal.new(value.cents.to_s)).to_f
137
+ else
138
+ (cents / BigDecimal(value.exchange_to(currency).cents.to_s)).to_f
139
+ end
140
+ else
141
+ Money.new(cents / value, currency)
142
+ end
143
+ end
144
+
145
+ # Synonym for +#/+.
146
+ #
147
+ # @param [Money, Numeric] value Number to divide by.
148
+ #
149
+ # @return [Money] The resulting money if you divide Money by a number.
150
+ # @return [Float] The resulting number if you divide Money by a Money.
151
+ #
152
+ # @see #/
153
+ #
154
+ def div(value)
155
+ self / value
156
+ end
157
+
158
+ # Divide money by money or fixnum and return array containing quotient and
159
+ # modulus.
160
+ #
161
+ # @param [Money, Fixnum] val Number to divmod by.
162
+ #
163
+ # @return [Array<Money,Money>,Array<Fixnum,Money>]
164
+ #
165
+ # @example
166
+ # Money.new(100).divmod(9) #=> [#<Money @cents=11>, #<Money @cents=1>]
167
+ # Money.new(100).divmod(Money.new(9)) #=> [11, #<Money @cents=1>]
168
+ def divmod(val)
169
+ if val.is_a?(Money)
170
+ a = self.cents
171
+ b = self.currency == val.currency ? val.cents : val.exchange_to(self.currency).cents
172
+ q, m = a.divmod(b)
173
+ return [q, Money.new(m, self.currency)]
174
+ else
175
+ return [self.div(val), Money.new(self.cents.modulo(val), self.currency)]
176
+ end
177
+ end
178
+
179
+ # Equivalent to +self.divmod(val)[1]+
180
+ #
181
+ # @param [Money, Fixnum] val Number take modulo with.
182
+ #
183
+ # @return [Money]
184
+ #
185
+ # @example
186
+ # Money.new(100).modulo(9) #=> #<Money @cents=1>
187
+ # Money.new(100).modulo(Money.new(9)) #=> #<Money @cents=1>
188
+ def modulo(val)
189
+ self.divmod(val)[1]
190
+ end
191
+
192
+ # Synonym for +#modulo+.
193
+ #
194
+ # @param [Money, Fixnum] val Number take modulo with.
195
+ #
196
+ # @return [Money]
197
+ #
198
+ # @see #modulo
199
+ def %(val)
200
+ self.modulo(val)
201
+ end
202
+
203
+ # If different signs +self.modulo(val) - val+ otherwise +self.modulo(val)+
204
+ #
205
+ # @param [Money, Fixnum] val Number to rake remainder with.
206
+ #
207
+ # @return [Money]
208
+ #
209
+ # @example
210
+ # Money.new(100).remainder(9) #=> #<Money @cents=1>
211
+ def remainder(val)
212
+ a, b = self, val
213
+ b = b.exchange_to(a.currency) if b.is_a?(Money) and a.currency != b.currency
214
+
215
+ a_sign, b_sign = :pos, :pos
216
+ a_sign = :neg if a.cents < 0
217
+ b_sign = :neg if (b.is_a?(Money) and b.cents < 0) or (b < 0)
218
+
219
+ return a.modulo(b) if a_sign == b_sign
220
+ a.modulo(b) - (b.is_a?(Money) ? b : Money.new(b, a.currency))
221
+ end
222
+
223
+ # Return absolute value of self as a new Money object.
224
+ #
225
+ # @return [Money]
226
+ #
227
+ # @example
228
+ # Money.new(-100).abs #=> #<Money @cents=100>
229
+ def abs
230
+ Money.new(self.cents.abs, self.currency)
231
+ end
232
+
233
+ # Test if the money amount is zero.
234
+ #
235
+ # @return [Boolean]
236
+ #
237
+ # @example
238
+ # Money.new(100).zero? #=> false
239
+ # Money.new(0).zero? #=> true
240
+ def zero?
241
+ cents == 0
242
+ end
243
+
244
+ # Test if the money amount is non-zero. Returns this money object if it is
245
+ # non-zero, or nil otherwise, like +Numeric#nonzero?+.
246
+ #
247
+ # @return [Money, nil]
248
+ #
249
+ # @example
250
+ # Money.new(100).nonzero? #=> #<Money @cents=100>
251
+ # Money.new(0).nonzero? #=> nil
252
+ def nonzero?
253
+ cents != 0 ? self : nil
254
+ end
255
+
256
+ end
257
+ end