exchange 1.1.0 → 1.1.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0a30e01a5f55d57a9201b8da420a8c3849ca73c6
4
- data.tar.gz: 3fde15afd9be50c593edab5bf94f517cc55e24b2
3
+ metadata.gz: 91f5a8992aa043b158277a444d70b03dcc83dba6
4
+ data.tar.gz: 1666ddfa3deca602192b2ac49a9171f329b25d9c
5
5
  SHA512:
6
- metadata.gz: ef1eafc5d5d39a7e68508285e6c2b1dfd194034fd11792106180d63265b1ad500d0c362f2c77cb35aaa510f47412704559b09c47fbcd210afee3f398d319f2f6
7
- data.tar.gz: 27dce37969266711bbba84ddb2777e78b25fc3bca17092364ca0baadb787fa92843904b2020224c338d2d47c2d67907a917caf3b7bbaa0fd0cdae670c4bb60ea
6
+ metadata.gz: d301bbf1ef608479b9b51e5ca4eab45f1a35c62265f445c37f1c82e628aa8a884f4063fc3f6865c2afdd593c429f30fe32f2b26d629856ef36f59478d4fcba90
7
+ data.tar.gz: 6c51362dfbdb84d89feb15d8c4b9a34f01bf39cded31ae93ea50dfbc6930ea461d2c1f11e0b13da61a83ced54581f01ca6ef0e2e01ec02e54ccb369a1e250db6
@@ -4,6 +4,7 @@ rvm:
4
4
  - 1.9.3
5
5
  - 2.0.0
6
6
  - rbx-19mode
7
+ - rbx-20mode
7
8
  - jruby-19mode
8
9
  - jruby-20mode
9
10
 
@@ -1,6 +1,6 @@
1
1
  = exchange {<img src="https://secure.travis-ci.org/beatrichartz/exchange.png?branch=master" />}[http://travis-ci.org/beatrichartz/exchange] {<img src="https://gemnasium.com/beatrichartz/exchange.png" alt="Dependency Status" />}[https://gemnasium.com/beatrichartz/exchange] {<img src="https://codeclimate.com/github/beatrichartz/exchange.png" />}[https://codeclimate.com/github/beatrichartz/exchange]
2
2
 
3
- The Exchange Gem gives you easy access to currency functions directly on your Numbers. {It is tested against}[http://travis-ci.org/beatrichartz/exchange]: ruby 2.0, 1.9, ruby 1.8, ree and rubinius (1.8 and 1.9 mode). Exchange will in future versions take advantage of 2.0 features, be sure to check this page for updates!
3
+ The Exchange Gem gives you easy access to currency functions directly on your Numbers. {It is tested against}[http://travis-ci.org/beatrichartz/exchange]: ruby 2.0, 1.9, ree and rubinius (1.9 and 2.0 mode). Exchange will in future versions take advantage of 2.1 features like refinements, be sure to check this page for updates!
4
4
 
5
5
  You can use it with just plain ruby projects, in Rails 2 and 3, Sinatra or whatever Framework you like.
6
6
 
@@ -9,7 +9,7 @@ You can use it with just plain ruby projects, in Rails 2 and 3, Sinatra or whate
9
9
  == Installation
10
10
  === Bundler / Rails
11
11
  Add it to your Gemfile
12
- gem "exchange", ">= 0.10.0"
12
+ gem "exchange", ">= 1.1.0"
13
13
  === Manually
14
14
  Just install it as a gem
15
15
  gem install exchange
@@ -52,7 +52,7 @@ Exchange uses BigDecimal in all its currency and conversion operations, so you w
52
52
 
53
53
  === BigDecimal? Sounds slow to me
54
54
 
55
- If performance combined with conversion is your concern, {head over to this benchmark}[https://github.com/beatrichartz/exchange/blob/master/benchmark/benchmark.rb]. With ruby 1.9.3, you'll get about the following results
55
+ If performance combined with conversion is your concern, don't worry. With ruby 1.9.3, you'll get about the following results for money instantiation (e.g. 1.in(:eur))
56
56
 
57
57
  1000 operations
58
58
 
@@ -426,6 +426,6 @@ Please note that only open source APIs can be accepted as contributions to this
426
426
 
427
427
  == Copyright
428
428
 
429
- Copyright (c) 2012 Beat Richartz. See LICENSE.txt for
429
+ Copyright (c) 2013 Beat Richartz. See LICENSE.txt for
430
430
  further details.
431
431
 
@@ -8,7 +8,7 @@ Gem::Specification.new do |s|
8
8
  s.authors = ["Beat Richartz"]
9
9
  s.description = "Simple Money handling for your ruby app – ISO4217-compatible Currency instantiation, conversion, string formatting and more via an intuitive DSL: 1.in(:usd).to(:eur)"
10
10
  s.email = "attr_accessor@gmail.com"
11
- s.homepage = "http://beatrichartz.github.com/exchange"
11
+ s.homepage = "http://beatrichartz.github.io/exchange"
12
12
  s.licenses = ["MIT"]
13
13
  s.require_paths = ["lib"]
14
14
  s.summary = "Simple Money handling for your ruby app"
@@ -3,7 +3,7 @@ module Exchange
3
3
 
4
4
  # The current version of the exchange gem
5
5
  #
6
- VERSION = '1.1.0'
6
+ VERSION = '1.1.1'
7
7
 
8
8
  # The root installation path of the gem
9
9
  # @version 0.5
@@ -8,8 +8,8 @@ module Exchange
8
8
  # Installs a method chain that overwrites the old error prone meth with the new one
9
9
  #
10
10
  def self.money_error_preventing_method_chain base, meth
11
- base.send :alias_method, :"#{meth}with_errors", meth
12
- base.send :alias_method, meth, :"#{meth}without_errors"
11
+ base.send :alias_method, :"#{meth}_with_errors", meth
12
+ base.send :alias_method, meth, :"#{meth}_without_errors"
13
13
  end
14
14
 
15
15
  # @!macro prevent_errors_with_exchange_for
@@ -18,11 +18,11 @@ module Exchange
18
18
  # @method $1(other)
19
19
  #
20
20
  def self.prevent_errors_with_exchange_for base, meth
21
- base.send(:define_method, :"#{meth}without_errors", lambda { |other|
21
+ base.send(:define_method, :"#{meth}_without_errors", lambda { |other|
22
22
  if other.is_a?(Exchange::Money)
23
23
  BigDecimal.new(self.to_s).send(meth, other.value).to_f
24
24
  else
25
- send(:"#{meth}with_errors", other)
25
+ send(:"#{meth}_with_errors", other)
26
26
  end
27
27
  })
28
28
  money_error_preventing_method_chain base, meth
@@ -180,19 +180,35 @@ module Exchange
180
180
  new_hsh
181
181
  end
182
182
 
183
- # Interpolates a string with separators every 3 characters
184
- #
185
-
186
183
  # get a precision for a specified amount and a specified currency
184
+ #
187
185
  # @params [Float, Integer] amount The amount to get the precision for
188
186
  # @params [Symbol] currency the currency to get the precision for
189
187
  #
190
188
  def precision_for amount, currency
191
189
  defined_minor_precision = definitions[currency][:minor_unit]
192
- given_major_precision, given_minor_precision = amount.to_s.match(/^-?(\d*)\.?(\d*)$/).to_a[1..2].map(&:size)
190
+ match = amount.to_s.match(/^-?(\d*)\.?(\d*)e?(-?\d+)?$/).to_a[1..3]
191
+ given_major_precision, given_minor_precision = precision_from_match *match
193
192
 
194
193
  given_major_precision + [defined_minor_precision, given_minor_precision].max
195
194
  end
196
195
 
196
+ # Get the precision from a match with /^-?(\d*)\.?(\d*)e?(-?\d+)?$/
197
+ #
198
+ # @params [String] major The major amount of the match as a string
199
+ # @params [String] minor The minor amount of the match as a string
200
+ # @params [String] rational The rational of the match as a string
201
+ # @return [Array] An array containing the major and the minor precision in this order
202
+ #
203
+ def precision_from_match major, minor, rational=nil
204
+ if rational
205
+ leftover_minor_precision = minor.eql?('0') ? 0 : minor.size
206
+ rational_precision = rational.delete('-').to_i
207
+ [major.size, leftover_minor_precision.send(rational.start_with?('-') ? :+ : :-, rational_precision)]
208
+ else
209
+ [major, minor].map(&:size)
210
+ end
211
+ end
212
+
197
213
  end
198
214
  end
@@ -86,7 +86,7 @@ module Exchange
86
86
  def to other, options={}
87
87
  other = ISO.assert_currency!(other)
88
88
 
89
- if api_supports_currency?(other) && api_supports_currency?(currency)
89
+ if api_supports_currency?(currency) && api_supports_currency?(other)
90
90
  opts = { :at => time, :from => self }.merge(options)
91
91
  Money.new(api.new.convert(value, currency, other, opts), other, opts)
92
92
  elsif fallback!
@@ -6,7 +6,7 @@ describe "Exchange::Cache::Base" do
6
6
  describe "key generation" do
7
7
  before(:each) do
8
8
  time = Time.gm 2012, 03, 01, 23, 23, 23
9
- Time.stub! :now => time
9
+ Time.stub :now => time
10
10
  end
11
11
  context "with a daily cache" do
12
12
  it "should build a timestamped key with the class given, the yearday and the year" do
@@ -15,7 +15,7 @@ describe "Exchange::CacheDalli::Client" do
15
15
  Exchange.configuration.reset
16
16
  end
17
17
  describe "client" do
18
- let(:client) { mock('memcached') }
18
+ let(:client) { double('memcached') }
19
19
  before(:each) do
20
20
  Exchange::GemLoader.new('dalli').try_load
21
21
  end
@@ -28,7 +28,7 @@ describe "Exchange::CacheDalli::Client" do
28
28
  end
29
29
  end
30
30
  describe "wipe_client!" do
31
- let(:client) { mock('memcached') }
31
+ let(:client) { double('memcached') }
32
32
 
33
33
  it "should set the client to nil" do
34
34
  Dalli::Client.should_receive(:new).with("HOST:PORT").and_return(client)
@@ -38,7 +38,7 @@ describe "Exchange::CacheDalli::Client" do
38
38
  end
39
39
  end
40
40
  describe "cached" do
41
- let(:client) { mock('memcached', :get => '') }
41
+ let(:client) { double('memcached', :get => '') }
42
42
  before(:each) do
43
43
  Dalli::Client.should_receive(:new).with("HOST:PORT").and_return(client)
44
44
  end
@@ -69,7 +69,7 @@ describe "Exchange::CacheDalli::Client" do
69
69
  end
70
70
  end
71
71
  context "when no cached result exists" do
72
- let(:client) { mock('memcached') }
72
+ let(:client) { double('memcached') }
73
73
  context "when returning nil" do
74
74
  before(:each) do
75
75
  subject.should_receive(:key).with('API_CLASS', {}).twice.and_return('KEY')
@@ -15,7 +15,7 @@ describe "Exchange::Cache::Memory" do
15
15
  context "with a class" do
16
16
  before(:each) do
17
17
  @time = Time.gm(2012,10,10,12)
18
- Time.stub! :now => @time
18
+ Time.stub :now => @time
19
19
  end
20
20
  it "should yield a valid instance variable name" do
21
21
  subject.send(:instance_variable_name, Exchange::ExternalAPI::Ecb, {}).should == '@exchange_externalapi_ecb_2012_284_2012_284'
@@ -25,7 +25,7 @@ describe "Exchange::Cache::Memory" do
25
25
  describe "clean_out_cache" do
26
26
  before(:each) do
27
27
  @time = Time.gm(2012,10,10,12)
28
- Time.stub! :now => @time
28
+ Time.stub :now => @time
29
29
  subject.instance_variable_set '@exchange_externalapi_someapi_2011_284_2011_284_chfeur', 'Expired'
30
30
  subject.instance_variable_set '@exchange_externalapi_someapi_2010_284_2012_284_chfeur', 'Valid1'
31
31
  subject.instance_variable_set '@exchange_externalapi_ecb_2012_283_2011_283', 'Expired'
@@ -18,7 +18,7 @@ describe "Exchange::Cache::Rails" do
18
18
  Exchange.configuration.reset
19
19
  end
20
20
  describe "client" do
21
- let(:client) { mock('rails_cache') }
21
+ let(:client) { double('rails_cache') }
22
22
  it "should set up a client on the specified host and port for the cache" do
23
23
  ::Rails.should_receive(:cache).and_return(client)
24
24
  subject.client.should == client
@@ -29,7 +29,7 @@ describe "Exchange::Cache::Rails" do
29
29
  lambda { subject.cached('API_CLASS') }.should raise_error(Exchange::Cache::CachingWithoutBlockError)
30
30
  end
31
31
  context "when a result is returned" do
32
- let(:client) { mock('rails_cache') }
32
+ let(:client) { double('rails_cache') }
33
33
  context "with a daily cache" do
34
34
  before(:each) do
35
35
  subject.should_receive(:key).with('API_CLASS', {}).and_return('KEY')
@@ -56,7 +56,7 @@ describe "Exchange::Cache::Rails" do
56
56
  end
57
57
  end
58
58
  context "when no result is returned" do
59
- let(:client) { mock('rails_cache') }
59
+ let(:client) { double('rails_cache') }
60
60
  before(:each) do
61
61
  subject.should_receive(:key).with('API_CLASS', {}).at_most(3).times.and_return('KEY')
62
62
  ::Rails.should_receive(:cache).twice.and_return(client)
@@ -17,7 +17,7 @@ describe "Exchange::Cache::Redis" do
17
17
  Exchange.configuration.reset
18
18
  end
19
19
  describe "client" do
20
- let(:client) { mock('redis') }
20
+ let(:client) { double('redis') }
21
21
  after(:each) do
22
22
  subject.instance_variable_set "@client", nil
23
23
  end
@@ -27,7 +27,7 @@ describe "Exchange::Cache::Redis" do
27
27
  end
28
28
  end
29
29
  describe "cached" do
30
- let(:client) { mock('redis', :get => nil) }
30
+ let(:client) { double('redis', :get => nil) }
31
31
  before(:each) do
32
32
  ::Redis.should_receive(:new).with(:host => 'HOST', :port => 'PORT').and_return(client)
33
33
  end
@@ -7,7 +7,7 @@ describe "Exchange::ErrorSafe" do
7
7
  end
8
8
  before(:each) do
9
9
  @time = Time.gm(2012,8,27)
10
- Time.stub! :now => @time
10
+ Time.stub :now => @time
11
11
  end
12
12
  after(:all) do
13
13
  Exchange.configuration.reset
@@ -7,7 +7,7 @@ describe "Exchange::Conversability" do
7
7
  end
8
8
  before(:each) do
9
9
  @time = Time.gm(2012,8,27)
10
- Time.stub! :now => @time
10
+ Time.stub :now => @time
11
11
  end
12
12
  after(:all) do
13
13
  Exchange.configuration.reset
@@ -27,7 +27,7 @@ describe "Exchange::ExternalAPI::Call" do
27
27
  @count = 0
28
28
  @uri_mock.should_receive(:open).at_most(3).times.and_return do
29
29
  @count += 1
30
- @count == 3 ? mock('opened', :read => fixture('api_responses/example_json_api.json')) : raise(OpenURI::HTTPError.new('404', 'URI'))
30
+ @count == 3 ? double('opened', :read => fixture('api_responses/example_json_api.json')) : raise(OpenURI::HTTPError.new('404', 'URI'))
31
31
  end
32
32
  Exchange::ExternalAPI::Call.new('JSON_API') do |result|
33
33
  result.should == JSON.load(fixture('api_responses/example_json_api.json'))
@@ -62,7 +62,7 @@ describe "Exchange::ExternalAPI::Call" do
62
62
  @count = 0
63
63
  @uri_mock.should_receive(:open).at_most(3).times.and_return do
64
64
  @count += 1
65
- @count == 3 ? mock('opened', :read => fixture('api_responses/example_xml_api.xml')) : raise(OpenURI::HTTPError.new('404', 'URI'))
65
+ @count == 3 ? double('opened', :read => fixture('api_responses/example_xml_api.xml')) : raise(OpenURI::HTTPError.new('404', 'URI'))
66
66
  end
67
67
  Exchange::ExternalAPI::Call.new('XML_API', :format => :xml) do |result|
68
68
  result.to_s.should == Nokogiri::XML.parse(fixture('api_responses/example_xml_api.xml').sub("\n", '')).to_s
@@ -14,7 +14,7 @@ describe "Exchange::ExternalAPI::Ecb" do
14
14
  end
15
15
  before(:each) do
16
16
  time = Time.gm(2012,2,3)
17
- Time.stub! :now => time
17
+ Time.stub :now => time
18
18
  end
19
19
  describe "updating rates" do
20
20
  subject { Exchange::ExternalAPI::Ecb.new }
@@ -23,7 +23,7 @@ describe "Exchange::ExternalAPI::OpenExchangeRates" do
23
23
  end
24
24
  it "should set the timestamp from time.now" do
25
25
  time = Time.now
26
- time.stub! :now => time
26
+ time.stub :now => time
27
27
  subject.update
28
28
  subject.timestamp.should == time.to_i
29
29
  end
@@ -6,7 +6,7 @@ describe "Exchange::Helper" do
6
6
  describe "assure_time" do
7
7
  before(:each) do
8
8
  time = Time.now
9
- Time.stub! :now => time
9
+ Time.stub :now => time
10
10
  end
11
11
  context "with a time object" do
12
12
  it "should return that time object" do
@@ -737,6 +737,32 @@ describe "Exchange::ISO" do
737
737
  end
738
738
  end
739
739
  end
740
+ context "given a float with scientific notation" do
741
+ context "with bigger precision than the definition" do
742
+ it "should instantiate a big decimal with the given precision" do
743
+ BigDecimal.should_receive(:new).with("6.0e-05",6).and_return('INSTANCE')
744
+ subject.instantiate(6.0e-05, :tnd).should == 'INSTANCE'
745
+ BigDecimal.should_receive(:new).with("600000.0",8).and_return('INSTANCE')
746
+ subject.instantiate(6.0e05, :sar).should == 'INSTANCE'
747
+ BigDecimal.should_receive(:new).with("1.456e-08",12).and_return('INSTANCE')
748
+ subject.instantiate(1.456e-08, :omr).should == 'INSTANCE'
749
+ BigDecimal.should_receive(:new).with("145600000.0",12).and_return('INSTANCE')
750
+ subject.instantiate(1.456e08, :omr).should == 'INSTANCE'
751
+ end
752
+ end
753
+ context "with smaller precision than the definition" do
754
+ it "should instantiate a big decimal with the defined precision" do
755
+ BigDecimal.should_receive(:new).with("0.6",4).and_return('INSTANCE')
756
+ subject.instantiate(6.0e-01, :tnd).should == 'INSTANCE'
757
+ BigDecimal.should_receive(:new).with("60.0",4).and_return('INSTANCE')
758
+ subject.instantiate(6.0e01, :sar).should == 'INSTANCE'
759
+ BigDecimal.should_receive(:new).with("0.14",4).and_return('INSTANCE')
760
+ subject.instantiate(1.4e-01, :omr).should == 'INSTANCE'
761
+ BigDecimal.should_receive(:new).with("14.56",5).and_return('INSTANCE')
762
+ subject.instantiate(1.456e01, :omr).should == 'INSTANCE'
763
+ end
764
+ end
765
+ end
740
766
  context "given a big decimal" do
741
767
  let!(:bigdecimal) { BigDecimal.new("23.23") }
742
768
  it "should instantiate a big decimal according to the iso standards" do
@@ -92,7 +92,7 @@ describe "Exchange::Money" do
92
92
  context "with a 'to' currency not provided by the given api" do
93
93
  context "but provided by a fallback api" do
94
94
  it "should use the fallback" do
95
- subject.api::CURRENCIES.stub! :include? => false
95
+ subject.api::CURRENCIES.stub :include? => false
96
96
  mock_api("http://api.finance.xaviermedia.com/api/#{Time.now.strftime("%Y/%m/%d")}.xml", fixture('api_responses/example_xml_api.xml'), 3)
97
97
  subject.to(:chf).value.round(2).should == 36.36
98
98
  subject.to(:chf).currency.should == :chf
@@ -101,9 +101,9 @@ describe "Exchange::Money" do
101
101
  end
102
102
  context "but not provided by any fallback api" do
103
103
  it "should raise the no rate error" do
104
- Exchange::ExternalAPI::OpenExchangeRates::CURRENCIES.stub! :include? => false
105
- Exchange::ExternalAPI::XavierMedia::CURRENCIES.stub! :include? => false
106
- Exchange::ExternalAPI::Ecb::CURRENCIES.stub! :include? => false
104
+ Exchange::ExternalAPI::OpenExchangeRates::CURRENCIES.stub :include? => false
105
+ Exchange::ExternalAPI::XavierMedia::CURRENCIES.stub :include? => false
106
+ Exchange::ExternalAPI::Ecb::CURRENCIES.stub :include? => false
107
107
  lambda { subject.to(:xaf) }.should raise_error Exchange::NoRateError
108
108
  end
109
109
  end
@@ -21,7 +21,7 @@ module HelperMethods
21
21
  end
22
22
 
23
23
  def mock_api(adress, response, count=1)
24
- @uri_mock = mock('uri', :open => mock('opened_uri', :read => response))
24
+ @uri_mock = double('uri', :open => double('opened_uri', :read => response))
25
25
  URI.should_receive(:parse).with(adress).at_most(count).times.and_return(@uri_mock)
26
26
  end
27
27
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: exchange
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Beat Richartz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-29 00:00:00.000000000 Z
11
+ date: 2013-11-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -155,7 +155,7 @@ files:
155
155
  - spec/support/api_responses/example_historic_json.json
156
156
  - spec/support/api_responses/example_json_api.json
157
157
  - spec/support/api_responses/example_xml_api.xml
158
- homepage: http://beatrichartz.github.com/exchange
158
+ homepage: http://beatrichartz.github.io/exchange
159
159
  licenses:
160
160
  - MIT
161
161
  metadata: {}
@@ -175,7 +175,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
175
175
  version: '0'
176
176
  requirements: []
177
177
  rubyforge_project:
178
- rubygems_version: 2.0.3
178
+ rubygems_version: 2.0.7
179
179
  signing_key:
180
180
  specification_version: 4
181
181
  summary: Simple Money handling for your ruby app