fixer 0.3.0 → 0.4

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,4 +1,4 @@
1
- .DS_Store
2
1
  .bundle
3
2
  pkg
4
3
  *.gem
4
+ Gemfile.lock
data/.rvmrc CHANGED
@@ -1 +1 @@
1
- rvm use 1.9.2
1
+ rvm --create use 1.9.2@fixer
data/README.md CHANGED
@@ -1,11 +1,79 @@
1
1
  Fixer
2
2
  ====
3
3
 
4
- Fixer wraps the current and historical [foreign exchange rate feeds](http://www.ecb.europa.eu/stats/exchange/eurofxref/html/index.en.html) of the European Central Bank.
4
+ Fixer wraps the current and historical
5
+ [foreign exchange rate feeds](http://www.ecb.europa.eu/stats/exchange/eurofxref/html/index.en.html)
6
+ of the European Central Bank.
5
7
 
6
8
  Usage
7
9
  -----
8
10
 
9
- Fixer.daily
10
- Fixer.historical_90
11
- Fixer.historical
11
+ ```ruby
12
+ Fixer.daily
13
+ Fixer.ninety_days
14
+ Fixer.historical
15
+ ```
16
+
17
+ A sample implementation:
18
+
19
+ ```ruby
20
+ # Migration
21
+ class CreateForeignExchanges < ActiveRecord::Migration
22
+ def self.up
23
+ create_table :foreign_exchanges do |t|
24
+ t.string :iso_code
25
+ t.float :rate
26
+
27
+ t.timestamps
28
+ end
29
+
30
+ add_index :foreign_exchanges, :iso_code
31
+ end
32
+
33
+ def self.down
34
+ drop_table :foreign_exchanges
35
+ end
36
+ end
37
+
38
+ # Model
39
+ class ForeignExchange < ActiveRecord::Base
40
+ class << self
41
+ # Returns an exchange rate quote.
42
+ #
43
+ # Accepts a counter currency code and an optional base currency code.
44
+ # Latter defaults to EUR if none is specified.
45
+ def quote(counter, base='EUR')
46
+ find_rate_by_currency(counter) / find_rate_by_currency(base)
47
+ end
48
+
49
+ private
50
+
51
+ def find_rate_by_currency(iso_code)
52
+ where(:iso_code => iso_code).first.rate
53
+ end
54
+ end
55
+ end
56
+
57
+ # Bank
58
+ class ECB < Money::Bank::Base
59
+ class << self
60
+ def refresh
61
+ hashes = Fixer.daily.first[:rates]
62
+ hashes.push({ :currency => "EUR", :rate => 1.0 })
63
+ hashes.each do |hash|
64
+ fx = ForeignExchange.find_or_initialize_by_iso_code(hash[:currency])
65
+ fx.rate = hash[:rate]
66
+ fx.save
67
+ end
68
+ end
69
+ end
70
+
71
+ def exchange_with(from, to_currency)
72
+ rate = ForeignExchange.quote(to_currency.iso_code, from.currency.iso_code)
73
+ Money.new((from.cents * rate).floor, to_currency)
74
+ end
75
+ end
76
+
77
+ # Initializer
78
+ Money.default_bank = ECB.new
79
+ ```
data/Rakefile CHANGED
@@ -3,7 +3,6 @@ require "rspec/core/rake_task"
3
3
 
4
4
  Bundler::GemHelper.install_tasks
5
5
 
6
- desc "Run all specs in spec directory"
7
6
  RSpec::Core::RakeTask.new(:spec) do |spec|
8
7
  spec.pattern = "spec/**/*_spec.rb"
9
8
  end
@@ -6,7 +6,7 @@ Gem::Specification.new do |s|
6
6
  s.name = "fixer"
7
7
  s.version = Fixer::VERSION
8
8
  s.platform = Gem::Platform::RUBY
9
- s.authors = ["Hakan Ensari"]
9
+ s.authors = ["Paper Cavalier"]
10
10
  s.email = ["code@papercavalier.com"]
11
11
  s.homepage = "http://fixer.heroku.com"
12
12
  s.summary = "A Ruby wrapper to the European Central Bank exchange rate feeds"
@@ -14,8 +14,8 @@ Gem::Specification.new do |s|
14
14
 
15
15
  s.rubyforge_project = "fixer"
16
16
 
17
- s.add_dependency("nokogiri", ["~> 1.4.0"])
18
- s.add_development_dependency("rspec", ["~> 2.1.0"])
17
+ s.add_dependency("nokogiri", ["~> 1.4"])
18
+ s.add_development_dependency("rspec", ["~> 2.6"])
19
19
 
20
20
  s.files = `git ls-files`.split("\n")
21
21
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -1,37 +1,23 @@
1
- require 'open-uri'
2
- require 'nokogiri'
1
+ require 'fixer/feed'
2
+ require 'fixer/builder'
3
3
 
4
4
  module Fixer
5
- class << self
6
- def daily
7
- get('daily')
8
- end
5
+ extend self
9
6
 
10
- def historical
11
- get('hist')
12
- end
7
+ def daily
8
+ Feed.new('daily').get
9
+ end
13
10
 
14
- def historical_90
15
- get('hist-90d')
16
- end
11
+ def historical
12
+ Feed.new('hist').get
13
+ end
17
14
 
18
- private
15
+ def historical_90
16
+ Kernel.warn("[DEPRECATION] `historical_90` is deprecated. Please use `ninety_days` instead.")
17
+ ninety_days
18
+ end
19
19
 
20
- def get(type)
21
- path = "http://www.ecb.europa.eu/stats/eurofxref/eurofxref-#{type}.xml"
22
- feed = open(path).read
23
- doc = Nokogiri::XML(feed)
24
- doc.xpath('/gesmes:Envelope/xmlns:Cube/xmlns:Cube', doc.root.namespaces).map do |snapshot|
25
- {
26
- :date => snapshot['time'],
27
- :rates => snapshot.xpath('./xmlns:Cube').map do |fx|
28
- {
29
- :currency => fx['currency'],
30
- :rate => fx['rate']
31
- }
32
- end
33
- }
34
- end
35
- end
20
+ def ninety_days
21
+ Feed.new('hist-90d').get
36
22
  end
37
23
  end
@@ -0,0 +1,19 @@
1
+ module Fixer
2
+ class Builder
3
+ def initialize(node)
4
+ @node = node
5
+ end
6
+
7
+ def build
8
+ {
9
+ :date => @node['time'],
10
+ :rates => @node.xpath('./xmlns:Cube').map do |fx|
11
+ {
12
+ :currency => fx['currency'],
13
+ :rate => fx['rate']
14
+ }
15
+ end
16
+ }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ require 'nokogiri'
2
+ require 'open-uri'
3
+
4
+ module Fixer
5
+ class Feed
6
+ def initialize(type)
7
+ @type = type
8
+ end
9
+
10
+ def get
11
+ doc = Nokogiri::XML(feed)
12
+ doc.xpath('/gesmes:Envelope/xmlns:Cube/xmlns:Cube', doc.root.namespaces).map do |node|
13
+ Builder.new(node).build
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def feed
20
+ open(path).read
21
+ end
22
+
23
+ def path
24
+ "http://www.ecb.europa.eu/stats/eurofxref/eurofxref-#{@type}.xml"
25
+ end
26
+ end
27
+ end
@@ -1,3 +1,3 @@
1
1
  module Fixer
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4"
3
3
  end
@@ -1,33 +1,34 @@
1
- require 'spec_helper'
1
+ require "spec_helper"
2
2
 
3
3
  describe Fixer do
4
- it "downloads daily rates" do
5
- rates = Fixer.daily
4
+ describe ".daily" do
5
+ it "downloads daily rates" do
6
+ rates = Fixer.daily
6
7
 
7
- rates.size.should eql 1
8
- rates.first.should have_key :date
9
- rates.first.should have_key :rates
8
+ rates.size.should eql 1
9
+ rates.first.should be_a_snapshot
10
+ end
10
11
  end
11
12
 
12
- it "downloads 90-day historical" do
13
- rates = Fixer.historical_90
13
+ describe ".ninety_days" do
14
+ it "downloads rates for the past 90 days" do
15
+ rates = Fixer.ninety_days
14
16
 
15
- # We should have more than 50 working days in a three-month period
16
- rates.size.should > 50
17
- rates.each do |rate|
18
- rate.should have_key :date
19
- rate.should have_key :rates
17
+ # We should have more than 50 working days in a three-month period
18
+ rates.size.should > 50
19
+ rates.each do |rate|
20
+ rate.should be_a_snapshot
21
+ end
20
22
  end
21
23
  end
22
24
 
23
- it "downloads historical" do
25
+ it "downloads all rates since January 1st, 1999" do
24
26
  rates = Fixer.historical
25
27
 
26
28
  # We should have a lot of working days in history
27
29
  rates.size.should > 1000
28
30
  rates.each do |rate|
29
- rate.should have_key :date
30
- rate.should have_key :rates
31
+ rate.should be_a_snapshot
31
32
  end
32
33
  end
33
34
  end
@@ -1,4 +1,10 @@
1
- require "bundler"
1
+ require "bundler/setup"
2
2
  require "rspec"
3
3
 
4
4
  require File.expand_path("../../lib/fixer", __FILE__)
5
+
6
+ RSpec::Matchers.define :be_a_snapshot do
7
+ match do |actual|
8
+ actual.keys.include?(:date) && actual.keys.include?(:rates)
9
+ end
10
+ end
metadata CHANGED
@@ -4,17 +4,16 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 3
8
- - 0
9
- version: 0.3.0
7
+ - 4
8
+ version: "0.4"
10
9
  platform: ruby
11
10
  authors:
12
- - Hakan Ensari
11
+ - Paper Cavalier
13
12
  autorequire:
14
13
  bindir: bin
15
14
  cert_chain: []
16
15
 
17
- date: 2010-12-03 00:00:00 +00:00
16
+ date: 2011-07-08 00:00:00 +01:00
18
17
  default_executable:
19
18
  dependencies:
20
19
  - !ruby/object:Gem::Dependency
@@ -28,8 +27,7 @@ dependencies:
28
27
  segments:
29
28
  - 1
30
29
  - 4
31
- - 0
32
- version: 1.4.0
30
+ version: "1.4"
33
31
  type: :runtime
34
32
  version_requirements: *id001
35
33
  - !ruby/object:Gem::Dependency
@@ -42,9 +40,8 @@ dependencies:
42
40
  - !ruby/object:Gem::Version
43
41
  segments:
44
42
  - 2
45
- - 1
46
- - 0
47
- version: 2.1.0
43
+ - 6
44
+ version: "2.6"
48
45
  type: :development
49
46
  version_requirements: *id002
50
47
  description: Fixer is a Ruby wrapper to the current and historical foreign exchange or FX rate feeds of the European Central Bank.
@@ -61,12 +58,13 @@ files:
61
58
  - .rspec
62
59
  - .rvmrc
63
60
  - Gemfile
64
- - Gemfile.lock
65
61
  - LICENSE
66
62
  - README.md
67
63
  - Rakefile
68
64
  - fixer.gemspec
69
65
  - lib/fixer.rb
66
+ - lib/fixer/builder.rb
67
+ - lib/fixer/feed.rb
70
68
  - lib/fixer/version.rb
71
69
  - spec/fixer_spec.rb
72
70
  - spec/spec_helper.rb
@@ -1,27 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- fixer (0.3.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
- rspec (2.1.0)
13
- rspec-core (~> 2.1.0)
14
- rspec-expectations (~> 2.1.0)
15
- rspec-mocks (~> 2.1.0)
16
- rspec-core (2.1.0)
17
- rspec-expectations (2.1.0)
18
- diff-lcs (~> 1.1.2)
19
- rspec-mocks (2.1.0)
20
-
21
- PLATFORMS
22
- ruby
23
-
24
- DEPENDENCIES
25
- fixer!
26
- nokogiri (~> 1.4.0)
27
- rspec (~> 2.1.0)