tannenbaum 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.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ M2NlN2EyZTY0MDk0MTU4Nzk1NWFmYjllMDJhZWRkYjMwZjgwOWNjMQ==
5
+ data.tar.gz: !binary |-
6
+ YzE1ZTQyOTk0YjU1ZTAwZjg3MTAyOGI4MmNkZGZlY2ZjNGE4MjhjNw==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ MjVhYjk5MTNmNWVmODZiNWM1MDcxYzg0YTcxZDM4OTkxN2FhNDk2MmJjZWVm
10
+ YjFjOWRjMDgxMjcwMGE0YWI5MjgwMzIyZGRhNWZkZmE2NWQxZWNmOGI0NDFm
11
+ YjUwMzg1MmE4YWNhYmNlMTBlZTRkMjRmYjJmZDVlZjVhYjljY2I=
12
+ data.tar.gz: !binary |-
13
+ MzAzZTU4ZjFkMWY2NjY3NDFmZWVhMjUyODllNWQ2NjQ4ZmFlMDg0NDI4Nzkx
14
+ OTkzOGM3MWNkZmI0Y2E4ODg4ZWNmYjgzOTEzNDdiNjE3OTM4Y2NmZDVkNDRl
15
+ NjEzNWQzMTM3YWE3MWQxZjVlOTFkZDc5Mzc1NjkzMmJmNDE4MzE=
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color --format documentation
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ tannenbaum
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 1.9.3-p484
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ - 1.9.3
5
+ script: bundle exec rspec spec
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,5 @@
1
+ guard :rspec do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { "spec" }
5
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Horacio Bertorello
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,40 @@
1
+ [![Build Status](https://secure.travis-ci.org/svankie/tannenbaum.png)](http://travis-ci.org/svankie/tannenbaum)
2
+
3
+ # Tannenbaum
4
+
5
+ Tannenbaum is an experimental tool for querying currency informal exchange rates.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'tannenbaum'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install tannenbaum
20
+
21
+ ## Usage
22
+
23
+ [1] pry(main)> require 'tannenbaum'
24
+ => true
25
+ [2] pry(main)> quoting = Tannenbaum::Quote.new
26
+ => #<Tannenbaum::Quote:0x92993bc @provider=Tannenbaum::Providers::USD>
27
+ [3] pry(main)> rates = quoting.ask
28
+ => #<struct Tannenbaum::ExchangeRate
29
+ sell=10.77,
30
+ buy=10.72,
31
+ timestamp= #<DateTime: 2014-01-13T18:50:02+00:00 ((2456671j,67802s,0n),+0s,2299161j)>,
32
+ provider="elDolarBlue">
33
+
34
+ ## Contributing
35
+
36
+ 1. Fork it
37
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
38
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
39
+ 4. Push to the branch (`git push origin my-new-feature`)
40
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/lib/tannenbaum.rb ADDED
@@ -0,0 +1,7 @@
1
+ require "tannenbaum/exceptions"
2
+ require "tannenbaum/providers"
3
+ require "tannenbaum/quote"
4
+ require "tannenbaum/scraper"
5
+ require "tannenbaum/version"
6
+
7
+ module Tannenbaum; end
@@ -0,0 +1,5 @@
1
+ module Tannenbaum
2
+ module Exceptions
3
+ class InvalidCurrencyException < Exception; end
4
+ end
5
+ end
@@ -0,0 +1,16 @@
1
+ module Tannenbaum
2
+ module Providers
3
+ # Our exchange rate data providers are defined here as separate classes.
4
+ class USD
5
+ # The name of the [Provider].
6
+ def self.provider
7
+ "elDolarBlue"
8
+ end
9
+
10
+ # The URL of the [Provider].
11
+ def self.url
12
+ "http://www.eldolarblue.net/getDolarBlue.php?as=xml"
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,39 @@
1
+ module Tannenbaum
2
+ class Quote
3
+ # The [Quote] class defines our medium for getting informal exchange rate information
4
+ # for a given currency on a given [Provider].
5
+ def initialize(currency = :USD)
6
+ raise Tannenbaum::Exceptions::InvalidCurrencyException unless Tannenbaum::Providers.constants.include?(currency)
7
+ @provider = get_provider(currency)
8
+ end
9
+
10
+ # Retrieves the latest exchange rate prices according to our [Provider].
11
+ #
12
+ # @param ensure_fresh [Boolean] Ensures that we get the latest rates.
13
+ # @return [ExchangeRate] Struct with a sell and buy prices and the query timestamp.
14
+ def ask(ensure_fresh = false)
15
+ if ensure_fresh
16
+ @exchange_rates = fetch_current_exchange_rates
17
+ else
18
+ @exchange_rates ||= fetch_current_exchange_rates
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def get_provider(currency)
25
+ Tannenbaum::Providers.const_get(currency)
26
+ end
27
+
28
+ def fetch_current_exchange_rates
29
+ raw_exchange_data = Tannenbaum::Scraper.new(@provider).process
30
+ Tannenbaum::ExchangeRate.new(raw_exchange_data)
31
+ end
32
+ end
33
+
34
+ class ExchangeRate < Struct.new(:sell, :buy, :timestamp, :provider)
35
+ def initialize(hash)
36
+ super(*hash.values_at(:sell, :buy, :timestamp, :provider))
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,52 @@
1
+ require "nokogiri"
2
+ require "open-uri"
3
+
4
+ module Tannenbaum
5
+ class Scraper
6
+ # A [Scraper] that fetches and parses the exchange rate data from our -for now- only [Provider].
7
+ def initialize(supplier)
8
+ @url = supplier.url
9
+ @provider = supplier.provider
10
+ end
11
+
12
+ # Processes the XML response of our [Provider]
13
+ # and return it as a [Hash].
14
+ #
15
+ # @return [Hash] with fresh exchange rate data.
16
+ def process
17
+ xml_response = open(@url) rescue Hash.new
18
+ quote = Nokogiri::XML(xml_response)
19
+ parse_exchange_rates(quote)
20
+ end
21
+
22
+ private
23
+
24
+ def parse_exchange_rates(quote)
25
+ result = [:sell, :buy].inject({}) do |rates, key|
26
+ rate = extract_node_value(quote, key)
27
+ rates[key] = sanitize_rate!(rate)
28
+ rates
29
+ end
30
+ # XXX: yeah, it's hardcoded. mayhaps every ::Provider
31
+ # should have its own ::Scraper. i've to implement it.
32
+ timestamp = extract_node_value(quote, :datetime)
33
+ result[:timestamp] = parse_timestamp!(timestamp)
34
+
35
+ result[:provider] = @provider
36
+
37
+ result
38
+ end
39
+
40
+ def extract_node_value(node, key)
41
+ node.xpath("//#{key.to_s}").text
42
+ end
43
+
44
+ def sanitize_rate!(value, precision = 2)
45
+ value.to_f.round(precision)
46
+ end
47
+
48
+ def parse_timestamp!(timestamp)
49
+ DateTime.parse(timestamp) rescue DateTime.now
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,3 @@
1
+ module Tannenbaum
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,20 @@
1
+ require "tannenbaum"
2
+
3
+ describe Tannenbaum do
4
+ describe Tannenbaum::Quote do
5
+ it "shows the current exchange rates and timestamp for a given currency" do
6
+ quotation = Tannenbaum::Quote.new(:USD)
7
+
8
+ exchange_rates = quotation.ask
9
+
10
+ exchange_rates.sell.should be_a(Float)
11
+ exchange_rates.buy.should be_a(Float)
12
+
13
+ exchange_rates.timestamp.should be_a(DateTime)
14
+ end
15
+
16
+ it "fails when trying to quote a non-existant currency" do
17
+ expect { Tannenbaum::Quote.new(:ANT) }.to raise_exception(Tannenbaum::Exceptions::InvalidCurrencyException)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'tannenbaum/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "tannenbaum"
8
+ spec.version = Tannenbaum::VERSION
9
+ spec.authors = ["Horacio Bertorello"]
10
+ spec.email = ["svankie@gmail.com"]
11
+ spec.description = %q{Tannenbaum is a tool for querying currency informal exchange rates.}
12
+ spec.summary = %q{Tannenbaum is a tool for querying currency informal exchange rates.}
13
+ spec.homepage = "https://www.github.com/svankie/tannenbaum"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "nokogiri"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "guard-rspec"
25
+ spec.add_development_dependency "pry"
26
+ spec.add_development_dependency "rake"
27
+ spec.add_development_dependency "rspec"
28
+ end
metadata ADDED
@@ -0,0 +1,147 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tannenbaum
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Horacio Bertorello
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-01-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nokogiri
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: guard-rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Tannenbaum is a tool for querying currency informal exchange rates.
98
+ email:
99
+ - svankie@gmail.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - .gitignore
105
+ - .rspec
106
+ - .ruby-gemset
107
+ - .ruby-version
108
+ - .travis.yml
109
+ - Gemfile
110
+ - Guardfile
111
+ - LICENSE.txt
112
+ - README.md
113
+ - Rakefile
114
+ - lib/tannenbaum.rb
115
+ - lib/tannenbaum/exceptions.rb
116
+ - lib/tannenbaum/providers.rb
117
+ - lib/tannenbaum/quote.rb
118
+ - lib/tannenbaum/scraper.rb
119
+ - lib/tannenbaum/version.rb
120
+ - spec/tannenbaum_spec.rb
121
+ - tannenbaum.gemspec
122
+ homepage: https://www.github.com/svankie/tannenbaum
123
+ licenses:
124
+ - MIT
125
+ metadata: {}
126
+ post_install_message:
127
+ rdoc_options: []
128
+ require_paths:
129
+ - lib
130
+ required_ruby_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ! '>='
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ required_rubygems_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ! '>='
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ requirements: []
141
+ rubyforge_project:
142
+ rubygems_version: 2.1.11
143
+ signing_key:
144
+ specification_version: 4
145
+ summary: Tannenbaum is a tool for querying currency informal exchange rates.
146
+ test_files:
147
+ - spec/tannenbaum_spec.rb