exchange 1.1.0 → 1.1.1

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: 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