exchange 0.12.0 → 1.0.0

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.
Files changed (69) hide show
  1. data/.travis.yml +1 -0
  2. data/README.rdoc +34 -6
  3. data/Rakefile +3 -30
  4. data/changelog.rdoc +6 -0
  5. data/exchange.gemspec +3 -6
  6. data/iso4217.yml +238 -81
  7. data/lib/exchange.rb +2 -1
  8. data/lib/exchange/base.rb +3 -2
  9. data/lib/exchange/cache.rb +1 -0
  10. data/lib/exchange/cache/base.rb +2 -1
  11. data/lib/exchange/cache/configuration.rb +2 -1
  12. data/lib/exchange/cache/file.rb +2 -1
  13. data/lib/exchange/cache/memcached.rb +2 -1
  14. data/lib/exchange/cache/memory.rb +2 -1
  15. data/lib/exchange/cache/no_cache.rb +2 -1
  16. data/lib/exchange/cache/rails.rb +2 -1
  17. data/lib/exchange/cache/redis.rb +2 -1
  18. data/lib/exchange/configurable.rb +3 -2
  19. data/lib/exchange/configuration.rb +8 -5
  20. data/lib/exchange/core_extensions.rb +2 -1
  21. data/lib/exchange/core_extensions/cachify.rb +2 -1
  22. data/lib/exchange/core_extensions/float/error_safe.rb +2 -1
  23. data/lib/exchange/core_extensions/numeric/conversability.rb +2 -1
  24. data/lib/exchange/external_api.rb +3 -1
  25. data/lib/exchange/external_api/base.rb +2 -1
  26. data/lib/exchange/external_api/call.rb +2 -1
  27. data/lib/exchange/external_api/configuration.rb +18 -3
  28. data/lib/exchange/external_api/ecb.rb +2 -1
  29. data/lib/exchange/external_api/json.rb +2 -1
  30. data/lib/exchange/external_api/open_exchange_rates.rb +2 -1
  31. data/lib/exchange/external_api/random.rb +31 -0
  32. data/lib/exchange/external_api/xavier_media.rb +2 -1
  33. data/lib/exchange/external_api/xml.rb +2 -1
  34. data/lib/exchange/gem_loader.rb +2 -1
  35. data/lib/exchange/helper.rb +2 -1
  36. data/lib/exchange/iso.rb +29 -13
  37. data/lib/exchange/money.rb +35 -9
  38. data/lib/exchange/typecasting.rb +2 -1
  39. data/spec/exchange/cache/base_spec.rb +2 -1
  40. data/spec/exchange/cache/configuration_spec.rb +4 -1
  41. data/spec/exchange/cache/file_spec.rb +2 -1
  42. data/spec/exchange/cache/memcached_spec.rb +2 -1
  43. data/spec/exchange/cache/memory_spec.rb +4 -2
  44. data/spec/exchange/cache/no_cache_spec.rb +2 -1
  45. data/spec/exchange/cache/rails_spec.rb +2 -1
  46. data/spec/exchange/cache/redis_spec.rb +2 -1
  47. data/spec/exchange/configuration_spec.rb +6 -2
  48. data/spec/exchange/core_extensions/array/cachify_spec.rb +2 -1
  49. data/spec/exchange/core_extensions/float/error_safe_spec.rb +2 -1
  50. data/spec/exchange/core_extensions/hash/cachify_spec.rb +2 -1
  51. data/spec/exchange/core_extensions/numeric/cachify_spec.rb +2 -1
  52. data/spec/exchange/core_extensions/numeric/conversability_spec.rb +2 -1
  53. data/spec/exchange/core_extensions/string/cachify_spec.rb +2 -1
  54. data/spec/exchange/core_extensions/symbol/cachify_spec.rb +2 -1
  55. data/spec/exchange/external_api/base_spec.rb +2 -1
  56. data/spec/exchange/external_api/call_spec.rb +2 -1
  57. data/spec/exchange/external_api/configuration_spec.rb +18 -2
  58. data/spec/exchange/external_api/ecb_spec.rb +2 -1
  59. data/spec/exchange/external_api/open_exchange_rates_spec.rb +2 -1
  60. data/spec/exchange/external_api/random_spec.rb +40 -0
  61. data/spec/exchange/external_api/xavier_media_spec.rb +2 -1
  62. data/spec/exchange/gem_loader_spec.rb +2 -1
  63. data/spec/exchange/helper_spec.rb +2 -1
  64. data/spec/exchange/iso_spec.rb +214 -189
  65. data/spec/exchange/money_spec.rb +65 -2
  66. data/spec/exchange/typecasting_spec.rb +2 -1
  67. data/spec/spec_helper.rb +3 -1
  68. metadata +10 -10
  69. data/benchmark/benchmark.rb +0 -50
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  require 'spec_helper'
2
3
 
3
4
  describe "Exchange::Money" do
@@ -5,7 +6,8 @@ describe "Exchange::Money" do
5
6
  before(:all) do
6
7
  Exchange.configuration = Exchange::Configuration.new do |c|
7
8
  c.api = {
8
- :subclass => :open_exchange_rates
9
+ :subclass => :open_exchange_rates,
10
+ :fallback => [:xavier_media, :ecb]
9
11
  }
10
12
  c.cache = {
11
13
  :subclass => :no_cache
@@ -54,6 +56,44 @@ describe "Exchange::Money" do
54
56
  subject.to(:ch).should be_kind_of Exchange::Money
55
57
  end
56
58
  end
59
+ context "when an api is not reachable" do
60
+ context "and a fallback api is" do
61
+ it "should use the fallback " do
62
+ URI.should_receive(:parse).with("http://openexchangerates.org/api/latest.json?app_id=").once.and_raise Exchange::ExternalAPI::APIError
63
+ mock_api("http://api.finance.xaviermedia.com/api/#{Time.now.strftime("%Y/%m/%d")}.xml", fixture('api_responses/example_xml_api.xml'), 3)
64
+ subject.to(:ch).value.round(2).should == 36.36
65
+ subject.to(:ch).currency.should == :chf
66
+ subject.to(:ch).should be_kind_of Exchange::Money
67
+ end
68
+ end
69
+ context "and no fallback api is" do
70
+ it "should raise the api error" do
71
+ URI.should_receive(:parse).with("http://openexchangerates.org/api/latest.json?app_id=").once.and_raise Exchange::ExternalAPI::APIError
72
+ URI.should_receive(:parse).with("http://api.finance.xaviermedia.com/api/#{Time.now.strftime("%Y/%m/%d")}.xml").once.and_raise Exchange::ExternalAPI::APIError
73
+ URI.should_receive(:parse).with("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist-90d.xml").once.and_raise Exchange::ExternalAPI::APIError
74
+ lambda { subject.to(:ch) }.should raise_error Exchange::ExternalAPI::APIError
75
+ end
76
+ end
77
+ end
78
+ context "with a currency not provided by the given api" do
79
+ context "but provided by a fallback api" do
80
+ it "should use the fallback" do
81
+ subject.api::CURRENCIES.stub! :include? => false
82
+ mock_api("http://api.finance.xaviermedia.com/api/#{Time.now.strftime("%Y/%m/%d")}.xml", fixture('api_responses/example_xml_api.xml'), 3)
83
+ subject.to(:ch).value.round(2).should == 36.36
84
+ subject.to(:ch).currency.should == :chf
85
+ subject.to(:ch).should be_kind_of Exchange::Money
86
+ end
87
+ end
88
+ context "but not provided by any fallback api" do
89
+ it "should raise the no rate error" do
90
+ Exchange::ExternalAPI::OpenExchangeRates::CURRENCIES.stub! :include? => false
91
+ Exchange::ExternalAPI::XavierMedia::CURRENCIES.stub! :include? => false
92
+ Exchange::ExternalAPI::Ecb::CURRENCIES.stub! :include? => false
93
+ lambda { subject.to(:xaf) }.should raise_error Exchange::NoRateError
94
+ end
95
+ end
96
+ end
57
97
  end
58
98
  describe "operations" do
59
99
  after(:each) do
@@ -428,6 +468,11 @@ describe "Exchange::Money" do
428
468
  subject.round(2).currency.should == :usd
429
469
  subject.round(2).should be_kind_of Exchange::Money
430
470
  end
471
+ it "should allow for psychological rounding" do
472
+ subject.round(:psych).value.should == 39.99
473
+ subject.round(:psych).currency.should == :usd
474
+ subject.round(:psych).should be_kind_of Exchange::Money
475
+ end
431
476
  end
432
477
  end
433
478
  describe "ceil" do
@@ -454,6 +499,11 @@ describe "Exchange::Money" do
454
499
  subject.ceil(2).currency.should == :omr
455
500
  subject.ceil(2).should be_kind_of Exchange::Money
456
501
  end
502
+ it "should allow for psychological ceiling" do
503
+ subject.ceil(:psych).value.should == 40.999
504
+ subject.ceil(:psych).currency.should == :omr
505
+ subject.ceil(:psych).should be_kind_of Exchange::Money
506
+ end
457
507
  end
458
508
  end
459
509
  describe "floor" do
@@ -480,6 +530,11 @@ describe "Exchange::Money" do
480
530
  subject.floor(2).currency.should == :jpy
481
531
  subject.floor(2).should be_kind_of Exchange::Money
482
532
  end
533
+ it "should allow for psychological flooring" do
534
+ subject.floor(:psych).value.should == 39
535
+ subject.floor(:psych).currency.should == :jpy
536
+ subject.floor(:psych).should be_kind_of Exchange::Money
537
+ end
483
538
  end
484
539
  end
485
540
  end
@@ -500,6 +555,14 @@ describe "Exchange::Money" do
500
555
  Exchange::Money.new(23.4, :sar).to_s(:amount).should == "23.40"
501
556
  Exchange::Money.new(23.0, :clp).to_s(:amount).should == "23"
502
557
  end
558
+ it "should render the currency with a symbol according to ISO 4217 Definitions" do
559
+ Exchange::Money.new(23.232524, :tnd).to_s(:symbol).should == "TND 23.233"
560
+ Exchange::Money.new(23.23252423, :sar).to_s(:symbol).should == "﷼23.23"
561
+ Exchange::Money.new(23.23252423, :clp).to_s(:symbol).should == "$23"
562
+ Exchange::Money.new(23.2, :tnd).to_s(:symbol).should == "TND 23.200"
563
+ Exchange::Money.new(23.4, :sar).to_s(:symbol).should == "﷼23.40"
564
+ Exchange::Money.new(23.0, :clp).to_s(:symbol).should == "$23"
565
+ end
503
566
  end
504
567
  describe "methods via method missing" do
505
568
  it "should be able to convert via to_currency to other currencies" do
@@ -530,4 +593,4 @@ describe "Exchange::Money" do
530
593
  lambda { subject.to_hell }.should raise_error(NoMethodError)
531
594
  end
532
595
  end
533
- end
596
+ end
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  require 'spec_helper'
2
3
 
3
4
  describe "Exchange::Typecasting" do
@@ -83,4 +84,4 @@ describe "Exchange::Typecasting" do
83
84
  end
84
85
  end
85
86
 
86
- end
87
+ end
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
3
  $LOAD_PATH.unshift(File.dirname(__FILE__))
3
4
 
@@ -12,6 +13,7 @@ rescue Bundler::BundlerError => e
12
13
  end
13
14
 
14
15
  require 'exchange'
16
+ require 'dalli'
15
17
 
16
18
  module HelperMethods
17
19
  def fixture(name)
@@ -24,4 +26,4 @@ module HelperMethods
24
26
  end
25
27
  end
26
28
 
27
- RSpec.configuration.include(HelperMethods)
29
+ RSpec.configuration.include(HelperMethods)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: exchange
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.0
4
+ version: 1.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-09 00:00:00.000000000 Z
12
+ date: 2013-03-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri
@@ -75,11 +75,9 @@ dependencies:
75
75
  - - ! '>='
76
76
  - !ruby/object:Gem::Version
77
77
  version: 1.0.0
78
- description: ! "The Exchange Gem gives you easy access to currency functions directly
79
- on your Numbers. Imagine a conversion as easy as \n 1.in(:eur).to(:usd) or even
80
- better \n 1.in(:eur).to(:usd, :at => Time.now - 84600)\n which gets you an exchange
81
- at the rates of yesterday."
82
- email: exchange_gem@gmail.com
78
+ description: ! 'Simple Money handling for your ruby app ISO4217-compatible Currency
79
+ instantiation, conversion, string formatting and more via an intuitive DSL: 1.in(:usd).to(:eur)'
80
+ email: attr_accessor@gmail.com
83
81
  executables: []
84
82
  extensions: []
85
83
  extra_rdoc_files: []
@@ -92,7 +90,6 @@ files:
92
90
  - LICENSE.txt
93
91
  - README.rdoc
94
92
  - Rakefile
95
- - benchmark/benchmark.rb
96
93
  - changelog.rdoc
97
94
  - exchange.gemspec
98
95
  - html.html
@@ -122,6 +119,7 @@ files:
122
119
  - lib/exchange/external_api/ecb.rb
123
120
  - lib/exchange/external_api/json.rb
124
121
  - lib/exchange/external_api/open_exchange_rates.rb
122
+ - lib/exchange/external_api/random.rb
125
123
  - lib/exchange/external_api/xavier_media.rb
126
124
  - lib/exchange/external_api/xml.rb
127
125
  - lib/exchange/gem_loader.rb
@@ -150,6 +148,7 @@ files:
150
148
  - spec/exchange/external_api/configuration_spec.rb
151
149
  - spec/exchange/external_api/ecb_spec.rb
152
150
  - spec/exchange/external_api/open_exchange_rates_spec.rb
151
+ - spec/exchange/external_api/random_spec.rb
153
152
  - spec/exchange/external_api/xavier_media_spec.rb
154
153
  - spec/exchange/gem_loader_spec.rb
155
154
  - spec/exchange/helper_spec.rb
@@ -184,10 +183,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
184
183
  version: '0'
185
184
  requirements: []
186
185
  rubyforge_project:
187
- rubygems_version: 1.8.24
186
+ rubygems_version: 1.8.25
188
187
  signing_key:
189
188
  specification_version: 3
190
- summary: Simple Exchange Rate operations for your ruby app
189
+ summary: Simple Money handling for your ruby app
191
190
  test_files:
192
191
  - spec/exchange/cache/base_spec.rb
193
192
  - spec/exchange/cache/configuration_spec.rb
@@ -210,6 +209,7 @@ test_files:
210
209
  - spec/exchange/external_api/configuration_spec.rb
211
210
  - spec/exchange/external_api/ecb_spec.rb
212
211
  - spec/exchange/external_api/open_exchange_rates_spec.rb
212
+ - spec/exchange/external_api/random_spec.rb
213
213
  - spec/exchange/external_api/xavier_media_spec.rb
214
214
  - spec/exchange/gem_loader_spec.rb
215
215
  - spec/exchange/helper_spec.rb
@@ -1,50 +0,0 @@
1
- require 'rubygems'
2
- require 'benchmark'
3
- require 'bigdecimal'
4
-
5
- class Helper
6
- def load_or_omit a_gem
7
- begin
8
- require a_gem.to_s
9
- return true
10
- rescue LoadError
11
- puts "You do not have #{a_gem} installed. gem install #{a_gem} to benchmark it\n\n"
12
- return false
13
- end
14
- end
15
-
16
- def median array
17
- (array.inject(0) { |sum, member| sum += member } / 3.0).round 6 if array
18
- end
19
- end
20
-
21
- helper = Helper.new
22
-
23
- operations = 1000
24
- results = {}
25
-
26
- results[:normal_float] = []
27
- 3.times { results[:normal_float] << Benchmark.realtime { operations.times { 3.555 * 4.234 } } }
28
-
29
- results[:big_decimal] = []
30
- one = BigDecimal.new("3.555")
31
- two = BigDecimal.new("4.234")
32
- 3.times { results[:big_decimal] << Benchmark.realtime { operations.times { one * two } } }
33
-
34
- if helper.load_or_omit(:money)
35
- m = Money.us_dollar(50)
36
- results[:money] = []
37
- 3.times { results[:money] << Benchmark.realtime { operations.times { m * 0.29 } } }
38
- end
39
-
40
- if helper.load_or_omit(:exchange)
41
- m = 50.in(:usd)
42
- results[:exchange] = []
43
- 3.times { results[:exchange] << Benchmark.realtime { operations.times { m * 0.29 } } }
44
- end
45
-
46
- puts "#{operations} operations\n\n"
47
- puts "Normal Float Operation takes \t#{helper.median(results[:normal_float])}s\n"
48
- puts "Big Decimal Operation takes \t#{helper.median(results[:big_decimal])}s\n"
49
- puts "Money gem Operation takes \t#{helper.median(results[:money])}s\n" if results[:money]
50
- puts "Exchange gem Operation takes \t#{helper.median(results[:exchange])}s\n" if results[:exchange]