money 4.0.1 → 4.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.
@@ -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