currency_exchange 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Rakefile +20 -0
- data/currency_exchange.gemspec +27 -0
- data/lib/currency_exchange/data/currencies.rb +176 -0
- data/lib/currency_exchange/exchangers/open_exchange.rb +21 -0
- data/lib/currency_exchange/ext/fixnum.rb +22 -0
- data/lib/currency_exchange/storage/cache.rb +31 -0
- data/lib/currency_exchange/storage/mem_cache.rb +19 -0
- data/lib/currency_exchange/transporters/exchange_transporter.rb +29 -0
- data/lib/currency_exchange/version.rb +3 -0
- data/lib/currency_exchange.rb +36 -0
- data/spec/data/currencies_spec.rb +35 -0
- data/spec/exchangers/open_exchange_spec.rb +70 -0
- data/spec/ext/fixnum_spec.rb +49 -0
- data/spec/spec_helper.rb +8 -0
- metadata +157 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require 'rubygems'
|
3
|
+
begin
|
4
|
+
require 'bundler/setup'
|
5
|
+
rescue LoadError
|
6
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'bundler'
|
10
|
+
Bundler::GemHelper.install_tasks
|
11
|
+
|
12
|
+
require 'rake'
|
13
|
+
require 'rspec/core/rake_task'
|
14
|
+
|
15
|
+
desc "Run all examples"
|
16
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
17
|
+
t.rspec_opts = %w[--color]
|
18
|
+
end
|
19
|
+
|
20
|
+
task :default => [:spec]
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "currency_exchange/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "currency_exchange"
|
7
|
+
s.version = CurrencyExchange::VERSION
|
8
|
+
s.authors = ["Thil Bandara"]
|
9
|
+
s.email = ["tbandara@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/thil/currency_exchange"
|
11
|
+
s.summary = %q{A basic library to retrieve and convert currency}
|
12
|
+
s.description = %q{A basic library to retrieve and convert currency}
|
13
|
+
|
14
|
+
s.rubyforge_project = "currency_exchange"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# specify any dependencies here; for example:
|
22
|
+
s.add_development_dependency "rspec"
|
23
|
+
s.add_runtime_dependency "rest-client"
|
24
|
+
s.add_runtime_dependency "json"
|
25
|
+
s.add_runtime_dependency "activesupport", ">= 3.2.0"
|
26
|
+
s.add_runtime_dependency "rails", ">= 3.2.0"
|
27
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
module CurrencyExchange
|
2
|
+
module Data
|
3
|
+
class Currencies
|
4
|
+
|
5
|
+
def self.has_currency?(from, to)
|
6
|
+
return false unless from && to
|
7
|
+
CURRENCIES.has_key?(from.upcase) && CURRENCIES.has_key?(to.upcase)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
CURRENCIES = {
|
13
|
+
"AED"=> "United Arab Emirates Dirham",
|
14
|
+
"AFN"=> "Afghan Afghani",
|
15
|
+
"ALL"=> "Albanian Lek",
|
16
|
+
"AMD"=> "Armenian Dram",
|
17
|
+
"ANG"=> "Netherlands Antillean Guilder",
|
18
|
+
"AOA"=> "Angolan Kwanza",
|
19
|
+
"ARS"=> "Argentine Peso",
|
20
|
+
"AUD"=> "Australian Dollar",
|
21
|
+
"AWG"=> "Aruban Florin",
|
22
|
+
"AZN"=> "Azerbaijani Manat",
|
23
|
+
"BAM"=> "Bosnia-Herzegovina Convertible Mark",
|
24
|
+
"BBD"=> "Barbadian Dollar",
|
25
|
+
"BDT"=> "Bangladeshi Taka",
|
26
|
+
"BGN"=> "Bulgarian Lev",
|
27
|
+
"BHD"=> "Bahraini Dinar",
|
28
|
+
"BIF"=> "Burundian Franc",
|
29
|
+
"BMD"=> "Bermudan Dollar",
|
30
|
+
"BND"=> "Brunei Dollar",
|
31
|
+
"BOB"=> "Bolivian Boliviano",
|
32
|
+
"BRL"=> "Brazilian Real",
|
33
|
+
"BSD"=> "Bahamian Dollar",
|
34
|
+
"BTN"=> "Bhutanese Ngultrum",
|
35
|
+
"BWP"=> "Botswanan Pula",
|
36
|
+
"BYR"=> "Belarusian Ruble",
|
37
|
+
"BZD"=> "Belize Dollar",
|
38
|
+
"CAD"=> "Canadian Dollar",
|
39
|
+
"CDF"=> "Congolese Franc",
|
40
|
+
"CHF"=> "Swiss Franc",
|
41
|
+
"CLF"=> "Chilean Unit of Account (UF)",
|
42
|
+
"CLP"=> "Chilean Peso",
|
43
|
+
"CNY"=> "Chinese Yuan",
|
44
|
+
"COP"=> "Colombian Peso",
|
45
|
+
"CRC"=> "Costa Rican Colon",
|
46
|
+
"CUP"=> "Cuban Peso",
|
47
|
+
"CVE"=> "Cape Verdean Escudo",
|
48
|
+
"CZK"=> "Czech Republic Koruna",
|
49
|
+
"DJF"=> "Djiboutian Franc",
|
50
|
+
"DKK"=> "Danish Krone",
|
51
|
+
"DOP"=> "Dominican Peso",
|
52
|
+
"DZD"=> "Algerian Dinar",
|
53
|
+
"EGP"=> "Egyptian Pound",
|
54
|
+
"ETB"=> "Ethiopian Birr",
|
55
|
+
"EUR"=> "Euro",
|
56
|
+
"FJD"=> "Fijian Dollar",
|
57
|
+
"FKP"=> "Falkland Islands Pound",
|
58
|
+
"GBP"=> "British Pound Sterling",
|
59
|
+
"GEL"=> "Georgian Lari",
|
60
|
+
"GHS"=> "Ghanaian Cedi",
|
61
|
+
"GIP"=> "Gibraltar Pound",
|
62
|
+
"GMD"=> "Gambian Dalasi",
|
63
|
+
"GNF"=> "Guinean Franc",
|
64
|
+
"GTQ"=> "Guatemalan Quetzal",
|
65
|
+
"GYD"=> "Guyanaese Dollar",
|
66
|
+
"HKD"=> "Hong Kong Dollar",
|
67
|
+
"HNL"=> "Honduran Lempira",
|
68
|
+
"HRK"=> "Croatian Kuna",
|
69
|
+
"HTG"=> "Haitian Gourde",
|
70
|
+
"HUF"=> "Hungarian Forint",
|
71
|
+
"IDR"=> "Indonesian Rupiah",
|
72
|
+
"IEP"=> "Irish Pound",
|
73
|
+
"ILS"=> "Israeli New Sheqel",
|
74
|
+
"INR"=> "Indian Rupee",
|
75
|
+
"IQD"=> "Iraqi Dinar",
|
76
|
+
"IRR"=> "Iranian Rial",
|
77
|
+
"ISK"=> "Icelandic Krona",
|
78
|
+
"JMD"=> "Jamaican Dollar",
|
79
|
+
"JOD"=> "Jordanian Dinar",
|
80
|
+
"JPY"=> "Japanese Yen",
|
81
|
+
"KES"=> "Kenyan Shilling",
|
82
|
+
"KGS"=> "Kyrgystani Som",
|
83
|
+
"KHR"=> "Cambodian Riel",
|
84
|
+
"KMF"=> "Comorian Franc",
|
85
|
+
"KPW"=> "North Korean Won",
|
86
|
+
"KRW"=> "South Korean Won",
|
87
|
+
"KWD"=> "Kuwaiti Dinar",
|
88
|
+
"KZT"=> "Kazakhstani Tenge",
|
89
|
+
"LAK"=> "Laotian Kip",
|
90
|
+
"LBP"=> "Lebanese Pound",
|
91
|
+
"LKR"=> "Sri Lankan Rupee",
|
92
|
+
"LRD"=> "Liberian Dollar",
|
93
|
+
"LSL"=> "Lesotho Loti",
|
94
|
+
"LTL"=> "Lithuanian Litas",
|
95
|
+
"LVL"=> "Latvian Lats",
|
96
|
+
"LYD"=> "Libyan Dinar",
|
97
|
+
"MAD"=> "Moroccan Dirham",
|
98
|
+
"MDL"=> "Moldovan Leu",
|
99
|
+
"MGA"=> "Malagasy Ariary",
|
100
|
+
"MKD"=> "Macedonian Denar",
|
101
|
+
"MMK"=> "Myanma Kyat",
|
102
|
+
"MNT"=> "Mongolian Tugrik",
|
103
|
+
"MOP"=> "Macanese Pataca",
|
104
|
+
"MRO"=> "Mauritanian Ouguiya",
|
105
|
+
"MUR"=> "Mauritian Rupee",
|
106
|
+
"MVR"=> "Maldivian Rufiyaa",
|
107
|
+
"MWK"=> "Malawian Kwacha",
|
108
|
+
"MXN"=> "Mexican Peso",
|
109
|
+
"MYR"=> "Malaysian Ringgit",
|
110
|
+
"MZN"=> "Mozambican Metical",
|
111
|
+
"NAD"=> "Namibian Dollar",
|
112
|
+
"NGN"=> "Nigerian Naira",
|
113
|
+
"NIO"=> "Nicaraguan Cordoba",
|
114
|
+
"NOK"=> "Norwegian Krone",
|
115
|
+
"NPR"=> "Nepalese Rupee",
|
116
|
+
"NZD"=> "New Zealand Dollar",
|
117
|
+
"OMR"=> "Omani Rial",
|
118
|
+
"PAB"=> "Panamanian Balboa",
|
119
|
+
"PEN"=> "Peruvian Nuevo Sol",
|
120
|
+
"PGK"=> "Papua New Guinean Kina",
|
121
|
+
"PHP"=> "Philippine Peso",
|
122
|
+
"PKR"=> "Pakistani Rupee",
|
123
|
+
"PLN"=> "Polish Zloty",
|
124
|
+
"PYG"=> "Paraguayan Guarani",
|
125
|
+
"QAR"=> "Qatari Rial",
|
126
|
+
"RON"=> "Romanian Leu",
|
127
|
+
"RSD"=> "Serbian Dinar",
|
128
|
+
"RUB"=> "Russian Ruble",
|
129
|
+
"RWF"=> "Rwandan Franc",
|
130
|
+
"SAR"=> "Saudi Riyal",
|
131
|
+
"SBD"=> "Solomon Islands Dollar",
|
132
|
+
"SCR"=> "Seychellois Rupee",
|
133
|
+
"SDG"=> "Sudanese Pound",
|
134
|
+
"SEK"=> "Swedish Krona",
|
135
|
+
"SGD"=> "Singapore Dollar",
|
136
|
+
"SHP"=> "Saint Helena Pound",
|
137
|
+
"SLL"=> "Sierra Leonean Leone",
|
138
|
+
"SOS"=> "Somali Shilling",
|
139
|
+
"SRD"=> "Surinamese Dollar",
|
140
|
+
"STD"=> "Sao Tome and Principe Dobra",
|
141
|
+
"SVC"=> "Salvadoran Colon",
|
142
|
+
"SYP"=> "Syrian Pound",
|
143
|
+
"SZL"=> "Swazi Lilangeni",
|
144
|
+
"THB"=> "Thai Baht",
|
145
|
+
"TJS"=> "Tajikistani Somoni",
|
146
|
+
"TMT"=> "Turkmenistani Manat",
|
147
|
+
"TND"=> "Tunisian Dinar",
|
148
|
+
"TOP"=> "Tongan Pa anga",
|
149
|
+
"TRY"=> "Turkish Lira",
|
150
|
+
"TTD"=> "Trinidad and Tobago Dollar",
|
151
|
+
"TWD"=> "New Taiwan Dollar",
|
152
|
+
"TZS"=> "Tanzanian Shilling",
|
153
|
+
"UAH"=> "Ukrainian Hryvnia",
|
154
|
+
"UGX"=> "Ugandan Shilling",
|
155
|
+
"USD"=> "United States Dollar",
|
156
|
+
"UYU"=> "Uruguayan Peso",
|
157
|
+
"UZS"=> "Uzbekistan Som",
|
158
|
+
"VEF"=> "Venezuelan Bolivar",
|
159
|
+
"VND"=> "Vietnamese Dong",
|
160
|
+
"VUV"=> "Vanuatu Vatu",
|
161
|
+
"WST"=> "Samoan Tala",
|
162
|
+
"XAF"=> "CFA Franc BEAC",
|
163
|
+
"XCD"=> "East Caribbean Dollar",
|
164
|
+
"XDR"=> "Special Drawing Rights",
|
165
|
+
"XOF"=> "CFA Franc BCEAO",
|
166
|
+
"XPF"=> "CFP Franc",
|
167
|
+
"YER"=> "Yemeni Rial",
|
168
|
+
"ZAR"=> "South African Rand",
|
169
|
+
"ZMK"=> "Zambian Kwacha",
|
170
|
+
"ZWD"=> "Zimbabwean Dollar (1980-2008)",
|
171
|
+
"ZWL"=> "Zimbabwean Dollar"
|
172
|
+
}
|
173
|
+
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module CurrencyExchange
|
2
|
+
class Exchangers::OpenExchange
|
3
|
+
|
4
|
+
LATEST_EXCHANGE_URL = "http://openexchangerates.org/latest.json"
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@transporter = CurrencyExchange::Transporters::ExchangeTransporter.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def convert(number, from, to)
|
11
|
+
number * rates[to.upcase] * ( 1 / rates[from.upcase] ) if rates[to.upcase] && rates[from.upcase]
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def rates
|
17
|
+
@rates ||= @transporter.retrieve_rates(LATEST_EXCHANGE_URL)['rates']
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Numeric
|
2
|
+
UNABLE_TO_EXCHANGE = "Unable to exchange"
|
3
|
+
|
4
|
+
def exchange(from, to)
|
5
|
+
exchange = CurrencyExchange.convert(self, from, to)
|
6
|
+
exchange ? "$%.2f" % exchange : UNABLE_TO_EXCHANGE
|
7
|
+
end
|
8
|
+
|
9
|
+
def method_missing(sym, *args, &block)
|
10
|
+
empty, from, to = currency_string(sym)
|
11
|
+
if CurrencyExchange.has_currency?(from, to)
|
12
|
+
return exchange(from, to)
|
13
|
+
else
|
14
|
+
super.method_missing(sym, *args, &block)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def currency_string(method)
|
20
|
+
method.to_s.split /(.+)_to_(.+)/
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module CurrencyExchange
|
2
|
+
class Storage::Cache
|
3
|
+
|
4
|
+
class << self
|
5
|
+
attr_accessor :cache_strategy
|
6
|
+
|
7
|
+
def instance
|
8
|
+
@instance ||= load_instance
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def fetch(key)
|
13
|
+
end
|
14
|
+
|
15
|
+
def store(key, value)
|
16
|
+
value
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def self.load_instance
|
22
|
+
if self.cache_strategy == :memcache
|
23
|
+
CurrencyExchange::Storage::MemCache.new
|
24
|
+
else
|
25
|
+
self.new
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
begin
|
2
|
+
require 'rails'
|
3
|
+
rescue LoadError
|
4
|
+
raise "You don't have rails installed"
|
5
|
+
end
|
6
|
+
|
7
|
+
module CurrencyExchange
|
8
|
+
class Storage::MemCache < Storage::Cache
|
9
|
+
|
10
|
+
def fetch(key)
|
11
|
+
Rails.cache.read(key)
|
12
|
+
end
|
13
|
+
|
14
|
+
def store(key, value)
|
15
|
+
Rails.cache.write(key, value, :expires_in => 1.day)
|
16
|
+
value
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
begin
|
2
|
+
require 'rest-client'
|
3
|
+
require 'json'
|
4
|
+
rescue LoadError
|
5
|
+
raise "You don't have the required gems installed"
|
6
|
+
end
|
7
|
+
|
8
|
+
module CurrencyExchange
|
9
|
+
module Transporters
|
10
|
+
class ExchangeTransporter
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@storage = CurrencyExchange::Storage::Cache.instance
|
14
|
+
end
|
15
|
+
|
16
|
+
def retrieve_rates(url)
|
17
|
+
@storage.fetch(url) || @storage.store(url, fetch_json(url))
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def fetch_json(url)
|
23
|
+
response = RestClient.get(url, {:accept => :json})
|
24
|
+
JSON.parse(response.body)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require "currency_exchange/version"
|
2
|
+
require 'currency_exchange/ext/fixnum'
|
3
|
+
|
4
|
+
module CurrencyExchange
|
5
|
+
module Exchangers
|
6
|
+
autoload :OpenExchange, 'currency_exchange/exchangers/open_exchange'
|
7
|
+
end
|
8
|
+
|
9
|
+
module Transporters
|
10
|
+
autoload :ExchangeTransporter, 'currency_exchange/transporters/exchange_transporter'
|
11
|
+
end
|
12
|
+
|
13
|
+
module Data
|
14
|
+
autoload :Currencies, 'currency_exchange/data/currencies'
|
15
|
+
end
|
16
|
+
|
17
|
+
module Storage
|
18
|
+
autoload :Cache, 'currency_exchange/storage/cache'
|
19
|
+
autoload :MemCache, 'currency_exchange/storage/mem_cache'
|
20
|
+
end
|
21
|
+
|
22
|
+
class << self
|
23
|
+
def convert(number, from, to)
|
24
|
+
exchanger.convert(number, from, to) if has_currency?(from, to)
|
25
|
+
end
|
26
|
+
|
27
|
+
def has_currency?(from, to)
|
28
|
+
CurrencyExchange::Data::Currencies.has_currency?(from, to)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def exchanger
|
33
|
+
@exchanger ||= CurrencyExchange::Exchangers::OpenExchange.new
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CurrencyExchange::Data::Currencies do
|
4
|
+
|
5
|
+
describe "#has_currency?" do
|
6
|
+
let(:from) { "USD" }
|
7
|
+
let(:to) { "AUD" }
|
8
|
+
subject { CurrencyExchange::Data::Currencies.has_currency?(from, to) }
|
9
|
+
|
10
|
+
context "when from currency is nil" do
|
11
|
+
let(:from) { nil }
|
12
|
+
it { should == false }
|
13
|
+
end
|
14
|
+
|
15
|
+
context "when to currency is nil" do
|
16
|
+
let(:to) { nil }
|
17
|
+
it { subject.should == false }
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when from currency does not exist in currencies list" do
|
21
|
+
let(:from) { "EEE" }
|
22
|
+
it { subject.should == false }
|
23
|
+
end
|
24
|
+
|
25
|
+
context "when to currency does not exist in currencies list" do
|
26
|
+
let(:to) { "EEE" }
|
27
|
+
it { subject.should == false }
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should return true when from and to currencies exist" do
|
31
|
+
subject.should == true
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CurrencyExchange::Exchangers::OpenExchange do
|
4
|
+
|
5
|
+
describe "#convert" do
|
6
|
+
let(:aud) { "AUD" }
|
7
|
+
let(:aud_rate) { 4 }
|
8
|
+
let(:usd) { "USD" }
|
9
|
+
let(:usd_rate) { 2 }
|
10
|
+
let(:rates) { { aud => aud_rate, usd => usd_rate } }
|
11
|
+
let(:number) { 10 }
|
12
|
+
let(:calculated_rate) { number * usd_rate * ( 1 / aud_rate ) }
|
13
|
+
let(:open_exchange) { CurrencyExchange::Exchangers::OpenExchange.new }
|
14
|
+
|
15
|
+
subject { open_exchange.convert(number, aud, usd) }
|
16
|
+
|
17
|
+
before do
|
18
|
+
open_exchange.stub(:rates).and_return(rates)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should return exchanged rate" do
|
22
|
+
subject.should == calculated_rate
|
23
|
+
end
|
24
|
+
|
25
|
+
context "when from/to country code is lowercase" do
|
26
|
+
subject { open_exchange.convert(number, "aud", "usd") }
|
27
|
+
|
28
|
+
it "should return exchanged rate" do
|
29
|
+
subject.should == calculated_rate
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "when country code is not in rates" do
|
34
|
+
subject { open_exchange.convert(number, "ad", "usd") }
|
35
|
+
|
36
|
+
it { should == nil }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#rates" do
|
41
|
+
let(:url) { CurrencyExchange::Exchangers::OpenExchange::LATEST_EXCHANGE_URL }
|
42
|
+
let(:rates) { { "AED" => 3.1 } }
|
43
|
+
let(:data) { { "disclaimer" => 'abc', "rates" => rates } }
|
44
|
+
let(:transporter) { mock(CurrencyExchange::Transporters::ExchangeTransporter, :retrieve_rates => data) }
|
45
|
+
let(:open_exchange) { CurrencyExchange::Exchangers::OpenExchange.new }
|
46
|
+
|
47
|
+
subject { open_exchange.send(:rates) }
|
48
|
+
|
49
|
+
before do
|
50
|
+
CurrencyExchange::Transporters::ExchangeTransporter.stub(:new).and_return(transporter)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should call transporter" do
|
54
|
+
transporter.should_receive(:retrieve_rates).with(url)
|
55
|
+
subject
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should retrieve rates from data" do
|
59
|
+
subject.should == rates
|
60
|
+
end
|
61
|
+
|
62
|
+
context "when data is empty" do
|
63
|
+
let(:data) { {} }
|
64
|
+
|
65
|
+
it { should == nil }
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Numeric do
|
4
|
+
|
5
|
+
describe "#exchange" do
|
6
|
+
let(:number) { 10 }
|
7
|
+
let(:converted) { 3 }
|
8
|
+
let(:from) { "USD" }
|
9
|
+
let(:to) { "AUD" }
|
10
|
+
|
11
|
+
subject { number.exchange(from, to) }
|
12
|
+
|
13
|
+
before do
|
14
|
+
CurrencyExchange.stub(:convert).with(number, from, to).and_return(converted)
|
15
|
+
end
|
16
|
+
|
17
|
+
context "when converted value is nil" do
|
18
|
+
let(:converted) { nil }
|
19
|
+
it "should return unable to exchange" do
|
20
|
+
subject.should == Numeric::UNABLE_TO_EXCHANGE
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should convert exchange value into dollar decimals" do
|
25
|
+
subject.should == "$%.2f" % converted
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "#currency_to_currency" do
|
30
|
+
let(:aud) { "aud" }
|
31
|
+
let(:usd) { "usd" }
|
32
|
+
let(:number) { 10 }
|
33
|
+
|
34
|
+
subject { number.aud_to_usd }
|
35
|
+
|
36
|
+
it "should call exchange with usd and aud" do
|
37
|
+
CurrencyExchange.should_receive(:convert).with(number, aud, usd)
|
38
|
+
subject
|
39
|
+
end
|
40
|
+
|
41
|
+
context "when currency doesnt exist" do
|
42
|
+
subject { number.au_to_usd }
|
43
|
+
it "should throw no method exception" do
|
44
|
+
expect{subject}.to raise_error(NoMethodError)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: currency_exchange
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Thil Bandara
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-02-13 00:00:00 Z
|
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
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: rest-client
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
hash: 3
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
version: "0"
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: json
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
hash: 3
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
version: "0"
|
60
|
+
type: :runtime
|
61
|
+
version_requirements: *id003
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: activesupport
|
64
|
+
prerelease: false
|
65
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
hash: 15
|
71
|
+
segments:
|
72
|
+
- 3
|
73
|
+
- 2
|
74
|
+
- 0
|
75
|
+
version: 3.2.0
|
76
|
+
type: :runtime
|
77
|
+
version_requirements: *id004
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rails
|
80
|
+
prerelease: false
|
81
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
hash: 15
|
87
|
+
segments:
|
88
|
+
- 3
|
89
|
+
- 2
|
90
|
+
- 0
|
91
|
+
version: 3.2.0
|
92
|
+
type: :runtime
|
93
|
+
version_requirements: *id005
|
94
|
+
description: A basic library to retrieve and convert currency
|
95
|
+
email:
|
96
|
+
- tbandara@gmail.com
|
97
|
+
executables: []
|
98
|
+
|
99
|
+
extensions: []
|
100
|
+
|
101
|
+
extra_rdoc_files: []
|
102
|
+
|
103
|
+
files:
|
104
|
+
- .gitignore
|
105
|
+
- Gemfile
|
106
|
+
- Rakefile
|
107
|
+
- currency_exchange.gemspec
|
108
|
+
- lib/currency_exchange.rb
|
109
|
+
- lib/currency_exchange/data/currencies.rb
|
110
|
+
- lib/currency_exchange/exchangers/open_exchange.rb
|
111
|
+
- lib/currency_exchange/ext/fixnum.rb
|
112
|
+
- lib/currency_exchange/storage/cache.rb
|
113
|
+
- lib/currency_exchange/storage/mem_cache.rb
|
114
|
+
- lib/currency_exchange/transporters/exchange_transporter.rb
|
115
|
+
- lib/currency_exchange/version.rb
|
116
|
+
- spec/data/currencies_spec.rb
|
117
|
+
- spec/exchangers/open_exchange_spec.rb
|
118
|
+
- spec/ext/fixnum_spec.rb
|
119
|
+
- spec/spec_helper.rb
|
120
|
+
homepage: https://github.com/thil/currency_exchange
|
121
|
+
licenses: []
|
122
|
+
|
123
|
+
post_install_message:
|
124
|
+
rdoc_options: []
|
125
|
+
|
126
|
+
require_paths:
|
127
|
+
- lib
|
128
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
hash: 3
|
134
|
+
segments:
|
135
|
+
- 0
|
136
|
+
version: "0"
|
137
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
138
|
+
none: false
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
hash: 3
|
143
|
+
segments:
|
144
|
+
- 0
|
145
|
+
version: "0"
|
146
|
+
requirements: []
|
147
|
+
|
148
|
+
rubyforge_project: currency_exchange
|
149
|
+
rubygems_version: 1.8.9
|
150
|
+
signing_key:
|
151
|
+
specification_version: 3
|
152
|
+
summary: A basic library to retrieve and convert currency
|
153
|
+
test_files:
|
154
|
+
- spec/data/currencies_spec.rb
|
155
|
+
- spec/exchangers/open_exchange_spec.rb
|
156
|
+
- spec/ext/fixnum_spec.rb
|
157
|
+
- spec/spec_helper.rb
|