currency 0.4.3 → 0.4.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/Manifest.txt +1 -0
- data/Rakefile +3 -2
- data/Releases.txt +7 -0
- data/lib/currency.rb +2 -0
- data/lib/currency/currency_version.rb +1 -1
- data/lib/currency/exchange/rate/deriver.rb +7 -2
- data/lib/currency/exchange/rate/source.rb +9 -4
- data/lib/currency/exchange/rate/source/test.rb +1 -1
- data/lib/currency/exchange/rate/source/timed_cache.rb +89 -35
- data/lib/currency/formatter.rb +34 -5
- data/lib/currency/money.rb +2 -2
- data/lib/currency/parser.rb +27 -9
- data/test/formatter_test.rb +15 -4
- data/test/parser_test.rb +45 -0
- data/test/timed_cache_test.rb +95 -0
- metadata +5 -4
data/Manifest.txt
CHANGED
data/Rakefile
CHANGED
@@ -26,8 +26,9 @@ Can store/retrieve Money values using ActiveRecord.
|
|
26
26
|
|
27
27
|
For more details, see:
|
28
28
|
|
29
|
+
http://rubyforge.org/projects/currency/
|
29
30
|
http://currency.rubyforge.org/
|
30
|
-
http://currency.rubyforge.org/files/
|
31
|
+
http://currency.rubyforge.org/files/README_txt.html
|
31
32
|
|
32
33
|
}
|
33
34
|
|
@@ -68,7 +69,7 @@ PKG_SVN_ROOT="svn+ssh://rubyforge.org/var/svn/#{PKG_NAME}/#{PKG_NAME}"
|
|
68
69
|
|
69
70
|
release, release_notes = get_release_notes
|
70
71
|
|
71
|
-
hoe = Hoe.new(
|
72
|
+
hoe = Hoe.new(PKG_Name.downcase, release) do |p|
|
72
73
|
p.author = 'Kurt Stephens'
|
73
74
|
p.description = PKG_DESCRIPTION
|
74
75
|
p.email = "ruby-#{PKG_NAME}@umleta.com"
|
data/Releases.txt
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
= Currency Release History
|
2
2
|
|
3
|
+
== Release 0.4.4: 2007/04/01
|
4
|
+
|
5
|
+
* Fixed TimedCache.
|
6
|
+
* Updated documentation.
|
7
|
+
* Added support for Parser#time = :now.
|
8
|
+
* Added support for Time in Formatter and Parser using Time#xmlschema.
|
9
|
+
|
3
10
|
== Release 0.4.3: 2007/04/01
|
4
11
|
|
5
12
|
* Added available? checks for NewYorkFed.
|
data/lib/currency.rb
CHANGED
@@ -26,7 +26,9 @@
|
|
26
26
|
# exchange rates from http://xe.com/ :
|
27
27
|
#
|
28
28
|
# require 'currency'
|
29
|
+
# require 'currency/exchange/rate/deriver'
|
29
30
|
# require 'currency/exchange/rate/source/xe'
|
31
|
+
# require 'currency/exchange/rate/source/timed_cache'
|
30
32
|
#
|
31
33
|
# # Rate source initialization
|
32
34
|
# provider = Currency::Exchange::Rate::Source::Xe.new
|
@@ -41,9 +41,9 @@ class Currency::Exchange::Rate::Deriver < Currency::Exchange::Rate::Source::Base
|
|
41
41
|
|
42
42
|
# Flush all cached Rates.
|
43
43
|
def clear_rates
|
44
|
-
@
|
44
|
+
@derived_rates.clear
|
45
45
|
@all_rates.clear
|
46
|
-
@source.
|
46
|
+
@source.clear_rates
|
47
47
|
super
|
48
48
|
end
|
49
49
|
|
@@ -140,6 +140,11 @@ class Currency::Exchange::Rate::Deriver < Currency::Exchange::Rate::Source::Base
|
|
140
140
|
end
|
141
141
|
|
142
142
|
|
143
|
+
def load_rates(time = nil)
|
144
|
+
all_rates(time)
|
145
|
+
end
|
146
|
+
|
147
|
+
|
143
148
|
# Returns true if the underlying rate provider is available.
|
144
149
|
def available?(time = nil)
|
145
150
|
source.available?(time)
|
@@ -41,10 +41,15 @@ require 'currency/exchange/rate'
|
|
41
41
|
#
|
42
42
|
# Somewhere at initialization of application:
|
43
43
|
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
44
|
+
# require 'currency'
|
45
|
+
# require 'currency/exchange/rate/deriver'
|
46
|
+
# require 'currency/exchange/rate/source/xe'
|
47
|
+
# require 'currency/exchange/rate/source/timed_cache'
|
48
|
+
#
|
49
|
+
# provider = Currency::Exchange::Rate::Source::Xe.new
|
50
|
+
# deriver = Currency::Exchange::Rate::Deriver.new(:source => provider)
|
51
|
+
# cache = Currency::Exchange::Rate::Source::TimedCache.new(:source => deriver)
|
52
|
+
# Currency::Exchange::Rate::Source.default = cache
|
48
53
|
#
|
49
54
|
module Currency::Exchange::Rate::Source
|
50
55
|
|
@@ -26,6 +26,14 @@ class Currency::Exchange::Rate::Source::TimedCache < ::Currency::Exchange::Rate:
|
|
26
26
|
attr_accessor :time_to_live_fudge
|
27
27
|
|
28
28
|
|
29
|
+
# Returns the time of the last load.
|
30
|
+
attr_reader :rate_load_time
|
31
|
+
|
32
|
+
|
33
|
+
# Returns the time of the next load.
|
34
|
+
attr_reader :rate_reload_time
|
35
|
+
|
36
|
+
|
29
37
|
# Returns source's name.
|
30
38
|
def name
|
31
39
|
source.name
|
@@ -35,15 +43,18 @@ class Currency::Exchange::Rate::Source::TimedCache < ::Currency::Exchange::Rate:
|
|
35
43
|
def initialize(*opt)
|
36
44
|
self.time_to_live = 600
|
37
45
|
self.time_to_live_fudge = 30
|
38
|
-
@
|
46
|
+
@rate_load_time = nil
|
47
|
+
@rate_reload_time = nil
|
39
48
|
@processing_rates = false
|
49
|
+
@cached_rates = { }
|
50
|
+
@cached_rates_old = nil
|
40
51
|
super(*opt)
|
41
52
|
end
|
42
53
|
|
43
54
|
|
44
55
|
# Clears current rates.
|
45
56
|
def clear_rates
|
46
|
-
@cached_rates
|
57
|
+
@cached_rates = { }
|
47
58
|
@source.clear_rates
|
48
59
|
super
|
49
60
|
end
|
@@ -53,16 +64,16 @@ class Currency::Exchange::Rate::Source::TimedCache < ::Currency::Exchange::Rate:
|
|
53
64
|
# is expired.
|
54
65
|
def expired?
|
55
66
|
if @time_to_live &&
|
56
|
-
@
|
57
|
-
(Time.now > @
|
67
|
+
@rate_reload_time &&
|
68
|
+
(Time.now > @rate_reload_time)
|
58
69
|
|
59
70
|
if @cached_rates
|
60
|
-
$stderr.puts "#{self}: rates expired on #{@
|
61
|
-
|
62
|
-
@cached_rates_old ||= @cashed_rates
|
71
|
+
$stderr.puts "#{self}: rates expired on #{@rate_reload_time}" if @verbose
|
63
72
|
|
64
|
-
@
|
73
|
+
@cached_rates_old = @cached_rates
|
65
74
|
end
|
75
|
+
|
76
|
+
clear_rates
|
66
77
|
|
67
78
|
true
|
68
79
|
else
|
@@ -79,7 +90,17 @@ class Currency::Exchange::Rate::Source::TimedCache < ::Currency::Exchange::Rate:
|
|
79
90
|
super(c1, c2, time)
|
80
91
|
end
|
81
92
|
|
93
|
+
|
94
|
+
def get_rate(c1, c2, time)
|
95
|
+
# STDERR.puts "get_rate #{c1} #{c2} #{time}"
|
96
|
+
rates = load_rates(time)
|
97
|
+
# STDERR.puts "rates = #{rates.inspect}"
|
98
|
+
rate = rates && (rates.select{|x| x.c1 == c1 && x.c2 == c2}[0])
|
99
|
+
# STDERR.puts "rate = #{rate.inspect}"
|
100
|
+
rate
|
101
|
+
end
|
82
102
|
|
103
|
+
|
83
104
|
# Returns an array of all the cached Rates.
|
84
105
|
def rates(time = nil)
|
85
106
|
load_rates(time)
|
@@ -92,52 +113,85 @@ class Currency::Exchange::Rate::Source::TimedCache < ::Currency::Exchange::Rate:
|
|
92
113
|
expired?
|
93
114
|
|
94
115
|
# Return rates, if cached.
|
95
|
-
return
|
116
|
+
return rates if rates = @cached_rates["#{time}"]
|
96
117
|
|
97
|
-
# Force load of rates
|
98
|
-
@cached_rates = _load_rates_from_source(time)
|
118
|
+
# Force load of rates.
|
119
|
+
rates = @cached_rates["#{time}"] = _load_rates_from_source(time)
|
99
120
|
|
121
|
+
# Update expiration.
|
122
|
+
_calc_rate_reload_time
|
123
|
+
|
124
|
+
return nil unless rates
|
125
|
+
|
100
126
|
# Flush old rates.
|
101
127
|
@cached_rates_old = nil
|
102
|
-
|
103
|
-
|
104
|
-
if time_to_live
|
105
|
-
@rates_renew_time = @rate_timestamp + (time_to_live + (time_to_live_fudge || 0))
|
106
|
-
$stderr.puts "#{self}: rates expire on #{@rates_renew_time}" if @verbose
|
107
|
-
end
|
108
|
-
|
109
|
-
@rates
|
128
|
+
|
129
|
+
rates
|
110
130
|
end
|
111
131
|
|
112
132
|
|
133
|
+
def time_to_live=(x)
|
134
|
+
@time_to_live = x
|
135
|
+
_calc_rate_reload_time
|
136
|
+
x
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
def time_to_live_fudge=(x)
|
141
|
+
@time_to_live_fudge = x
|
142
|
+
_calc_rate_reload_time
|
143
|
+
x
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
def _calc_rate_reload_time
|
148
|
+
if @time_to_live && @rate_load_time
|
149
|
+
@rate_reload_time = @rate_load_time + (@time_to_live + (@time_to_live_fudge || 0))
|
150
|
+
$stderr.puts "#{self}: rates expire on #{@rate_reload_time}" if @verbose
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
|
156
|
+
|
113
157
|
def _load_rates_from_source(time = nil) # :nodoc:
|
114
|
-
|
115
|
-
raise "Reentry!" if @processing_rates
|
158
|
+
rates = nil
|
116
159
|
|
117
|
-
|
118
|
-
|
160
|
+
begin
|
161
|
+
# Do not allow re-entrancy
|
162
|
+
raise "Reentry!" if @processing_rates
|
163
|
+
|
164
|
+
# Begin processing new rate request.
|
165
|
+
@processing_rates = true
|
119
166
|
|
120
|
-
|
121
|
-
|
167
|
+
# Clear cached Rates.
|
168
|
+
clear_rates
|
122
169
|
|
123
|
-
|
124
|
-
|
170
|
+
# Load rates from the source.
|
171
|
+
rates = source.load_rates(time)
|
125
172
|
|
126
|
-
|
127
|
-
|
128
|
-
|
173
|
+
# Compute new rate timestamp.
|
174
|
+
@rate_load_time = Time.now
|
175
|
+
|
176
|
+
# STDERR.puts "rate_load_time = #{@rate_load_time}"
|
177
|
+
ensure
|
178
|
+
# End processsing new rate request.
|
179
|
+
@processing_rates = false
|
180
|
+
|
129
181
|
end
|
130
182
|
|
131
|
-
#
|
132
|
-
@rate_timestamp = Time.now
|
183
|
+
# STDERR.puts "_load_rates => #{rates.inspect}"
|
133
184
|
|
134
|
-
# End processsing new rate request.
|
135
|
-
@processing_rates = false
|
136
|
-
|
137
185
|
rates
|
138
186
|
end
|
139
187
|
|
140
188
|
|
189
|
+
# Returns true if the underlying rate provider is available.
|
190
|
+
def available?(time = nil)
|
191
|
+
source.available?(time)
|
192
|
+
end
|
193
|
+
|
194
|
+
|
141
195
|
end # class
|
142
196
|
|
143
197
|
|
data/lib/currency/formatter.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# Copyright (C) 2006-2007 Kurt Stephens <ruby-currency(at)umleta.com>
|
2
2
|
# See LICENSE.txt for details.
|
3
3
|
|
4
|
+
require 'rss/rss' # Time#xmlschema
|
5
|
+
|
4
6
|
|
5
7
|
# This class formats a Money value as a String.
|
6
8
|
# Each Currency has a default Formatter.
|
@@ -32,7 +34,9 @@ class Currency::Formatter
|
|
32
34
|
# The currency code or nil.
|
33
35
|
attr_accessor :code
|
34
36
|
|
35
|
-
|
37
|
+
# The time or nil.
|
38
|
+
attr_accessor :time
|
39
|
+
|
36
40
|
def initialize(opts = @@empty_hash)
|
37
41
|
@template =
|
38
42
|
@template_proc =
|
@@ -89,6 +93,13 @@ class Currency::Formatter
|
|
89
93
|
# If true, append currency code.
|
90
94
|
attr_accessor :code
|
91
95
|
|
96
|
+
# If true, append the time.
|
97
|
+
attr_accessor :time
|
98
|
+
|
99
|
+
# The number of fractional digits in the time.
|
100
|
+
# Defaults to 4.
|
101
|
+
attr_accessor :time_fractional_digits
|
102
|
+
|
92
103
|
# If true, use html formatting.
|
93
104
|
#
|
94
105
|
# Currency::Money(12.45, :EUR).to_s(:html => true; :code => true)
|
@@ -98,7 +109,7 @@ class Currency::Formatter
|
|
98
109
|
# A template string used to format a money value.
|
99
110
|
# Defaults to:
|
100
111
|
#
|
101
|
-
# '#{code}#{code && " "}#{symbol}#{sign}#{whole}#{fraction}'
|
112
|
+
# '#{code}#{code && " "}#{symbol}#{sign}#{whole}#{fraction}#{time && " "}#{time}'
|
102
113
|
attr_accessor :template
|
103
114
|
|
104
115
|
|
@@ -112,6 +123,8 @@ class Currency::Formatter
|
|
112
123
|
self.symbol = false
|
113
124
|
self.code = false
|
114
125
|
self.html = false
|
126
|
+
self.time = false
|
127
|
+
self.time_fractional_digits = nil
|
115
128
|
end
|
116
129
|
x
|
117
130
|
end
|
@@ -138,7 +151,10 @@ class Currency::Formatter
|
|
138
151
|
@symbol = true
|
139
152
|
@code = false
|
140
153
|
@html = false
|
141
|
-
@
|
154
|
+
@time = false
|
155
|
+
@time_fractional_digits = 4
|
156
|
+
@template = '#{code}#{code && " "}#{symbol}#{sign}#{whole}#{fraction}#{time && " "}#{time}'
|
157
|
+
@template_object = nil
|
142
158
|
|
143
159
|
opt.each_pair{ | k, v | self.send("#{k}=", v) }
|
144
160
|
end
|
@@ -171,10 +187,13 @@ class Currency::Formatter
|
|
171
187
|
end
|
172
188
|
|
173
189
|
|
174
|
-
def _format(m, currency = nil) # :nodoc:
|
190
|
+
def _format(m, currency = nil, time = nil) # :nodoc:
|
175
191
|
# Get currency.
|
176
192
|
currency ||= m.currency
|
177
193
|
|
194
|
+
# Get time.
|
195
|
+
time ||= m.time
|
196
|
+
|
178
197
|
# Setup template
|
179
198
|
tmpl = self.template_object.clone
|
180
199
|
# $stderr.puts "template.template = #{tmpl.template.inspect}"
|
@@ -219,8 +238,11 @@ class Currency::Formatter
|
|
219
238
|
tmpl.symbol = @symbol ? ((@html && currency.symbol_html) || currency.symbol) : nil
|
220
239
|
|
221
240
|
|
222
|
-
#
|
241
|
+
# Add currency code.
|
223
242
|
tmpl.code = @code ? _format_Currency(currency) : nil
|
243
|
+
|
244
|
+
# Add time.
|
245
|
+
tmpl.time = @time ? time && _format_Time(time) : nil
|
224
246
|
|
225
247
|
# Ask template to format the components.
|
226
248
|
tmpl.format
|
@@ -236,6 +258,13 @@ class Currency::Formatter
|
|
236
258
|
end
|
237
259
|
|
238
260
|
|
261
|
+
def _format_Time(t) # :nodoc:
|
262
|
+
x = ''
|
263
|
+
x << t.getutc.xmlschema(@time_fractional_digits) if t
|
264
|
+
x
|
265
|
+
end
|
266
|
+
|
267
|
+
|
239
268
|
@@empty_hash = { }
|
240
269
|
@@empty_hash.freeze
|
241
270
|
|
data/lib/currency/money.rb
CHANGED
@@ -278,10 +278,10 @@ class Currency::Money
|
|
278
278
|
end
|
279
279
|
end
|
280
280
|
|
281
|
-
# Basic inspection, with symbol
|
281
|
+
# Basic inspection, with symbol, currency code and time.
|
282
282
|
# The standard #inspect method is available as #inspect_deep.
|
283
283
|
def inspect(*opts)
|
284
|
-
self.format(:symbol => true, :code => true)
|
284
|
+
self.format(:symbol => true, :code => true, :time => true)
|
285
285
|
end
|
286
286
|
|
287
287
|
# How to alias a method defined in an object superclass in a different class:
|
data/lib/currency/parser.rb
CHANGED
@@ -2,6 +2,9 @@
|
|
2
2
|
# See LICENSE.txt for details.
|
3
3
|
|
4
4
|
|
5
|
+
require 'rss/rss' # Time#xmlschema
|
6
|
+
|
7
|
+
|
5
8
|
# This class parses a Money value from a String.
|
6
9
|
# Each Currency has a default Parser.
|
7
10
|
class Currency::Parser
|
@@ -16,6 +19,7 @@ class Currency::Parser
|
|
16
19
|
attr_accessor :enforce_currency
|
17
20
|
|
18
21
|
# The default Time to use if no Time is specified in the string.
|
22
|
+
# If :now, time is set to Time.new.
|
19
23
|
attr_accessor :time
|
20
24
|
|
21
25
|
@@default = nil
|
@@ -34,6 +38,7 @@ class Currency::Parser
|
|
34
38
|
|
35
39
|
def initialize(opt = { })
|
36
40
|
@time =
|
41
|
+
@enforce_currency =
|
37
42
|
@currency =
|
38
43
|
nil
|
39
44
|
opt.each_pair{ | k, v | self.send("#{k}=", v) }
|
@@ -50,15 +55,28 @@ class Currency::Parser
|
|
50
55
|
|
51
56
|
# $stderr.puts "'#{x}'.Money_rep(#{self})"
|
52
57
|
|
58
|
+
# Parse time.
|
59
|
+
time = nil
|
60
|
+
if (md = /(\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d+)?Z)/.match(x))
|
61
|
+
time = Time.xmlschema(md[1])
|
62
|
+
unless time
|
63
|
+
raise ::Currency::Exception::InvalidMoneyString.new("time: #{str.inspect} #{currency} #{x.inspect}")
|
64
|
+
end
|
65
|
+
x = md.pre_match + md.post_match
|
66
|
+
end
|
67
|
+
# Default time
|
68
|
+
time ||= @time
|
69
|
+
time = Time.new if time == :now
|
70
|
+
|
53
71
|
# $stderr.puts "x = #{x}"
|
54
72
|
convert_currency = nil
|
55
|
-
# Handle currency code
|
73
|
+
# Handle currency code in string.
|
56
74
|
if (md = /([A-Z][A-Z][A-Z])/.match(x))
|
57
75
|
curr = ::Currency::Currency.get(md[1])
|
58
76
|
x = md.pre_match + md.post_match
|
59
77
|
if @currency && @currency != curr
|
60
78
|
if @enforce_currency
|
61
|
-
raise ::Currency::Exception::IncompatibleCurrency.new("#{str.inspect} #{@currency.code}")
|
79
|
+
raise ::Currency::Exception::IncompatibleCurrency.new("currency: #{str.inspect} #{@currency.code}")
|
62
80
|
end
|
63
81
|
convert_currency = @currency
|
64
82
|
end
|
@@ -67,7 +85,7 @@ class Currency::Parser
|
|
67
85
|
currency = @currency || ::Currency::Currency.default
|
68
86
|
currency = ::Currency::Currency.get(currency)
|
69
87
|
end
|
70
|
-
|
88
|
+
|
71
89
|
# Remove placeholders and symbol.
|
72
90
|
x = x.gsub(/[, ]/, '')
|
73
91
|
symbol = currency.symbol # FIXME
|
@@ -107,7 +125,7 @@ class Currency::Parser
|
|
107
125
|
|
108
126
|
x = whole.to_i
|
109
127
|
|
110
|
-
x = ::Currency::Money.new_rep(x, currency,
|
128
|
+
x = ::Currency::Money.new_rep(x, currency, time)
|
111
129
|
else
|
112
130
|
# $stderr.puts "'#{self}'.parse(#{str}) => ??? '#{x}'"
|
113
131
|
#x.to_f.Money_rep(self)
|
@@ -130,13 +148,13 @@ class Currency::Parser
|
|
130
148
|
# Parse a Money string in this Currency.
|
131
149
|
#
|
132
150
|
# "123.45".money # Using default Currency.
|
133
|
-
# => $123.45
|
151
|
+
# => USD $123.45
|
134
152
|
#
|
135
|
-
# "123.45 USD".money # Explicit Currency.
|
136
|
-
# => $123.45
|
153
|
+
# "$123.45 USD".money # Explicit Currency.
|
154
|
+
# => USD $123.45
|
137
155
|
#
|
138
|
-
# "123.45
|
139
|
-
# => $123.45
|
156
|
+
# "CAD 123.45".money
|
157
|
+
# => CAD $123.45
|
140
158
|
#
|
141
159
|
# "123.45 CAD".money(:USD) # Incompatible explicit Currency.
|
142
160
|
# !!! "123.45 CAD" USD (Currency::Exception::IncompatibleCurrency)
|
data/test/formatter_test.rb
CHANGED
@@ -15,11 +15,12 @@ class FormatterTest < TestBase
|
|
15
15
|
# Simple stuff.
|
16
16
|
#
|
17
17
|
|
18
|
-
def test_default
|
19
|
-
assert_kind_of Money, m = ::Currency::Money.new_rep(123456789)
|
20
|
-
assert_equal
|
21
|
-
assert_equal m.currency.code
|
18
|
+
def test_default(time = nil)
|
19
|
+
assert_kind_of Money, m = ::Currency::Money.new_rep(123456789, :USD, time)
|
20
|
+
assert_equal Currency.default, m.currency
|
21
|
+
assert_equal :USD, m.currency.code
|
22
22
|
assert_equal "$1,234,567.89", m.to_s
|
23
|
+
assert_equal time, m.time
|
23
24
|
|
24
25
|
m
|
25
26
|
end
|
@@ -60,6 +61,7 @@ class FormatterTest < TestBase
|
|
60
61
|
m
|
61
62
|
end
|
62
63
|
|
64
|
+
|
63
65
|
def test_misc
|
64
66
|
m = ::Currency::Money(12.45, :USD)
|
65
67
|
assert_equal "<span class=\"currency_code\">USD</span> $12.45",
|
@@ -75,6 +77,15 @@ class FormatterTest < TestBase
|
|
75
77
|
end
|
76
78
|
|
77
79
|
|
80
|
+
def test_time
|
81
|
+
time = Time.new
|
82
|
+
m = test_default(time)
|
83
|
+
assert_equal "$1,234,567.89", m.to_s(:time => false)
|
84
|
+
assert_equal "$1,234,567.89 #{time.getutc.xmlschema(4)}", m.to_s(:time => true)
|
85
|
+
|
86
|
+
m
|
87
|
+
end
|
88
|
+
|
78
89
|
end
|
79
90
|
|
80
91
|
end # module
|
data/test/parser_test.rb
CHANGED
@@ -54,6 +54,51 @@ class ParserTest < TestBase
|
|
54
54
|
assert_equal m.inspect, m2.inspect
|
55
55
|
end
|
56
56
|
|
57
|
+
|
58
|
+
def test_round_trip_time
|
59
|
+
::Currency::Currency.default = :USD
|
60
|
+
time = Time.now.getutc
|
61
|
+
assert_not_nil m = ::Currency::Money("1234567.89", :CAD, time)
|
62
|
+
assert_not_nil m.time
|
63
|
+
assert_not_nil m2 = ::Currency::Money(m.inspect)
|
64
|
+
assert_not_nil m2.time
|
65
|
+
assert_equal m.rep, m2.rep
|
66
|
+
assert_equal m.currency, m2.currency
|
67
|
+
assert_equal m.time.to_i, m2.time.to_i
|
68
|
+
assert_equal m.inspect, m2.inspect
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
def test_time_nil
|
73
|
+
parser = ::Currency::Parser.new
|
74
|
+
parser.time = nil
|
75
|
+
|
76
|
+
assert_not_nil m = parser.parse("$1234.55")
|
77
|
+
assert_equal nil, m.time
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
def test_time
|
82
|
+
parser = ::Currency::Parser.new
|
83
|
+
parser.time = Time.new
|
84
|
+
|
85
|
+
assert_not_nil m = parser.parse("$1234.55")
|
86
|
+
assert_equal parser.time, m.time
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
def test_time_now
|
91
|
+
parser = ::Currency::Parser.new
|
92
|
+
parser.time = :now
|
93
|
+
|
94
|
+
assert_not_nil m = parser.parse("$1234.55")
|
95
|
+
assert_not_nil m1_time = m.time
|
96
|
+
|
97
|
+
assert_not_nil m = parser.parse("$1234.55")
|
98
|
+
assert_not_nil m2_time = m.time
|
99
|
+
|
100
|
+
assert_not_equal m1_time, m2_time
|
101
|
+
end
|
57
102
|
end
|
58
103
|
|
59
104
|
end # module
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# Copyright (C) 2006-2007 Kurt Stephens <ruby-currency(at)umleta.com>
|
2
|
+
# See LICENSE.txt for details.
|
3
|
+
|
4
|
+
require 'test/test_base'
|
5
|
+
|
6
|
+
require 'currency'
|
7
|
+
require 'currency/exchange/rate/source/xe'
|
8
|
+
require 'currency/exchange/rate/source/timed_cache'
|
9
|
+
|
10
|
+
module Currency
|
11
|
+
|
12
|
+
class TimedCacheTest < TestBase
|
13
|
+
def setup
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
def get_rate_source
|
19
|
+
@source = source = Exchange::Rate::Source::Xe.new
|
20
|
+
|
21
|
+
# source.verbose = true
|
22
|
+
deriver = Exchange::Rate::Deriver.new(:source => source)
|
23
|
+
|
24
|
+
@cache = cache = Exchange::Rate::Source::TimedCache.new(:source => deriver)
|
25
|
+
|
26
|
+
cache
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
def test_timed_cache_usd_cad
|
31
|
+
assert_not_nil rates = @source.raw_rates
|
32
|
+
assert_not_nil rates[:USD]
|
33
|
+
assert_not_nil usd_cad = rates[:USD][:CAD]
|
34
|
+
|
35
|
+
assert_not_nil usd = Money.new(123.45, :USD)
|
36
|
+
assert_not_nil cad = usd.convert(:CAD)
|
37
|
+
|
38
|
+
assert_kind_of Numeric, m = (cad.to_f / usd.to_f)
|
39
|
+
# $stderr.puts "m = #{m}"
|
40
|
+
assert_equal_float usd_cad, m, 0.001
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
def test_timed_cache_cad_eur
|
45
|
+
assert_not_nil rates = @source.raw_rates
|
46
|
+
assert_not_nil rates[:USD]
|
47
|
+
assert_not_nil usd_cad = rates[:USD][:CAD]
|
48
|
+
assert_not_nil usd_eur = rates[:USD][:EUR]
|
49
|
+
|
50
|
+
assert_not_nil cad = Money.new(123.45, :CAD)
|
51
|
+
assert_not_nil eur = cad.convert(:EUR)
|
52
|
+
|
53
|
+
assert_kind_of Numeric, m = (eur.to_f / cad.to_f)
|
54
|
+
# $stderr.puts "m = #{m}"
|
55
|
+
assert_equal_float((1.0 / usd_cad) * usd_eur, m, 0.001)
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
def test_reload
|
60
|
+
# @cache.verbose = 5
|
61
|
+
|
62
|
+
test_timed_cache_cad_eur
|
63
|
+
|
64
|
+
assert_not_nil rates = @source.raw_rates
|
65
|
+
assert_not_nil rates[:USD]
|
66
|
+
assert_not_nil usd_cad_1 = rates[:USD][:CAD]
|
67
|
+
|
68
|
+
assert_not_nil t1 = @cache.rate_load_time
|
69
|
+
assert_not_nil t1_reload = @cache.rate_reload_time
|
70
|
+
assert t1_reload.to_i > t1.to_i
|
71
|
+
|
72
|
+
@cache.time_to_live = 5
|
73
|
+
@cache.time_to_live_fudge = 0
|
74
|
+
|
75
|
+
# puts @cache.rate_reload_time.to_i - @cache.rate_load_time.to_i
|
76
|
+
assert @cache.rate_reload_time.to_i - @cache.rate_load_time.to_i == @cache.time_to_live
|
77
|
+
|
78
|
+
sleep 10
|
79
|
+
|
80
|
+
test_timed_cache_cad_eur
|
81
|
+
|
82
|
+
assert_not_nil t2 = @cache.rate_load_time
|
83
|
+
assert t1.to_i != t2.to_i
|
84
|
+
|
85
|
+
assert_not_nil rates = @source.raw_rates
|
86
|
+
assert_not_nil rates[:USD]
|
87
|
+
assert_not_nil usd_cad_2 = rates[:USD][:CAD]
|
88
|
+
|
89
|
+
assert usd_cad_1.object_id != usd_cad_2.object_id
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
end # module
|
95
|
+
|
metadata
CHANGED
@@ -3,16 +3,16 @@ rubygems_version: 0.9.0
|
|
3
3
|
specification_version: 1
|
4
4
|
name: currency
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.4.
|
7
|
-
date: 2007-04-
|
8
|
-
summary: "Currency models currencies, monetary values, foreign exchanges rates. Pulls live and historical rates from http://xe.com/, http://newyorkfed.org/, http://thefinancials.com/. Can store/retrieve historical rate data from database using ActiveRecord. Can store/retrieve Money values using ActiveRecord. For more details, see: http://currency.rubyforge.org/ http://currency.rubyforge.org/files/
|
6
|
+
version: 0.4.4
|
7
|
+
date: 2007-04-30 00:00:00 -04:00
|
8
|
+
summary: "Currency models currencies, monetary values, foreign exchanges rates. Pulls live and historical rates from http://xe.com/, http://newyorkfed.org/, http://thefinancials.com/. Can store/retrieve historical rate data from database using ActiveRecord. Can store/retrieve Money values using ActiveRecord. For more details, see: http://rubyforge.org/projects/currency/ http://currency.rubyforge.org/ http://currency.rubyforge.org/files/README_txt.html"
|
9
9
|
require_paths:
|
10
10
|
- lib
|
11
11
|
- test
|
12
12
|
email: ruby-currency@umleta.com
|
13
13
|
homepage: http://rubyforge.org/projects/currency
|
14
14
|
rubyforge_project: currency
|
15
|
-
description: "Currency models currencies, monetary values, foreign exchanges rates. Pulls live and historical rates from http://xe.com/, http://newyorkfed.org/, http://thefinancials.com/. Can store/retrieve historical rate data from database using ActiveRecord. Can store/retrieve Money values using ActiveRecord. For more details, see: http://currency.rubyforge.org/ http://currency.rubyforge.org/files/
|
15
|
+
description: "Currency models currencies, monetary values, foreign exchanges rates. Pulls live and historical rates from http://xe.com/, http://newyorkfed.org/, http://thefinancials.com/. Can store/retrieve historical rate data from database using ActiveRecord. Can store/retrieve Money values using ActiveRecord. For more details, see: http://rubyforge.org/projects/currency/ http://currency.rubyforge.org/ http://currency.rubyforge.org/files/README_txt.html"
|
16
16
|
autorequire:
|
17
17
|
default_executable:
|
18
18
|
bindir: bin
|
@@ -82,6 +82,7 @@ files:
|
|
82
82
|
- test/parser_test.rb
|
83
83
|
- test/test_base.rb
|
84
84
|
- test/time_quantitizer_test.rb
|
85
|
+
- test/timed_cache_test.rb
|
85
86
|
- test/xe_test.rb
|
86
87
|
test_files: []
|
87
88
|
|