fixer 0.1.1 → 0.2.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.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ .DS_Store
2
+ .bundle
3
+ pkg
4
+ *.gem
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ -cfd
data/.rvmrc ADDED
@@ -0,0 +1,2 @@
1
+ rvm use 1.9.2
2
+ rvm wrapper 1.9.2
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "http://rubygems.org"
2
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,31 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ fixer (0.2.0)
5
+ nokogiri (~> 1.4.0)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ diff-lcs (1.1.2)
11
+ nokogiri (1.4.3.1)
12
+ rake (0.8.7)
13
+ rspec (2.0.0.rc)
14
+ rspec-core (= 2.0.0.rc)
15
+ rspec-expectations (= 2.0.0.rc)
16
+ rspec-mocks (= 2.0.0.rc)
17
+ rspec-core (2.0.0.rc)
18
+ rspec-expectations (2.0.0.rc)
19
+ diff-lcs (>= 1.1.2)
20
+ rspec-mocks (2.0.0.rc)
21
+ rspec-core (= 2.0.0.rc)
22
+ rspec-expectations (= 2.0.0.rc)
23
+
24
+ PLATFORMS
25
+ ruby
26
+
27
+ DEPENDENCIES
28
+ fixer!
29
+ nokogiri (~> 1.4.0)
30
+ rake
31
+ rspec (= 2.0.0.rc)
data/README.markdown CHANGED
@@ -3,18 +3,28 @@ Fixer
3
3
 
4
4
  Fixer is a Ruby wrapper to the [current and historical foreign exchange rate feeds provided by the European Central Bank](http://www.ecb.europa.eu/stats/exchange/eurofxref/html/index.en.html).
5
5
 
6
- Implement your own caching.
6
+ I am also throwing in a *minimal* cache. Use if it suits you or implement your own.
7
+
8
+ Bonus: Use the Money gem.
7
9
 
8
10
  Usage
9
11
  -----
10
12
 
11
- # Get daily rate
12
- Fixer.get('daily')
13
+ # Download the daily rates.
14
+ Fixer.daily
15
+
16
+ # Download the 90-day historical rates.
17
+ Fixer.historical_90
13
18
 
14
- # Get 90-day historical
15
- Fixer.get('hist-90d')
19
+ # Download all historical rates.
20
+ Fixer.historical
16
21
 
17
- # Get historical
18
- Fixer.get('hist')
22
+ # Use the built-in cache.
23
+ cache = Fixer::Cache
24
+ cache.to_usd
25
+ => 1.397
26
+ cache.base = "EUR"
27
+ cache.to_eur
28
+ => 0.7158
19
29
 
20
- # It doesn't get simpler than this.
30
+ # It doesn't get any simpler than this.
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # encoding: utf-8
2
+ require "bundler"
3
+ require "rspec/core/rake_task"
4
+
5
+ Bundler::GemHelper.install_tasks
6
+
7
+ desc "Run all specs in spec directory"
8
+ RSpec::Core::RakeTask.new(:spec) do |spec|
9
+ spec.pattern = "spec/**/*_spec.rb"
10
+ end
11
+
12
+ task :default => :spec
data/fixer.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "fixer/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "fixer"
7
+ s.version = Fixer::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Hakan Ensari"]
10
+ s.email = ["code@papercavalier.com"]
11
+ s.homepage = "http://fixer.heroku.com"
12
+ s.summary = "A Ruby wrapper to the European Central Bank exchange rate feeds"
13
+ s.description = "Fixer is a Ruby wrapper to the current and historical foreign exchange or FX rate feeds provided by the European Central Bank."
14
+
15
+ s.rubyforge_project = "fixer"
16
+
17
+ s.add_dependency("nokogiri", ["~> 1.4.0"])
18
+
19
+ s.add_development_dependency("rake")
20
+ s.add_development_dependency("rspec", ["= 2.0.0.rc"])
21
+
22
+ s.files = `git ls-files`.split("\n")
23
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
24
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
25
+ s.require_paths = ["lib"]
26
+ end
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+ module Fixer
3
+ class Cache
4
+ class << self
5
+ def base
6
+ @base || "EUR"
7
+ end
8
+
9
+ def base=(name)
10
+ @base = name
11
+ end
12
+
13
+ def expire
14
+ @rates = nil
15
+ end
16
+
17
+ def method_missing(sym, *args, &block)
18
+ if sym.to_s =~ /^to_(.*)$/
19
+ counter = $1.upcase
20
+ var_name = "@#{base}_#{counter}".to_sym
21
+ rate = instance_variable_get(var_name)
22
+ return rate unless rate.nil?
23
+
24
+ rate = quote(counter) / quote(base)
25
+ rate = (rate * 10000).round.to_f / 10000
26
+ instance_variable_set(var_name, rate)
27
+ rate
28
+ else
29
+ super
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def rates
36
+ begin
37
+ @rates ||= Fixer.daily.first[:rates].push({ :currency => "EUR", :rate => "1.0" })
38
+ rescue
39
+ raise Error, "Cache not valid"
40
+ end
41
+ end
42
+
43
+ def quote(counter)
44
+ rate = rates.detect { |rate| rate[:currency] == counter }
45
+ raise(Error, "Currency not valid") if rate.nil?
46
+ rate[:rate].to_f
47
+ end
48
+ end
49
+ end
50
+
51
+ class Error < StandardError; end
52
+ end
data/lib/fixer/version.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # encoding: utf-8
1
2
  module Fixer
2
- VERSION = '0.1.1'
3
+ VERSION = "0.2.0"
3
4
  end
data/lib/fixer.rb CHANGED
@@ -1,10 +1,9 @@
1
1
  # encoding: utf-8
2
2
  require 'open-uri'
3
3
  require 'nokogiri'
4
+ require File.dirname(__FILE__) + '/fixer/cache'
4
5
 
5
6
  module Fixer
6
- BASE_URL = 'http://www.ecb.europa.eu/stats/eurofxref/'
7
-
8
7
  class << self
9
8
  def daily
10
9
  get('daily')
@@ -17,20 +16,20 @@ module Fixer
17
16
  def historical_90
18
17
  get('hist-90d')
19
18
  end
20
-
19
+
21
20
  private
22
21
 
23
22
  def get(type)
24
- url = BASE_URL + "eurofxref-#{type}.xml"
25
- feed = open(url).read
26
- doc = Nokogiri::XML(feed)
23
+ path = "http://www.ecb.europa.eu/stats/eurofxref/eurofxref-#{type}.xml"
24
+ feed = open(path).read
25
+ doc = Nokogiri::XML(feed)
27
26
  doc.xpath('/gesmes:Envelope/xmlns:Cube/xmlns:Cube', doc.root.namespaces).map do |snapshot|
28
27
  {
29
28
  :date => snapshot['time'],
30
29
  :rates => snapshot.xpath('./xmlns:Cube').map do |fx|
31
30
  {
32
- :currency => fx['currency'],
33
- :rate => fx['rate']
31
+ :currency => fx['currency'],
32
+ :rate => fx['rate']
34
33
  }
35
34
  end
36
35
  }
@@ -0,0 +1,80 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ module Fixer
5
+ describe Cache do
6
+ let(:mock_rates) do
7
+ [
8
+ { :currency=>"USD", :rate=>"1.3856" },
9
+ { :currency=>"JPY", :rate=>"114.98" },
10
+ { :currency=>"GBP", :rate=>"0.87260" },
11
+ { :currency=>"CAD", :rate=>"1.4018" },
12
+ { :currency=>"EUR", :rate=>"1.0" }
13
+ ]
14
+ end
15
+
16
+ let(:cache) do
17
+ cache = Fixer::Cache
18
+ cache.base = "EUR"
19
+ cache.expire
20
+ cache
21
+ end
22
+
23
+ it "sets base currency" do
24
+ cache.base = "USD"
25
+ cache.base.should eql "USD"
26
+ end
27
+
28
+ it "quotes" do
29
+ cache.instance_variable_set(:@rates, mock_rates)
30
+ cache.send(:quote, "USD").should eql 1.3856
31
+ end
32
+
33
+ it "caches" do
34
+ cache.instance_variable_set(:@rates, "foo")
35
+ cache.send(:rates).should eql "foo"
36
+ end
37
+
38
+ it "seeds cache" do
39
+ cache.send(:rates).detect { |rate| rate[:currency] == "USD" }[:rate].should_not be_nil
40
+ end
41
+
42
+ it "expires cache" do
43
+ cache.instance_variable_set(:@rates, "foo")
44
+ cache.expire
45
+ cache.instance_variable_get(:@rates).should be_nil
46
+ end
47
+
48
+ it "raises an error if cache not valid" do
49
+ Fixer.stub!(:daily).and_return("foo")
50
+ lambda { cache.send(:rates) }.should raise_error Fixer::Error, "Cache not valid"
51
+ end
52
+
53
+ it "returns an exchange rate" do
54
+ cache.instance_variable_set(:@rates, mock_rates)
55
+ cache.to_eur.should eql 1.0
56
+ cache.to_usd.should eql 1.3856
57
+
58
+ cache.base = "GBP"
59
+ cache.to_gbp.should eql 1.0
60
+ cache.to_usd.should eql 1.5879
61
+ end
62
+
63
+ it "caches requested exchange rates" do
64
+ cache.instance_variable_set(:@rates, mock_rates)
65
+ cache.to_usd
66
+ cache.instance_variable_get(:@EUR_USD).should eql 1.3856
67
+ end
68
+
69
+ it "raises an error if counter currency not valid" do
70
+ cache.instance_variable_set(:@rates, mock_rates)
71
+ lambda { cache.to_foo }.should raise_error Fixer::Error, "Currency not valid"
72
+ end
73
+
74
+ it "raises an error if base currency not valid" do
75
+ cache.instance_variable_set(:@rates, mock_rates)
76
+ cache.base = "FOO"
77
+ lambda { cache.to_usd }.should raise_error Fixer::Error, "Currency not valid"
78
+ end
79
+ end
80
+ end
data/spec/fixer_spec.rb CHANGED
@@ -1,32 +1,31 @@
1
+ # encoding: utf-8
1
2
  require 'spec_helper'
2
3
 
3
4
  describe Fixer do
4
- context ".download" do
5
- it "downloads daily rates" do
6
- rates = Fixer.daily
7
- rates.size.should eql 1
8
- rates.first.should have_key :date
9
- rates.first.should have_key :rates
10
- end
5
+ it "downloads daily rates" do
6
+ rates = Fixer.daily
7
+ rates.size.should eql 1
8
+ rates.first.should have_key :date
9
+ rates.first.should have_key :rates
10
+ end
11
11
 
12
- it "downloads 90-day historical" do
13
- rates = Fixer.historical_90
14
- # We should have more than 50 working days in a three-month period
15
- rates.size.should > 50
16
- rates.each do |rate|
17
- rate.should have_key :date
18
- rate.should have_key :rates
19
- end
12
+ it "downloads 90-day historical" do
13
+ rates = Fixer.historical_90
14
+ # We should have more than 50 working days in a three-month period
15
+ rates.size.should > 50
16
+ rates.each do |rate|
17
+ rate.should have_key :date
18
+ rate.should have_key :rates
20
19
  end
20
+ end
21
21
 
22
- it "downloads historical" do
23
- rates = Fixer.historical
24
- # We should have a lot of working days in history
25
- rates.size.should > 1000
26
- rates.each do |rate|
27
- rate.should have_key :date
28
- rate.should have_key :rates
29
- end
22
+ it "downloads historical" do
23
+ rates = Fixer.historical
24
+ # We should have a lot of working days in history
25
+ rates.size.should > 1000
26
+ rates.each do |rate|
27
+ rate.should have_key :date
28
+ rate.should have_key :rates
30
29
  end
31
30
  end
32
31
  end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # encoding: utf-8
1
2
  require "rubygems"
2
3
  require "bundler/setup"
3
4
  require "rspec"
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 1
8
- - 1
9
- version: 0.1.1
7
+ - 2
8
+ - 0
9
+ version: 0.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Hakan Ensari
@@ -14,11 +14,12 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-10-06 00:00:00 +01:00
17
+ date: 2010-10-07 00:00:00 +01:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: nokogiri
22
+ prerelease: false
22
23
  requirement: &id001 !ruby/object:Gem::Requirement
23
24
  none: false
24
25
  requirements:
@@ -30,10 +31,10 @@ dependencies:
30
31
  - 0
31
32
  version: 1.4.0
32
33
  type: :runtime
33
- prerelease: false
34
34
  version_requirements: *id001
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: rake
37
+ prerelease: false
37
38
  requirement: &id002 !ruby/object:Gem::Requirement
38
39
  none: false
39
40
  requirements:
@@ -43,10 +44,10 @@ dependencies:
43
44
  - 0
44
45
  version: "0"
45
46
  type: :development
46
- prerelease: false
47
47
  version_requirements: *id002
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: rspec
50
+ prerelease: false
50
51
  requirement: &id003 !ruby/object:Gem::Requirement
51
52
  none: false
52
53
  requirements:
@@ -59,7 +60,6 @@ dependencies:
59
60
  - rc
60
61
  version: 2.0.0.rc
61
62
  type: :development
62
- prerelease: false
63
63
  version_requirements: *id003
64
64
  description: Fixer is a Ruby wrapper to the current and historical foreign exchange or FX rate feeds provided by the European Central Bank.
65
65
  email:
@@ -71,10 +71,19 @@ extensions: []
71
71
  extra_rdoc_files: []
72
72
 
73
73
  files:
74
- - lib/fixer/version.rb
75
- - lib/fixer.rb
74
+ - .gitignore
75
+ - .rspec
76
+ - .rvmrc
77
+ - Gemfile
78
+ - Gemfile.lock
76
79
  - LICENSE
77
80
  - README.markdown
81
+ - Rakefile
82
+ - fixer.gemspec
83
+ - lib/fixer.rb
84
+ - lib/fixer/cache.rb
85
+ - lib/fixer/version.rb
86
+ - spec/fixer/cache_spec.rb
78
87
  - spec/fixer_spec.rb
79
88
  - spec/spec_helper.rb
80
89
  has_rdoc: true
@@ -82,8 +91,8 @@ homepage: http://fixer.heroku.com
82
91
  licenses: []
83
92
 
84
93
  post_install_message:
85
- rdoc_options:
86
- - --charset=UTF-8
94
+ rdoc_options: []
95
+
87
96
  require_paths:
88
97
  - lib
89
98
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -91,7 +100,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
91
100
  requirements:
92
101
  - - ">="
93
102
  - !ruby/object:Gem::Version
94
- hash: -4559416944163579922
95
103
  segments:
96
104
  - 0
97
105
  version: "0"
@@ -101,17 +109,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
101
109
  - - ">="
102
110
  - !ruby/object:Gem::Version
103
111
  segments:
104
- - 1
105
- - 3
106
- - 7
107
- version: 1.3.7
112
+ - 0
113
+ version: "0"
108
114
  requirements: []
109
115
 
110
- rubyforge_project:
116
+ rubyforge_project: fixer
111
117
  rubygems_version: 1.3.7
112
118
  signing_key:
113
119
  specification_version: 3
114
120
  summary: A Ruby wrapper to the European Central Bank exchange rate feeds
115
121
  test_files:
122
+ - spec/fixer/cache_spec.rb
116
123
  - spec/fixer_spec.rb
117
124
  - spec/spec_helper.rb