fixer 0.3.0 → 0.4

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