currency 0.4.3 → 0.4.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|