currency_spy 0.0.1

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,5 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ nbproject
5
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in currency_spy.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,24 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ currency_spy (0.0.1)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.1.2)
10
+ rspec (2.4.0)
11
+ rspec-core (~> 2.4.0)
12
+ rspec-expectations (~> 2.4.0)
13
+ rspec-mocks (~> 2.4.0)
14
+ rspec-core (2.4.0)
15
+ rspec-expectations (2.4.0)
16
+ diff-lcs (~> 1.1.2)
17
+ rspec-mocks (2.4.0)
18
+
19
+ PLATFORMS
20
+ ruby
21
+
22
+ DEPENDENCIES
23
+ currency_spy!
24
+ rspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Lukasz Badura
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,35 @@
1
+ = CurrencySpy
2
+
3
+ This is a simple gem composed of simple classes using the Mechanize parser to
4
+ fetch currency rates from various websites. It's main purpose was to collect
5
+ the data for a small bank loan comparison site. I've decided to publish this as
6
+ a standalone gem in case anybody wishes to fetch some rates in their
7
+ application. My classes deal mainly with Polish websites. Feel free to write
8
+ more or request a source.
9
+
10
+ == Requirements
11
+
12
+ The gem uses Mechanize to parse sites. I recommend using bundler to easily
13
+ install any dependencies. Please consult the gemspec for a list of
14
+ dependencies (including test and development environment).
15
+
16
+ == Installation
17
+
18
+ The plugin can be installed from rubygems:
19
+ sudo gem install currency_spy
20
+
21
+ To install the dependencies:
22
+ bundle
23
+
24
+ You can also clone my GitHub repository
25
+ (git://github.com/lbadura/currency_spy.git) and build the gem yourself and / or
26
+ hack on it.
27
+
28
+ == Credits
29
+
30
+ Feel free to contact me at lukasz@niebo.net.
31
+ My website: http://www.badurowie.org
32
+
33
+ Copyright (c) 2011 Lukasz Badura. Released under the MIT license.
34
+
35
+
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "currency_spy/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "currency_spy"
7
+ s.version = CurrencySpy::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Lukasz Badura"]
10
+ s.email = ["lukasz@niebo.net"]
11
+ s.homepage = "http://rubygems.org/gems/currency_spy"
12
+ s.summary = %q{A gem to fetch currency rates.}
13
+ s.description = %q{A simple gem to parse and fetch currency rates from different websites.}
14
+
15
+ s.rubyforge_project = "currency_spy"
16
+
17
+ s.add_development_dependency "rspec"
18
+ s.add_dependency "mechanize"
19
+
20
+ s.files = `git ls-files`.split("\n")
21
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
23
+ s.require_paths = ["lib"]
24
+ end
@@ -0,0 +1,50 @@
1
+ module CurrencySpy
2
+ class Nbp < CurrencySpy::Scraper
3
+
4
+ def initialize
5
+ super
6
+ @url = 'http://www.nbp.pl/home.aspx?f=/kursy/kursyc.html'
7
+ @page = parser.get(url)
8
+ end
9
+
10
+ def buy_rate(currency_code = nil)
11
+ currency_code = @currency_code ||= 'EUR'
12
+ regexp = Regexp.new(currency_code)
13
+ @page.search('//tr[@valign="middle"]').each do |tr|
14
+ tr.search('td').each do |td|
15
+ if (regexp.match(td.content))
16
+ return td.next_element.content.sub(',','.').to_f
17
+ end
18
+ end
19
+ end
20
+ return nil
21
+ end
22
+
23
+ def sell_rate(currency_code = nil)
24
+ currency_code = @currency_code ||= 'EUR'
25
+ regexp = Regexp.new(currency_code)
26
+ @page.search('//tr[@valign="middle"]').each do |tr|
27
+ tr.search('td').each do |td|
28
+ if (regexp.match(td.content))
29
+ return td.next_element.next_element.content.sub(',','.').to_f
30
+ end
31
+ end
32
+ end
33
+ return nil
34
+ end
35
+
36
+ def rate_time
37
+ regexp = Regexp.new(/\d\d\d\d-\d\d-\d\d/)
38
+ res = nil
39
+ @page.search('//p[@class="nag"]').each do |p|
40
+ p.search('b').each do |b|
41
+ if (regexp.match(b.content))
42
+ res = b.content
43
+ end
44
+ end
45
+ end
46
+ return DateTime.strptime(res, "%Y-%m-%d")
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,39 @@
1
+ module CurrencySpy
2
+ class Scraper
3
+ AVAILABLE_CODES = ['EUR', 'CHF', 'GBP'].freeze
4
+ attr_accessor :url, :currency_code
5
+ attr_reader :available_codes, :parser
6
+ def initialize()
7
+ @parser = Mechanize.new
8
+ @url = nil
9
+ end
10
+
11
+ def fetch_rates(currency_code = 'EUR')
12
+ if self.class.superclass.eql?(Object)
13
+ raise Exception.new("This method should be invoked from CurrencySpy::Scraper sub class")
14
+ else
15
+ if AVAILABLE_CODES.include?(currency_code)
16
+ @currency_code = currency_code
17
+ return {:buy_rate => buy_rate, :sell_rate => sell_rate, :rate_time => rate_time}
18
+ else
19
+ raise Exception.new("Unsupported currency code: #{currency_code}")
20
+ end
21
+ end
22
+ end
23
+
24
+ def buy_rate
25
+ # This method should be defined in a sub class
26
+ raise NotImplementedError
27
+ end
28
+
29
+ def sell_rate
30
+ # This method should be defined in a sub class
31
+ raise NotImplementedError
32
+ end
33
+
34
+ def rate_time
35
+ # This method should be defined in a sub class
36
+ raise NotImplementedError
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,3 @@
1
+ module CurrencySpy
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,12 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+ require 'mechanize'
3
+ require 'currency_spy/scraper'
4
+ require 'currency_spy/nbp'
5
+
6
+ module CurrencySpy
7
+ DATE_FORMAT = "%d-%m-%Y"
8
+
9
+ def self.datestr(date)
10
+ return date.strftime(CurrencySpy::DATE_FORMAT)
11
+ end
12
+ end
data/spec/nbp_spec.rb ADDED
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe "A Nbp scraper instance" do
4
+ before :each do
5
+ @scraper = CurrencySpy::Nbp.new
6
+ end
7
+
8
+ it "should have a proper url defined" do
9
+ @scraper.url.should == 'http://www.nbp.pl/home.aspx?f=/kursy/kursyc.html'
10
+ end
11
+
12
+ it "should return currency values" do
13
+ @scraper.fetch_rates.should_not be_nil
14
+ @scraper.fetch_rates.length.should == 3
15
+ @scraper.buy_rate.should == @scraper.fetch_rates[:buy_rate]
16
+ @scraper.sell_rate.should == @scraper.fetch_rates[:sell_rate]
17
+ end
18
+
19
+ it "should return a buy rate smaller than the sell rate" do
20
+ @scraper.buy_rate.should < @scraper.sell_rate
21
+ end
22
+
23
+ it "should return buy rate as a float" do
24
+ @scraper.fetch_rates[:buy_rate].should be_a_kind_of(Float)
25
+ end
26
+
27
+ it "should return sell rate as a float" do
28
+ @scraper.fetch_rates[:sell_rate].should be_a_kind_of(Float)
29
+ end
30
+
31
+ it "should return rate time as a DateTime instance" do
32
+ @scraper.fetch_rates[:rate_time].should be_a_kind_of(DateTime)
33
+ end
34
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe "A Scraper class" do
4
+ it "Should have a list of available currency codes" do
5
+ CurrencySpy::Scraper::AVAILABLE_CODES.should_not be_empty
6
+ end
7
+ end
8
+
9
+ describe "An instance of scraper" do
10
+ before :each do
11
+ @scraper = CurrencySpy::Scraper.new
12
+ end
13
+
14
+ it "should raise an exception if fetch_rate is called on Scraper class instance" do
15
+ lambda {@scraper.fetch_rates("XYZ")}.should raise_error(Exception, "This method should be invoked from CurrencySpy::Scraper sub class")
16
+ end
17
+
18
+ it "should raise an exception if an abstract method is called" do
19
+ lambda {@scraper.buy_rate}.should raise_error(NotImplementedError)
20
+ lambda {@scraper.sell_rate}.should raise_error(NotImplementedError)
21
+ lambda {@scraper.rate_time}.should raise_error(NotImplementedError)
22
+ end
23
+
24
+ it "should allow to read the mechanize parser" do
25
+ @scraper.parser.should_not be_nil
26
+ @scraper.parser.should be_a_kind_of Mechanize
27
+ end
28
+
29
+ it "should assign default properties" do
30
+ @scraper.url.should be_nil
31
+ end
32
+ end
@@ -0,0 +1,2 @@
1
+ require 'rspec'
2
+ require 'currency_spy'
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: currency_spy
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Lukasz Badura
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-01-08 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rspec
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :development
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: mechanize
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ version: "0"
44
+ type: :runtime
45
+ version_requirements: *id002
46
+ description: A simple gem to parse and fetch currency rates from different websites.
47
+ email:
48
+ - lukasz@niebo.net
49
+ executables: []
50
+
51
+ extensions: []
52
+
53
+ extra_rdoc_files: []
54
+
55
+ files:
56
+ - .gitignore
57
+ - Gemfile
58
+ - Gemfile.lock
59
+ - LICENSE
60
+ - README.rdoc
61
+ - Rakefile
62
+ - currency_spy.gemspec
63
+ - lib/currency_spy.rb
64
+ - lib/currency_spy/nbp.rb
65
+ - lib/currency_spy/scraper.rb
66
+ - lib/currency_spy/version.rb
67
+ - spec/nbp_spec.rb
68
+ - spec/scraper_spec.rb
69
+ - spec/spec_helper.rb
70
+ has_rdoc: true
71
+ homepage: http://rubygems.org/gems/currency_spy
72
+ licenses: []
73
+
74
+ post_install_message:
75
+ rdoc_options: []
76
+
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ segments:
85
+ - 0
86
+ version: "0"
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ segments:
93
+ - 0
94
+ version: "0"
95
+ requirements: []
96
+
97
+ rubyforge_project: currency_spy
98
+ rubygems_version: 1.3.7
99
+ signing_key:
100
+ specification_version: 3
101
+ summary: A gem to fetch currency rates.
102
+ test_files:
103
+ - spec/nbp_spec.rb
104
+ - spec/scraper_spec.rb
105
+ - spec/spec_helper.rb