money 6.5.1 → 6.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2e625dd2f1daa9df7fbe2c8c5ed8972c5bf69f9a
4
- data.tar.gz: 50addb5ca7123aff716961c6e782d43846d90c55
3
+ metadata.gz: c65fe09cbae38c4022a53cdc0c6b5cba47e72930
4
+ data.tar.gz: 5de5a0732f90ab4af46ef801378a7a6161b5324d
5
5
  SHA512:
6
- metadata.gz: 51736bea340dca0e23da25018aad574380bdfea0281e20aaf0af90c306f50d48be15ffb15136daff9caac4c5c6a5f563042c6703dc6403c83ce32fee85d42e30
7
- data.tar.gz: 2b32b72aa148550d672ae639b0c9c96a13c5d3c35676fdf7649f130bd79a4d41880444d2d1b0fdbe3d442d840518fcf2e35bdb3156ddd46a8f1490f68e6ada24
6
+ metadata.gz: bba3d4bc1dfc26c28ed9e4720a815c0bf36c6dd0376c17a664cb70d066d5c436c29da795abade5bd61c0797808f5969f52fa696d7bfeb874333ad11411745583
7
+ data.tar.gz: 1a38008c4890e953e1002485fd1098c935ed370cf4e05648846327302d2202fed8adf96df22b37cb98abf7de5b36a8cc87bc7d168d7ab606f2d87a28d87e4f32
data/.travis.yml CHANGED
@@ -1,4 +1,5 @@
1
1
  language: ruby
2
+ sudo: false
2
3
  rvm:
3
4
  - 1.9.3
4
5
  - 2.0.0
data/AUTHORS CHANGED
@@ -16,6 +16,7 @@ Bill DeRusha
16
16
  Bodaniel Jeanes
17
17
  Brian Jones
18
18
  bUg.
19
+ Cade Truitt
19
20
  Casper Thomsen
20
21
  Chad Boyd
21
22
  Choongmin Lee
@@ -30,6 +31,7 @@ Edwin Vlieg
30
31
  Eloy
31
32
  Evan Alter
32
33
  Exoth
34
+ Filipe Goncalves
33
35
  François Beausoleil
34
36
  François Klingler
35
37
  Francisco Trindade
@@ -68,10 +70,13 @@ Mateusz Wolsza
68
70
  Matias Korhonen
69
71
  Matt Jankowski
70
72
  Matthew McEachen
73
+ Max Melentiev
71
74
  Michael J. Cohen
72
75
  Michael Irwin
73
76
  Michael Reinsch
77
+ Michael Rodrigues
74
78
  Mikael Wikman
79
+ Mike Herrera
75
80
  Mike Połétyn
76
81
  Musannif Zahir
77
82
  Neil Middleton
@@ -111,6 +116,8 @@ Tobias Schmidt
111
116
  Tom Lianza
112
117
  tommeier
113
118
  Troels Knak-Nielsen
119
+ Tsyren Ochirov
114
120
  Wei Zhu
115
121
  Zubin Henner
116
122
  Бродяной Александр
123
+ Douglas Miller
data/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  ## Next release
4
4
 
5
+ - Fixed VariableExchange#exchange_with for big numbers.
6
+ - Add Currency symbol translation support
7
+ - `Currency.all` raises a more helpful error message
8
+ (`Currency::MissingAttributeError`)if a currency has no priority
5
9
  - `Currency` implements `Enumerable`.
6
10
  - `Currency#<=>` sorts alphabetically by `id` if the `priority`s are the same,
7
11
  and no longer raises an error if one of the priorities is missing.
@@ -16,6 +20,17 @@
16
20
  `.ca_dollar`, and `.euro`.
17
21
  - Add helper methods for British pounds: `Money.pound_sterling` and
18
22
  `Money.gbp`.
23
+ - Add `Money.from_amount` to create money from a value in units instead of
24
+ fractional units.
25
+ - Changed CHF symbol from 'Fr' to 'CHF'
26
+ - Changed CLF exponent from 0 to 4
27
+ - Changed CLP subunit_to_unit from 1 to 100
28
+ - Minor fixes to prevent warnings on unused variables and the redefinition of
29
+ `Money.default_currency`
30
+ - `Money#==` changed to acknowledge that 0 in one currency is equal to 0 in any currency.
31
+ - Changed KRW subunit_to_unit from 100 to 1
32
+ - Decouple exchange rates storage from bank objects and formalize storage public API. Default is `Money::RatesStore::Memory`.
33
+ - `Currency.new` now a singleton by its id
19
34
 
20
35
  ## 6.5.1
21
36
  - Fix format for BYR currency
data/README.md CHANGED
@@ -79,9 +79,19 @@ Money.new(1000, "USD") - Money.new(200, "USD") == Money.new(800, "USD")
79
79
  Money.new(1000, "USD") / 5 == Money.new(200, "USD")
80
80
  Money.new(1000, "USD") * 5 == Money.new(5000, "USD")
81
81
 
82
+ # Unit to subunit conversions
83
+ Money.from_amount(5, "USD") == Money.new(500, "USD") # 5 USD
84
+ Money.from_amount(5, "JPY") == Money.new(5, "JPY") # 5 JPY
85
+ Money.from_amount(5, "TND") == Money.new(5000, "TND") # 5 TND
86
+
82
87
  # Currency conversions
83
88
  some_code_to_setup_exchange_rates
84
89
  Money.new(1000, "USD").exchange_to("EUR") == Money.new(some_value, "EUR")
90
+
91
+ # Formatting (see Formatting section for more options)
92
+ Money.new(100, "USD").format #=> "$1.00"
93
+ Money.new(100, "GBP").format #=> "£1.00"
94
+ Money.new(100, "EUR").format #=> "€1.00"
85
95
  ```
86
96
 
87
97
  ## Currency
@@ -233,11 +243,116 @@ Money.add_rate("USD", "EUR", 0.5)
233
243
  Money.new(1000, "EUR") + Money.new(1000, "USD") == Money.new(1500, "EUR")
234
244
  ```
235
245
 
236
- There is nothing stopping you from creating bank objects which scrapes
246
+ ### Exchange rate stores
247
+
248
+ The default bank is initialized with an in-memory store for exchange rates.
249
+
250
+ ```ruby
251
+ Money.default_bank = Money::Bank::VariableExchange.new(Money::RatesStore::Memory.new)
252
+ ```
253
+
254
+ You can pass you own store implementation, ie. for storing and retrieving rates off a database, file, cache, etc.
255
+
256
+ ```ruby
257
+ Money.default_bank = Money::Bank::VariableExchange.new(MyCustomStore.new)
258
+ ```
259
+
260
+ Stores must implement the following interface:
261
+
262
+ ```ruby
263
+ # Add new exchange rate.
264
+ # @param [String] iso_from Currency ISO code. ex. 'USD'
265
+ # @param [String] iso_to Currency ISO code. ex. 'CAD'
266
+ # @param [Numeric] rate Exchange rate. ex. 0.0016
267
+ #
268
+ # @return [Numeric] rate.
269
+ def add_rate(iso_from, iso_to, rate); end
270
+
271
+ # Get rate. Must be idempotent. ie. adding the same rate must not produce duplicates.
272
+ # @param [String] iso_from Currency ISO code. ex. 'USD'
273
+ # @param [String] iso_to Currency ISO code. ex. 'CAD'
274
+ #
275
+ # @return [Numeric] rate.
276
+ def get_rate(iso_from, iso_to); end
277
+
278
+ # Iterate over rate tuples (iso_from, iso_to, rate)
279
+ #
280
+ # @yieldparam iso_from [String] Currency ISO string.
281
+ # @yieldparam iso_to [String] Currency ISO string.
282
+ # @yieldparam rate [Numeric] Exchange rate.
283
+ #
284
+ # @return [Enumerator]
285
+ #
286
+ # @example
287
+ # store.each_rate do |iso_from, iso_to, rate|
288
+ # puts [iso_from, iso_to, rate].join
289
+ # end
290
+ def each_rate(&block); end
291
+
292
+ # Wrap store operations in a thread-safe transaction
293
+ # (or IO or Database transaction, depending on your implementation)
294
+ #
295
+ # @yield [n] Block that will be wrapped in transaction.
296
+ #
297
+ # @example
298
+ # store.transaction do
299
+ # store.add_rate('USD', 'CAD', 0.9)
300
+ # store.add_rate('USD', 'CLP', 0.0016)
301
+ # end
302
+ def transaction(&block); end
303
+
304
+ # Serialize store and its content to make Marshal.dump work.
305
+ #
306
+ # Returns an array with store class and any arguments needed to initialize the store in the current state.
307
+
308
+ # @return [Array] [class, arg1, arg2]
309
+ def marshal_dump; end
310
+ ```
311
+
312
+ The following example implements an `ActiveRecord` store to save exchange rates to a database.
313
+
314
+ ```ruby
315
+ # DB columns :from[String], :to[String], :rate[Float]
316
+
317
+ class ExchangeRate < ActiveRecord::Base
318
+ def self.get_rate(from_iso_code, to_iso_code)
319
+ rate = find_by_from_and_to(from_iso_code, to_iso_code)
320
+ rate.present? ? rate.rate : nil
321
+ end
322
+
323
+ def self.add_rate(from_iso_code, to_iso_code, rate)
324
+ exrate = find_or_initialize_by_from_and_to(from_iso_code, to_iso_code)
325
+ exrate.rate = rate
326
+ exrate.save!
327
+ end
328
+ end
329
+ ```
330
+
331
+ Now you can use it with the default bank.
332
+
333
+ ```ruby
334
+ Money.default_bank = Money::Bank::VariableExchange.new(ExchangeRate)
335
+
336
+ # Add to the underlying store
337
+ Money.default_bank.add_rate('USD', 'CAD', 0.9)
338
+ # Retrieve from the underlying store
339
+ Money.default_bank.get_rate('USD', 'CAD') # => 0.9
340
+ # Exchanging amounts just works.
341
+ Money.new(1000, 'USD').exchange_to('CAD') #=> #<Money fractional:900 currency:CAD>
342
+ ```
343
+
344
+ There is nothing stopping you from creating store objects which scrapes
237
345
  [XE](http://www.xe.com) for the current rates or just returns `rand(2)`:
238
346
 
239
347
  ``` ruby
240
- Money.default_bank = ExchangeBankWhichScrapesXeDotCom.new
348
+ Money.default_bank = Money::Bank::VariableExchange.new(StoreWhichScrapesXeDotCom.new)
349
+ ```
350
+
351
+ You can also implement your own Bank to calculate exchanges differently.
352
+ Different banks can share Stores.
353
+
354
+ ```ruby
355
+ Money.default_bank = MyCustomBank.new(Money::RatesStore::Memory.new)
241
356
  ```
242
357
 
243
358
  If you wish to disable automatic currency conversion to prevent arithmetic when
@@ -254,6 +369,7 @@ implementations.
254
369
 
255
370
  - [eu_central_bank](http://github.com/RubyMoney/eu_central_bank)
256
371
  - [google_currency](http://github.com/RubyMoney/google_currency)
372
+ - [money-json-rates](https://github.com/askuratovsky/money-json-rates)
257
373
  - [nordea](https://github.com/k33l0r/nordea)
258
374
  - [nbrb_currency](https://github.com/slbug/nbrb_currency)
259
375
  - [money-open-exchange-rates](https://github.com/spk/money-open-exchange-rates)
@@ -296,7 +412,9 @@ If you wish to disable this feature:
296
412
  Money.use_i18n = false
297
413
  ```
298
414
 
299
- *Note: There are several formatting rules for when `Money#format` is called. For more information, check out the [formatting module](https://github.com/RubyMoney/money/blob/master/lib/money/money/formatting.rb).*
415
+ ## Formatting
416
+
417
+ There are several formatting rules for when `Money#format` is called. For more information, check out the [formatting module](https://github.com/RubyMoney/money/blob/master/lib/money/money/formatting.rb).*
300
418
 
301
419
  ## Migration Notes
302
420
 
data/Rakefile CHANGED
@@ -1,4 +1,3 @@
1
- require "rubygems"
2
1
  require "bundler/gem_tasks"
3
2
  require "rake/clean"
4
3
  require "rspec/core/rake_task"
@@ -419,8 +419,8 @@
419
419
  "priority": 100,
420
420
  "iso_code": "CHF",
421
421
  "name": "Swiss Franc",
422
- "symbol": "Fr",
423
- "alternate_symbols": ["SFr", "CHF"],
422
+ "symbol": "CHF",
423
+ "alternate_symbols": ["SFr", "Fr"],
424
424
  "subunit": "Rappen",
425
425
  "subunit_to_unit": 100,
426
426
  "symbol_first": true,
@@ -437,7 +437,7 @@
437
437
  "symbol": "UF",
438
438
  "alternate_symbols": [],
439
439
  "subunit": "Peso",
440
- "subunit_to_unit": 1,
440
+ "subunit_to_unit": 10000,
441
441
  "symbol_first": true,
442
442
  "html_entity": "&#x20B1;",
443
443
  "decimal_mark": ",",
@@ -452,7 +452,7 @@
452
452
  "disambiguate_symbol": "CLP",
453
453
  "alternate_symbols": [],
454
454
  "subunit": "Peso",
455
- "subunit_to_unit": 100,
455
+ "subunit_to_unit": 1,
456
456
  "symbol_first": true,
457
457
  "html_entity": "&#36;",
458
458
  "decimal_mark": ",",
@@ -1036,14 +1036,14 @@
1036
1036
  "name": "Jordanian Dinar",
1037
1037
  "symbol": "د.ا",
1038
1038
  "alternate_symbols": ["JD"],
1039
- "subunit": "Piastre",
1040
- "subunit_to_unit": 100,
1039
+ "subunit": "Fils",
1040
+ "subunit_to_unit": 1000,
1041
1041
  "symbol_first": true,
1042
1042
  "html_entity": "",
1043
1043
  "decimal_mark": ".",
1044
1044
  "thousands_separator": ",",
1045
1045
  "iso_numeric": "400",
1046
- "smallest_denomination": 0.5
1046
+ "smallest_denomination": 5
1047
1047
  },
1048
1048
  "jpy": {
1049
1049
  "priority": 6,
@@ -1142,7 +1142,7 @@
1142
1142
  "name": "South Korean Won",
1143
1143
  "symbol": "₩",
1144
1144
  "subunit": null,
1145
- "subunit_to_unit": 100,
1145
+ "subunit_to_unit": 1,
1146
1146
  "alternate_symbols": [],
1147
1147
  "symbol_first": true,
1148
1148
  "html_entity": "&#x20A9;",
@@ -1,5 +1,3 @@
1
- require 'thread'
2
-
3
1
  class Money
4
2
  # Provides classes that aid in the ability of exchange one currency with
5
3
  # another.
@@ -1,4 +1,5 @@
1
1
  require 'money/bank/base'
2
+ require 'money/rates_store/memory'
2
3
  require 'json'
3
4
  require 'yaml'
4
5
 
@@ -15,42 +16,58 @@ class Money
15
16
  # conversion rates. One must manually specify them with +add_rate+, after
16
17
  # which one can perform exchanges with +#exchange_with+.
17
18
  #
19
+ # Exchange rates are stored in memory using +Money::RatesStore::Memory+ by default.
20
+ # Pass custom rates stores for other types of storage (file, database, etc)
21
+ #
18
22
  # @example
19
23
  # bank = Money::Bank::VariableExchange.new
20
24
  # bank.add_rate("USD", "CAD", 1.24515)
21
25
  # bank.add_rate("CAD", "USD", 0.803115)
22
26
  #
23
- # c1 = 100_00.to_money("USD")
24
- # c2 = 100_00.to_money("CAD")
27
+ # c1 = Money.new(100_00, "USD")
28
+ # c2 = Money.new(100_00, "CAD")
25
29
  #
26
30
  # # Exchange 100 USD to CAD:
27
- # bank.exchange_with(c1, "CAD") #=> #<Money @fractional=1245150>
31
+ # bank.exchange_with(c1, "CAD") #=> #<Money fractional:12451 currency:CAD>
28
32
  #
29
33
  # # Exchange 100 CAD to USD:
30
- # bank.exchange_with(c2, "USD") #=> #<Money @fractional=803115>
34
+ # bank.exchange_with(c2, "USD") #=> #<Money fractional:8031 currency:USD>
35
+ #
36
+ # # With custom exchange rates storage
37
+ # redis_store = MyCustomRedisStore.new(host: 'localhost:6379')
38
+ # bank = Money::Bank::VariableExchange.new(redis_store)
39
+ # # Store rates in redis
40
+ # bank.add_rate 'USD', 'CAD', 0.98
41
+ # # Get rate from redis
42
+ # bank.get_rate 'USD', 'CAD'
31
43
  class VariableExchange < Base
32
44
 
33
- attr_reader :rates, :mutex
45
+ attr_reader :mutex, :store
34
46
 
35
47
  # Available formats for importing/exporting rates.
36
48
  RATE_FORMATS = [:json, :ruby, :yaml]
49
+ SERIALIZER_SEPARATOR = '_TO_'.freeze
37
50
 
38
- # Setup rates hash and mutex for rates locking
51
+ # Initializes a new +Money::Bank::VariableExchange+ object.
52
+ # It defaults to using an in-memory, thread safe store instance for
53
+ # storing exchange rates.
39
54
  #
40
- # @return [self]
41
- def setup
42
- @rates = {}
43
- @mutex = Mutex.new
44
- self
55
+ # @param [RateStore] st An exchange rate store, used to persist exchange rate pairs.
56
+ # @yield [n] Optional block to use when rounding after exchanging one
57
+ # currency for another. See +Money::bank::base+
58
+ def initialize(st = Money::RatesStore::Memory.new, &block)
59
+ @store = st
60
+ super(&block)
45
61
  end
46
62
 
47
63
  def marshal_dump
48
- [@rates, @rounding_method]
64
+ [store.marshal_dump, @rounding_method]
49
65
  end
50
66
 
51
67
  def marshal_load(arr)
52
- @rates, @rounding_method = arr
53
- @mutex = Mutex.new
68
+ store_info = arr[0]
69
+ @store = store_info.shift.new(*store_info)
70
+ @rounding_method = arr[1]
54
71
  end
55
72
 
56
73
  # Exchanges the given +Money+ object to a new +Money+ object in
@@ -76,14 +93,14 @@ class Money
76
93
  # bank.add_rate("USD", "CAD", 1.24515)
77
94
  # bank.add_rate("CAD", "USD", 0.803115)
78
95
  #
79
- # c1 = 100_00.to_money("USD")
80
- # c2 = 100_00.to_money("CAD")
96
+ # c1 = Money.new(100_00, "USD")
97
+ # c2 = Money.new(100_00, "CAD")
81
98
  #
82
99
  # # Exchange 100 USD to CAD:
83
- # bank.exchange_with(c1, "CAD") #=> #<Money @fractional=1245150>
100
+ # bank.exchange_with(c1, "CAD") #=> #<Money fractional:12451 currency:CAD>
84
101
  #
85
102
  # # Exchange 100 CAD to USD:
86
- # bank.exchange_with(c2, "USD") #=> #<Money @fractional=803115>
103
+ # bank.exchange_with(c2, "USD") #=> #<Money fractional:8031 currency:USD>
87
104
  def exchange_with(from, to_currency, &block)
88
105
  to_currency = Currency.wrap(to_currency)
89
106
  if from.currency == to_currency
@@ -114,11 +131,12 @@ class Money
114
131
  elsif @rounding_method
115
132
  @rounding_method.call(ex)
116
133
  else
117
- ex.to_s.to_i
134
+ ex.to_s.to_d
118
135
  end
119
136
  end
120
137
 
121
138
  # Registers a conversion rate and returns it (uses +#set_rate+).
139
+ # Delegates to +Money::RatesStore::Memory+
122
140
  #
123
141
  # @param [Currency, String, Symbol] from Currency to exchange from.
124
142
  # @param [Currency, String, Symbol] to Currency to exchange to.
@@ -134,14 +152,14 @@ class Money
134
152
  set_rate(from, to, rate)
135
153
  end
136
154
 
137
- # Set the rate for the given currencies. Uses +Mutex+ to synchronize data
155
+ # Set the rate for the given currencies.
138
156
  # access.
157
+ # Delegates to +Money::RatesStore::Memory+
139
158
  #
140
159
  # @param [Currency, String, Symbol] from Currency to exchange from.
141
160
  # @param [Currency, String, Symbol] to Currency to exchange to.
142
161
  # @param [Numeric] rate Rate to use when exchanging currencies.
143
- # @param [Hash] opts Options hash to set special parameters
144
- # @option opts [Boolean] :without_mutex disables the usage of a mutex
162
+ # @param [Hash] opts Options hash to set special parameters. Backwards compatibility only.
145
163
  #
146
164
  # @return [Numeric]
147
165
  #
@@ -150,21 +168,16 @@ class Money
150
168
  # bank.set_rate("USD", "CAD", 1.24515)
151
169
  # bank.set_rate("CAD", "USD", 0.803115)
152
170
  def set_rate(from, to, rate, opts = {})
153
- fn = -> { @rates[rate_key_for(from, to)] = rate }
154
- if opts[:without_mutex]
155
- fn.call
156
- else
157
- @mutex.synchronize { fn.call }
158
- end
171
+ store.add_rate(Currency.wrap(from).iso_code, Currency.wrap(to).iso_code, rate)
159
172
  end
160
173
 
161
- # Retrieve the rate for the given currencies. Uses +Mutex+ to synchronize
174
+ # Retrieve the rate for the given currencies.
162
175
  # data access.
176
+ # Delegates to +Money::RatesStore::Memory+
163
177
  #
164
178
  # @param [Currency, String, Symbol] from Currency to exchange from.
165
179
  # @param [Currency, String, Symbol] to Currency to exchange to.
166
- # @param [Hash] opts Options hash to set special parameters
167
- # @option opts [Boolean] :without_mutex disables the usage of a mutex
180
+ # @param [Hash] opts Options hash to set special parameters. Backwards compatibility only.
168
181
  #
169
182
  # @return [Numeric]
170
183
  #
@@ -176,12 +189,7 @@ class Money
176
189
  # bank.get_rate("USD", "CAD") #=> 1.24515
177
190
  # bank.get_rate("CAD", "USD") #=> 0.803115
178
191
  def get_rate(from, to, opts = {})
179
- fn = -> { @rates[rate_key_for(from, to)] }
180
- if opts[:without_mutex]
181
- fn.call
182
- else
183
- @mutex.synchronize { fn.call }
184
- end
192
+ store.get_rate(Currency.wrap(from).iso_code, Currency.wrap(to).iso_code)
185
193
  end
186
194
 
187
195
  # Return the known rates as a string in the format specified. If +file+
@@ -190,8 +198,7 @@ class Money
190
198
  #
191
199
  # @param [Symbol] format Request format for the resulting string.
192
200
  # @param [String] file Optional file location to write the rates to.
193
- # @param [Hash] opts Options hash to set special parameters
194
- # @option opts [Boolean] :without_mutex disables the usage of a mutex
201
+ # @param [Hash] opts Options hash to set special parameters. Backwards compatibility only.
195
202
  #
196
203
  # @return [String]
197
204
  #
@@ -208,36 +215,38 @@ class Money
208
215
  raise Money::Bank::UnknownRateFormat unless
209
216
  RATE_FORMATS.include? format
210
217
 
211
- s = ""
212
- fn = -> {
218
+ store.transaction do
213
219
  s = case format
214
- when :json
215
- JSON.dump(@rates)
216
- when :ruby
217
- Marshal.dump(@rates)
218
- when :yaml
219
- YAML.dump(@rates)
220
- end
220
+ when :json
221
+ JSON.dump(rates)
222
+ when :ruby
223
+ Marshal.dump(rates)
224
+ when :yaml
225
+ YAML.dump(rates)
226
+ end
221
227
 
222
228
  unless file.nil?
223
229
  File.open(file, "w") {|f| f.write(s) }
224
230
  end
225
- }
226
- if opts[:without_mutex]
227
- fn.call
228
- else
229
- @mutex.synchronize { fn.call }
231
+
232
+ s
233
+ end
234
+ end
235
+
236
+ # This should be deprecated.
237
+ def rates
238
+ store.each_rate.each_with_object({}) do |(from,to,rate),hash|
239
+ hash[[from, to].join(SERIALIZER_SEPARATOR)] = rate
230
240
  end
231
- s
232
241
  end
233
242
 
234
243
  # Loads rates provided in +s+ given the specified format. Available
235
244
  # formats are +:json+, +:ruby+ and +:yaml+.
245
+ # Delegates to +Money::RatesStore::Memory+
236
246
  #
237
247
  # @param [Symbol] format The format of +s+.
238
248
  # @param [String] s The rates string.
239
- # @param [Hash] opts Options hash to set special parameters
240
- # @option opts [Boolean] :without_mutex disables the usage of a mutex
249
+ # @param [Hash] opts Options hash to set special parameters. Backwards compatibility only.
241
250
  #
242
251
  # @return [self]
243
252
  #
@@ -254,37 +263,23 @@ class Money
254
263
  raise Money::Bank::UnknownRateFormat unless
255
264
  RATE_FORMATS.include? format
256
265
 
257
- fn = -> {
258
- @rates = case format
259
- when :json
260
- JSON.load(s)
261
- when :ruby
262
- Marshal.load(s)
263
- when :yaml
264
- YAML.load(s)
265
- end
266
- }
267
- if opts[:without_mutex]
268
- fn.call
269
- else
270
- @mutex.synchronize { fn.call }
271
- end
272
- self
273
- end
266
+ store.transaction do
267
+ data = case format
268
+ when :json
269
+ JSON.load(s)
270
+ when :ruby
271
+ Marshal.load(s)
272
+ when :yaml
273
+ YAML.load(s)
274
+ end
274
275
 
275
- private
276
+ data.each do |key, rate|
277
+ from, to = key.split(SERIALIZER_SEPARATOR)
278
+ store.add_rate from, to, rate
279
+ end
280
+ end
276
281
 
277
- # Return the rate hashkey for the given currencies.
278
- #
279
- # @param [Currency, String, Symbol] from The currency to exchange from.
280
- # @param [Currency, String, Symbol] to The currency to exchange to.
281
- #
282
- # @return [String]
283
- #
284
- # @example
285
- # rate_key_for("USD", "CAD") #=> "USD_TO_CAD"
286
- def rate_key_for(from, to)
287
- "#{Currency.wrap(from).iso_code}_TO_#{Currency.wrap(to).iso_code}".upcase
282
+ self
288
283
  end
289
284
  end
290
285
  end