I think there are many products that manage money using RubyMoney. RubyMoney provides a currency setting by default, but you can override that setting if you wish. In many systems, once you set the settings when building the app, you will not change the settings after that, but in the context of testing, you may want to initialize the settings once changed. Isn't there?
In this article, I will explain how to initialize the currency setting of RubyMoney in such a case.
As a premise, set the currency as follows.
cad = Money::Currency.find(:cad)
cad.name # => Canadian Dollar
Money::Currency.register(
:priority => cad.priority,
:iso_code => cad.iso_code,
:name => 'Something Different',
:subunit => cad.subunit,
:subunit_to_unit => cad.subunit_to_unit,
:thousands_separator => cad.thousands_separator,
:decimal_mark => cad.decimal_mark
)
cad = Money::Currency.find(:cad)
cad.name # => Something Different
The Money :: Currency
class manages currency settings with an instance variable called @ table
. Therefore, it would be nice if this instance variable could be reset.
However, due to the specifications, @ table
cannot be accessed directly, so initialize it as follows.
Money::Currency.instance_variable_set('@table', nil)
Money::Currency.table # => reloading the initial setting
It's easy. However, even after performing the above initialization, I still receive the overwritten value.
cad = Money::Currency.find(:cad)
cad.name # => Something Different
Money::Currency.instance_variable_set('@table', nil)
Money::Currency.table
cad = Money::Currency.find(:cad)
cad.name # => Something Different.Not initialized!
Follow the library implementation in detail to find the answer. Once changed, the settings must be consistent after the application is launched, that is, from the start of the Ruby process to the end of that process.
To implement that specification, Money :: Currency
also manages the instance itself as a class variable.
That way, as library users, we don't have to worry about the settings under development.
With that in mind, the improved code is below.
cad.name # => Something Different
Money::Currency.class_variable_set('@@instances', {})
Money::Currency.instance_variable_set('@table', nil)
Money::Currency.table
cad = Money::Currency.find(:cad)
cad.name # => Canadian Dollar
It has been successfully initialized, and if you write this code in spec_helper etc., you can guarantee the test that does not depend on the setting override of Money :: Currency
under test.
But it's a hassle to write this setting.
In fact, the latest RubyMoney :: Money
master provides an APIMoney :: Currency.reset!
To do this initialization.
This is the pull request for that change.
If you want to use this feature, please install the latest master.
We hope that the next updated version of RubyMoney :: Money
will be released soon.
English version is here
Recommended Posts