money2 7.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,17 @@
1
+ # Contribution Guidelines
2
+
3
+ ## Steps
4
+
5
+ 1. Fork [the repo](https://github.com/RubyMoney/money)
6
+ 2. Grab dependencies: `bundle install`
7
+ 3. Make sure everything is working: `bundle exec rake spec`
8
+ 4. Make your changes
9
+ 5. Test your changes
10
+ 5. Create a Pull Request
11
+ 6. Celebrate!!!!!
12
+
13
+ ## Notes
14
+
15
+ When contributing, please make sure to update the CHANGELOG and AUTHORS files
16
+ when you submit your pull request. Upon merging of your first pull request,
17
+ you will be given commit access to the repository.
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'coveralls', :require => false
4
+ gem 'pry', :require => false
5
+
6
+ # JSON gem no longer supports ruby < 2.0.0
7
+ if defined?(JRUBY_VERSION)
8
+ gem 'json'
9
+ elsif RUBY_VERSION =~ /^1/
10
+ # Legacy gem locks for ruby 1.9.x
11
+ gem 'json', '~> 1.8.3'
12
+ gem 'tins', '~> 1.6.0'
13
+ gem 'term-ansicolor', '< 1.4'
14
+ end
15
+
16
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2005 Tobias Lutke
4
+ Copyright (c) 2008 Phusion
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining
7
+ a copy of this software and associated documentation files (the
8
+ "Software"), to deal in the Software without restriction, including
9
+ without limitation the rights to use, copy, modify, merge, publish,
10
+ distribute, sublicense, and/or sell copies of the Software, and to
11
+ permit persons to whom the Software is furnished to do so, subject to
12
+ the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be
15
+ included in all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,438 @@
1
+ # RubyMoney - Money
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/money.svg)](http://badge.fury.io/rb/money)
4
+ [![Build Status](https://travis-ci.org/RubyMoney/money.svg?branch=master)](https://travis-ci.org/RubyMoney/money)
5
+ [![Code Climate](https://codeclimate.com/github/RubyMoney/money.svg)](https://codeclimate.com/github/RubyMoney/money)
6
+ [![Coverage Status](https://coveralls.io/repos/RubyMoney/money/badge.svg?branch=master)](https://coveralls.io/r/RubyMoney/money?branch=master)
7
+ [![Inline docs](http://inch-ci.org/github/RubyMoney/money.svg)](http://inch-ci.org/github/RubyMoney/money)
8
+ [![Dependency Status](https://gemnasium.com/RubyMoney/money.svg)](https://gemnasium.com/RubyMoney/money)
9
+ [![License](https://img.shields.io/github/license/RubyMoney/money.svg)](http://opensource.org/licenses/MIT)
10
+
11
+ :warning: Please read about the [difference](https://github.com/printercu/money/wiki)
12
+ between this version and original `money` gem.
13
+
14
+ If you miss String parsing, check out the new [monetize gem](https://github.com/RubyMoney/monetize).
15
+
16
+ ## Contributing
17
+
18
+ See the [Contribution Guidelines](https://github.com/RubyMoney/money/blob/master/CONTRIBUTING.md)
19
+
20
+ ## Introduction
21
+
22
+ A Ruby Library for dealing with money and currency conversion.
23
+
24
+ ### Features
25
+
26
+ - Provides a `Money` class which encapsulates all information about an certain
27
+ amount of money, such as its value and its currency.
28
+ - Provides a `Money::Currency` class which encapsulates all information about
29
+ a monetary unit.
30
+ - Represents monetary values as integers, in cents. This avoids floating point
31
+ rounding errors.
32
+ - Represents currency as `Money::Currency` instances providing a high level of
33
+ flexibility.
34
+ - Provides APIs for exchanging money from one currency to another.
35
+
36
+ ### Resources
37
+
38
+ - [Website](http://rubymoney.github.io/money/)
39
+ - [API Documentation](http://www.rubydoc.info/gems/money/frames)
40
+ - [Git Repository](https://github.com/RubyMoney/money)
41
+
42
+ ### Notes
43
+
44
+ - Your app must use UTF-8 to function with this library. There are a
45
+ number of non-ASCII currency attributes.
46
+ - This app requires JSON. If you're using JRuby < 1.7.0
47
+ you'll need to add `gem "json"` to your Gemfile or similar.
48
+
49
+ ## Downloading
50
+
51
+ Install stable releases with the following command:
52
+
53
+ gem install money
54
+
55
+ The development version (hosted on Github) can be installed with:
56
+
57
+ git clone git://github.com/RubyMoney/money.git
58
+ cd money
59
+ rake install
60
+
61
+ ## Usage
62
+
63
+ ``` ruby
64
+ require 'money'
65
+
66
+ # 10.00 USD
67
+ money = Money.new(1000, "USD")
68
+ money.fractional #=> 1000
69
+ money.currency #=> Currency.new("USD")
70
+
71
+ # Comparisons
72
+ Money.new(1000, "USD") == Money.new(1000, "USD") #=> true
73
+ Money.new(1000, "USD") == Money.new(100, "USD") #=> false
74
+ Money.new(1000, "USD") == Money.new(1000, "EUR") #=> false
75
+ Money.new(1000, "USD") != Money.new(1000, "EUR") #=> true
76
+
77
+ # Arithmetic
78
+ Money.new(1000, "USD") + Money.new(500, "USD") == Money.new(1500, "USD")
79
+ Money.new(1000, "USD") - Money.new(200, "USD") == Money.new(800, "USD")
80
+ Money.new(1000, "USD") / 5 == Money.new(200, "USD")
81
+ Money.new(1000, "USD") * 5 == Money.new(5000, "USD")
82
+
83
+ # Unit to subunit conversions
84
+ Money.from_amount(5, "USD") == Money.new(500, "USD") # 5 USD
85
+ Money.from_amount(5, "JPY") == Money.new(5, "JPY") # 5 JPY
86
+ Money.from_amount(5, "TND") == Money.new(5000, "TND") # 5 TND
87
+
88
+ # Currency conversions
89
+ some_code_to_setup_exchange_rates
90
+ Money.new(1000, "USD").exchange_to("EUR") == Money.new(some_value, "EUR")
91
+
92
+ # Formatting (see Formatter section for more options)
93
+ Money.new(100, "USD").format #=> "$1.00"
94
+ Money.new(100, "GBP").format #=> "£1.00"
95
+ Money.new(100, "EUR").format #=> "€1.00"
96
+ ```
97
+
98
+ ## Currency
99
+
100
+ Currencies are consistently represented as instances of `Money::Currency`.
101
+ The most part of `Money` APIs allows you to supply either a `String` or a
102
+ `Money::Currency`.
103
+
104
+ ``` ruby
105
+ Money.new(1000, "USD") == Money.new(1000, Money::Currency.new("USD"))
106
+ Money.new(1000, "EUR").currency == Money::Currency.new("EUR")
107
+ ```
108
+
109
+ A `Money::Currency` instance holds all the information about the currency,
110
+ including the currency symbol, name and much more.
111
+
112
+ ``` ruby
113
+ currency = Money.new(1000, "USD").currency
114
+ currency.code #=> "USD"
115
+ currency.name #=> "United States Dollar"
116
+ ```
117
+
118
+ To define a new `Money::Currency` use `Money::Currency.register` as shown
119
+ below.
120
+
121
+ ``` ruby
122
+ curr = {
123
+ priority: 1,
124
+ code: 'USD',
125
+ iso_numeric: 840,
126
+ name: 'United States Dollar',
127
+ symbol: '$',
128
+ subunit: 'Cent',
129
+ subunit_to_unit: 100,
130
+ separator: '.',
131
+ delimiter: ',',
132
+ }
133
+
134
+ Money::Currency.register(curr)
135
+ ```
136
+
137
+ The pre-defined set of attributes includes:
138
+
139
+ - `:priority` a numerical value you can use to sort/group the currency list
140
+ - `:code` the international 3-letter code as defined by the ISO 4217 standard or
141
+ other code for non-ISO currencies.
142
+ - `:iso_numeric` the international 3-digit code as defined by the ISO 4217 standard
143
+ - `:name` the currency name
144
+ - `:symbol` the currency symbol (UTF-8 encoded)
145
+ - `:subunit` the name of the fractional monetary unit
146
+ - `:subunit_to_unit` the proportion between the unit and the subunit
147
+ - `:separator` character between the whole and fraction amounts
148
+ - `:delimiter` character between each thousands place
149
+
150
+ All attributes except `:code` are optional. Some attributes, such as
151
+ `:symbol`, are used by the Money class to print out a representation of the
152
+ object. Other attributes, such as `:name` or `:priority`, exist to provide a
153
+ basic API you can take advantage of to build your application.
154
+
155
+ ### :priority
156
+
157
+ The priority attribute is an arbitrary numerical value you can assign to the
158
+ `Money::Currency` and use in sorting/grouping operation.
159
+
160
+ For instance, let's assume your Rails application needs to render a currency
161
+ selector like the one available
162
+ [here](http://finance.yahoo.com/currency-converter/). You can create a couple of
163
+ custom methods to return the list of major currencies and all currencies as
164
+ follows:
165
+
166
+ ``` ruby
167
+ # Returns an array of currency id where
168
+ # priority < 10
169
+ def major_currencies(hash)
170
+ hash.inject([]) do |array, (id, attributes)|
171
+ priority = attributes[:priority]
172
+ if priority && priority < 10
173
+ array[priority] ||= []
174
+ array[priority] << id
175
+ end
176
+ array
177
+ end.compact.flatten
178
+ end
179
+
180
+ # Returns an array of all currency id
181
+ def all_currencies(hash)
182
+ hash.keys
183
+ end
184
+
185
+ major_currencies(Money::Currency.table)
186
+ # => [:usd, :eur, :gbp, :aud, :cad, :jpy]
187
+
188
+ all_currencies(Money::Currency.table)
189
+ # => [:aed, :afn, :all, ...]
190
+ ```
191
+
192
+ ### Default Currency
193
+
194
+ By default `Money` defaults to USD as its currency. This can be overwritten
195
+ using:
196
+
197
+ ``` ruby
198
+ Money.default_currency = Money::Currency.new("CAD")
199
+ ```
200
+
201
+ If you use Rails, then `environment.rb` is a very good place to put this.
202
+
203
+ ### Currency Exponent
204
+
205
+ The exponent of a money value is the number of digits after the decimal
206
+ separator (which separates the major unit from the minor unit). See e.g.
207
+ [ISO 4217](http://www.currency-iso.org/en/shared/amendments/iso-4217-amendment.html) for more
208
+ information. You can find the exponent (as an `Integer`) by
209
+
210
+ ``` ruby
211
+ Money::Currency.new("USD").exponent # => 2
212
+ Money::Currency.new("JPY").exponent # => 0
213
+ Money::Currency.new("MGA").exponent # => 1
214
+ ```
215
+
216
+ ### Currency Lookup
217
+
218
+ To find a given currency by ISO 4217 numeric code (three digits) you can do
219
+
220
+ ``` ruby
221
+ Money::Currency.find_by_iso_numeric(978) #=> Money::Currency.new(:eur)
222
+ ```
223
+
224
+ ## Currency Exchange
225
+
226
+ Exchanging money is performed through an exchange bank object. The default
227
+ exchange bank object requires one to manually specify the exchange rate. Here's
228
+ an example of how it works:
229
+
230
+ ``` ruby
231
+ Money.add_rate("USD", "CAD", 1.24515)
232
+ Money.add_rate("CAD", "USD", 0.803115)
233
+
234
+ Money.us_dollar(100).exchange_to("CAD") # => Money.new(124, "CAD")
235
+ Money.ca_dollar(100).exchange_to("USD") # => Money.new(80, "USD")
236
+ ```
237
+
238
+ Comparison and arithmetic operations work as expected:
239
+
240
+ ``` ruby
241
+ Money.new(1000, "USD") <=> Money.new(900, "USD") # => 1; 9.00 USD is smaller
242
+ Money.new(1000, "EUR") + Money.new(10, "EUR") == Money.new(1010, "EUR")
243
+
244
+ Money.add_rate("USD", "EUR", 0.5)
245
+ Money.new(1000, "EUR") + Money.new(1000, "USD") == Money.new(1500, "EUR")
246
+ ```
247
+
248
+ ### Exchange rate stores
249
+
250
+ The default bank is initialized with an in-memory store for exchange rates.
251
+
252
+ ```ruby
253
+ Money.default_bank = Money::Bank::VariableExchange.new(Money::RatesStore::Memory.new)
254
+ ```
255
+
256
+ You can pass you own store implementation, ie. for storing and retrieving rates off a database, file, cache, etc.
257
+
258
+ ```ruby
259
+ Money.default_bank = Money::Bank::VariableExchange.new(MyCustomStore.new)
260
+ ```
261
+
262
+ Stores must implement the following interface:
263
+
264
+ ```ruby
265
+ # Add new exchange rate.
266
+ # @param [String] iso_from Currency ISO code. ex. 'USD'
267
+ # @param [String] iso_to Currency ISO code. ex. 'CAD'
268
+ # @param [Numeric] rate Exchange rate. ex. 0.0016
269
+ #
270
+ # @return [Numeric] rate.
271
+ def add_rate(iso_from, iso_to, rate); end
272
+
273
+ # Get rate. Must be idempotent. ie. adding the same rate must not produce duplicates.
274
+ # @param [String] iso_from Currency ISO code. ex. 'USD'
275
+ # @param [String] iso_to Currency ISO code. ex. 'CAD'
276
+ #
277
+ # @return [Numeric] rate.
278
+ def get_rate(iso_from, iso_to); end
279
+
280
+ # Iterate over rate tuples (iso_from, iso_to, rate)
281
+ #
282
+ # @yieldparam iso_from [String] Currency ISO string.
283
+ # @yieldparam iso_to [String] Currency ISO string.
284
+ # @yieldparam rate [Numeric] Exchange rate.
285
+ #
286
+ # @return [Enumerator]
287
+ #
288
+ # @example
289
+ # store.each_rate do |iso_from, iso_to, rate|
290
+ # puts [iso_from, iso_to, rate].join
291
+ # end
292
+ def each_rate(&block); end
293
+
294
+ # Wrap store operations in a thread-safe transaction
295
+ # (or IO or Database transaction, depending on your implementation)
296
+ #
297
+ # @yield [n] Block that will be wrapped in transaction.
298
+ #
299
+ # @example
300
+ # store.transaction do
301
+ # store.add_rate('USD', 'CAD', 0.9)
302
+ # store.add_rate('USD', 'CLP', 0.0016)
303
+ # end
304
+ def transaction(&block); end
305
+
306
+ # Serialize store and its content to make Marshal.dump work.
307
+ #
308
+ # Returns an array with store class and any arguments needed to initialize the store in the current state.
309
+
310
+ # @return [Array] [class, arg1, arg2]
311
+ def marshal_dump; end
312
+ ```
313
+
314
+ The following example implements an `ActiveRecord` store to save exchange rates to a database.
315
+
316
+ ```ruby
317
+ # DB columns :from[String], :to[String], :rate[Float]
318
+
319
+ class ExchangeRate < ActiveRecord::Base
320
+ def self.get_rate(from_code, to_code)
321
+ rate = find_by(:from => from_code, :to => to_code)
322
+ rate.present? ? rate.rate : nil
323
+ end
324
+
325
+ def self.add_rate(from_code, to_code, rate)
326
+ exrate = find_or_initialize_by(:from => from_code, :to => to_code)
327
+ exrate.rate = rate
328
+ exrate.save!
329
+ end
330
+ end
331
+ ```
332
+
333
+ Now you can use it with the default bank.
334
+
335
+ ```ruby
336
+ Money.default_bank = Money::Bank::VariableExchange.new(ExchangeRate)
337
+
338
+ # Add to the underlying store
339
+ Money.default_bank.add_rate('USD', 'CAD', 0.9)
340
+ # Retrieve from the underlying store
341
+ Money.default_bank.get_rate('USD', 'CAD') # => 0.9
342
+ # Exchanging amounts just works.
343
+ Money.new(1000, 'USD').exchange_to('CAD') #=> #<Money fractional:900 currency:CAD>
344
+ ```
345
+
346
+ There is nothing stopping you from creating store objects which scrapes
347
+ [XE](http://www.xe.com) for the current rates or just returns `rand(2)`:
348
+
349
+ ``` ruby
350
+ Money.default_bank = Money::Bank::VariableExchange.new(StoreWhichScrapesXeDotCom.new)
351
+ ```
352
+
353
+ You can also implement your own Bank to calculate exchanges differently.
354
+ Different banks can share Stores.
355
+
356
+ ```ruby
357
+ Money.default_bank = MyCustomBank.new(Money::RatesStore::Memory.new)
358
+ ```
359
+
360
+ If you wish to disable automatic currency conversion to prevent arithmetic when
361
+ currencies don't match:
362
+
363
+ ``` ruby
364
+ Money.disallow_currency_conversion!
365
+ ```
366
+
367
+ ### Implementations
368
+
369
+ The following is a list of Money.gem compatible currency exchange rate
370
+ implementations.
371
+
372
+ - [eu_central_bank](https://github.com/RubyMoney/eu_central_bank)
373
+ - [google_currency](https://github.com/RubyMoney/google_currency)
374
+ - [currencylayer](https://github.com/askuratovsky/currencylayer)
375
+ - [nordea](https://github.com/matiaskorhonen/nordea)
376
+ - [nbrb_currency](https://github.com/slbug/nbrb_currency)
377
+ - [money-currencylayer-bank](https://github.com/phlegx/money-currencylayer-bank)
378
+ - [money-open-exchange-rates](https://github.com/spk/money-open-exchange-rates)
379
+ - [money-historical-bank](https://github.com/atwam/money-historical-bank)
380
+ - [russian_central_bank](https://github.com/rmustafin/russian_central_bank)
381
+ - [money-uphold-bank](https://github.com/subvisual/money-uphold-bank)
382
+
383
+ ## Ruby on Rails
384
+
385
+ To integrate money in a Rails application use [money-rails](https://github.com/RubyMoney/money-rails).
386
+
387
+ For deprecated methods of integrating with Rails, check [the wiki](https://github.com/RubyMoney/money/wiki).
388
+
389
+ ## I18n
390
+
391
+ If you want thousands seperator and decimal mark to be same across all
392
+ currencies this can be defined in your `I18n` translation files.
393
+
394
+ In an rails application this may look like:
395
+
396
+ ```yml
397
+ # config/locale/en.yml
398
+ en:
399
+ number:
400
+ format:
401
+ delimiter: ","
402
+ separator: "."
403
+ # or
404
+ number:
405
+ currency:
406
+ format:
407
+ delimiter: ","
408
+ separator: "."
409
+ ```
410
+
411
+ For this example `Money.new(123456789, "SEK").format` will return `1,234,567.89
412
+ kr` which otherwise will return `1 234 567,89 kr`.
413
+
414
+ If you wish to disable this feature:
415
+ ``` ruby
416
+ Money.formatter.use_i18n = false
417
+ ```
418
+
419
+ ### Troubleshooting
420
+
421
+ If you get a runtime error such as:
422
+
423
+ I18n::InvalidLocale: :en is not a valid locale
424
+
425
+ Set the following:
426
+ ``` ruby
427
+ I18n.enforce_available_locales = false
428
+ ```
429
+
430
+ ## Formatting
431
+
432
+ There are several formatting rules for when `Money#format` is called. For more information, check out the [formatting module source](https://github.com/RubyMoney/money/blob/master/lib/money/formatting.rb), or read the latest release's [rdoc version](http://www.rubydoc.info/gems/money/Money/Formatting).
433
+
434
+ If you wish to format money according to the EU's [Rules for expressing monetary units](http://publications.europa.eu/code/en/en-370303.htm#position) in either English, Irish, Latvian or Maltese:
435
+ ```ruby
436
+ m = Money.new('123', :gbp) # => #<Money fractional:123 currency:GBP>
437
+ m.format( symbol: m.currency.to_s + ' ') # => "GBP 1.23"
438
+ ```