currency 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest.txt +2 -0
- data/Rakefile +5 -5
- data/Releases.txt +12 -0
- data/lib/currency.rb +1 -0
- data/lib/currency/active_record.rb +3 -2
- data/lib/currency/config.rb +68 -0
- data/lib/currency/core_extensions.rb +1 -1
- data/lib/currency/currency_version.rb +1 -1
- data/lib/currency/exchange/rate/source/xe.rb +41 -66
- data/lib/currency/formatter.rb +111 -13
- data/lib/currency/money.rb +1 -1
- data/test/config_test.rb +36 -0
- data/test/formatter_test.rb +5 -5
- data/test/money_test.rb +3 -1
- data/test/test_base.rb +5 -2
- data/test/xe_test.rb +3 -1
- metadata +6 -4
data/Manifest.txt
CHANGED
@@ -10,6 +10,7 @@ examples/ex1.rb
|
|
10
10
|
examples/xe1.rb
|
11
11
|
lib/currency.rb
|
12
12
|
lib/currency/active_record.rb
|
13
|
+
lib/currency/config.rb
|
13
14
|
lib/currency/core_extensions.rb
|
14
15
|
lib/currency/currency.rb
|
15
16
|
lib/currency/currency/factory.rb
|
@@ -40,6 +41,7 @@ test/ar_column_test.rb
|
|
40
41
|
test/ar_simple_test.rb
|
41
42
|
test/ar_test_base.rb
|
42
43
|
test/ar_test_core.rb
|
44
|
+
test/config_test.rb
|
43
45
|
test/formatter_test.rb
|
44
46
|
test/historical_writer_test.rb
|
45
47
|
test/macro_test.rb
|
data/Rakefile
CHANGED
@@ -19,15 +19,15 @@ require 'rubygems'
|
|
19
19
|
require 'hoe'
|
20
20
|
|
21
21
|
PKG_Name = 'Currency'
|
22
|
-
PKG_DESCRIPTION = %{Currency models currencies, monetary values, foreign exchanges
|
23
|
-
Pulls live rates from http://xe.com/.
|
24
|
-
|
22
|
+
PKG_DESCRIPTION = %{Currency models currencies, monetary values, foreign exchanges rates.
|
23
|
+
Pulls live and historical rates from http://xe.com/, http://newyorkfed.org/, http://thefinancials.com/.
|
24
|
+
Can store/retrieve historical rate data from database using ActiveRecord.
|
25
|
+
Can store/retrieve Money values using ActiveRecord.
|
25
26
|
|
26
27
|
For more details, see:
|
27
28
|
|
28
|
-
http://currency.rubyforge.org/files/lib/currency_rb.html
|
29
|
-
http://currency.rubyforge.org/files/README.txt
|
30
29
|
http://currency.rubyforge.org/
|
30
|
+
http://currency.rubyforge.org/files/README.txt
|
31
31
|
|
32
32
|
}
|
33
33
|
|
data/Releases.txt
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
= Currency Release History
|
2
2
|
|
3
|
+
== Release 0.4.1: 2007/03/10
|
4
|
+
|
5
|
+
Some changes are not backwards-compatible
|
6
|
+
|
7
|
+
* Fixed Rate::Source::Xe; site format changed, more robust parser.
|
8
|
+
* Added Currency::Config.
|
9
|
+
* Support for filtering Float values before casting to Money, based on suggestions for rounding by Steffen Rusitschka.
|
10
|
+
* Fixed :allow_nil in ActiveRecord money macro based on fix by Steffen Rusitschka.
|
11
|
+
* Fixed package scoping issue in Money.
|
12
|
+
* Added support for Formatter#template string
|
13
|
+
* Money format template default changed to '#{code}#{code && " "}#{symbol}#{sign}#{whole}#{fraction}'. THIS MAY BREAK EXISTING CLIENTS. See http://www.jhall.demon.co.uk/currency/ for rationale.
|
14
|
+
|
3
15
|
== Release 0.4.0: 2007/02/21
|
4
16
|
|
5
17
|
=== MAJOR CHANGES IN THIS RELEASE FOR HISTORICAL RATE DATA
|
data/lib/currency.rb
CHANGED
@@ -123,6 +123,7 @@ end
|
|
123
123
|
$:.unshift(File.expand_path(File.dirname(__FILE__))) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
124
124
|
|
125
125
|
require 'currency/currency_version'
|
126
|
+
require 'currency/config'
|
126
127
|
require 'currency/exception'
|
127
128
|
require 'currency/money'
|
128
129
|
require 'currency/currency'
|
@@ -199,9 +199,10 @@ end_eval
|
|
199
199
|
|
200
200
|
money_rep ||= "#{attr_name}_money.rep"
|
201
201
|
|
202
|
+
validate_allow_nil = opts[:allow_nil] ? ', :allow_nil => true' : ''
|
202
203
|
validate = "# Validation\n"
|
203
|
-
validate << "\nvalidates_numericality_of :#{attr_name}\n"
|
204
|
-
validate << "\nvalidates_format_of :#{currency_column}, :with => /^[A-Z][A-Z][A-Z]
|
204
|
+
validate << "\nvalidates_numericality_of :#{attr_name}#{validate_allow_nil}\n"
|
205
|
+
validate << "\nvalidates_format_of :#{currency_column}, :with => /^[A-Z][A-Z][A-Z]$/#{validate_allow_nil}\n" if currency_column
|
205
206
|
|
206
207
|
|
207
208
|
alias_accessor ||= ''
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# Copyright (C) 2006-2007 Kurt Stephens <ruby-currency(at)umleta.com>
|
2
|
+
# See LICENSE.txt for details.
|
3
|
+
|
4
|
+
# The Currency::Config class is responsible for
|
5
|
+
# maintaining global configuration for the Currency package.
|
6
|
+
#
|
7
|
+
class Currency::Config
|
8
|
+
@@default = nil
|
9
|
+
|
10
|
+
# Returns the default Currency::Config object.
|
11
|
+
#
|
12
|
+
# If one is not specfied an instance is
|
13
|
+
# created. This is a global, not thread-local.
|
14
|
+
def self.default
|
15
|
+
@@default ||= self.new
|
16
|
+
end
|
17
|
+
|
18
|
+
# Sets the default Currency::Config object.
|
19
|
+
def self.default=(x)
|
20
|
+
@@default = x
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns the current Currency::Config object used during
|
24
|
+
# in the current thread.
|
25
|
+
#
|
26
|
+
# If #current= has not been called and #default= has not been called,
|
27
|
+
# then UndefinedExchange is raised.
|
28
|
+
def self.current
|
29
|
+
Thread.current[:currency_config] ||= self.default || (raise ::Currency::Exception::UndefinedConfig.new("Currency::Config.default not defined"))
|
30
|
+
end
|
31
|
+
|
32
|
+
# Sets the current Currency::Config object used
|
33
|
+
# in the current thread.
|
34
|
+
def self.current=(x)
|
35
|
+
Thread.current[:currency_config] = x
|
36
|
+
end
|
37
|
+
|
38
|
+
# Clones the current configuration and makes it current
|
39
|
+
# during the execution of a block. After block completes,
|
40
|
+
# the previous configuration is restored.
|
41
|
+
#
|
42
|
+
# Currency::Config.configure do | c |
|
43
|
+
# c.float_ref_filter = Proc.new { | x | x.round }
|
44
|
+
# "123.448".money.rep == 12345
|
45
|
+
# end
|
46
|
+
def self.configure(&blk)
|
47
|
+
c_prev = current
|
48
|
+
c_new = self.current = current.clone
|
49
|
+
result = nil
|
50
|
+
begin
|
51
|
+
result = yield c_new
|
52
|
+
ensure
|
53
|
+
self.current = c_prev
|
54
|
+
end
|
55
|
+
result
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
def float_ref_filter
|
61
|
+
@float_ref_filter ||= Proc.new { |x| x }
|
62
|
+
end
|
63
|
+
|
64
|
+
def float_ref_filter=(x)
|
65
|
+
@float_ref_filter = x
|
66
|
+
end
|
67
|
+
end # module
|
68
|
+
|
@@ -5,6 +5,8 @@ require 'currency/exchange/rate/source/base'
|
|
5
5
|
|
6
6
|
require 'net/http'
|
7
7
|
require 'open-uri'
|
8
|
+
# Cant use REXML because of missing </form> tags -- 2007/03/11
|
9
|
+
# require 'rexml/document'
|
8
10
|
|
9
11
|
# Connects to http://xe.com and parses "XE.com Quick Cross Rates"
|
10
12
|
# from home page HTML.
|
@@ -12,6 +14,8 @@ require 'open-uri'
|
|
12
14
|
# This is for demonstration purposes.
|
13
15
|
#
|
14
16
|
class Currency::Exchange::Rate::Source::Xe < ::Currency::Exchange::Rate::Source::Provider
|
17
|
+
class ParserError < ::Currency::Exception::Base; end
|
18
|
+
|
15
19
|
# Defines the pivot currency for http://xe.com/.
|
16
20
|
PIVOT_CURRENCY = :USD
|
17
21
|
|
@@ -37,7 +41,7 @@ class Currency::Exchange::Rate::Source::Xe < ::Currency::Exchange::Rate::Source:
|
|
37
41
|
|
38
42
|
# Returns a cached Hash of rates:
|
39
43
|
#
|
40
|
-
# xe.
|
44
|
+
# xe.raw_rates[:USD][:CAD] => 1.0134
|
41
45
|
#
|
42
46
|
def raw_rates
|
43
47
|
# Force load of rates
|
@@ -51,96 +55,67 @@ class Currency::Exchange::Rate::Source::Xe < ::Currency::Exchange::Rate::Source:
|
|
51
55
|
def parse_page_rates(data = nil)
|
52
56
|
data = get_page_content unless data
|
53
57
|
|
54
|
-
data = data.split(
|
55
|
-
|
56
|
-
@rate_timestamp = nil
|
57
|
-
|
58
|
-
# Chomp after
|
59
|
-
until data.empty?
|
60
|
-
line = data.pop
|
61
|
-
break if line =~ /Need More currencies\?/
|
62
|
-
end
|
63
|
-
|
64
|
-
# Chomp before Quick Cross Rates
|
65
|
-
until data.empty?
|
66
|
-
line = data.shift
|
67
|
-
break if line =~ /XE.com Quick Cross Rates/
|
68
|
-
end
|
58
|
+
@lines = data = data.split(/\n/);
|
69
59
|
|
70
|
-
|
71
|
-
md = nil
|
72
|
-
until data.empty?
|
73
|
-
line = data.shift
|
74
|
-
break if md = /rates as of (\d\d\d\d)\.(\d\d)\.(\d\d)\s+(\d\d):(\d\d).*GMT/.match(line)
|
75
|
-
end
|
76
|
-
if md
|
77
|
-
yyyy, mm, dd, h, m = md[1].to_i, md[2].to_i, md[3].to_i, md[4].to_i, md[5].to_i
|
78
|
-
@rate_timestamp = Time.gm(yyyy, mm, dd, h, m, 0, 0) rescue nil
|
79
|
-
#$stderr.puts "parsed #{md[0].inspect} => #{yyyy}, #{mm}, #{dd}, #{h}, #{m}"
|
80
|
-
#$stderr.puts " => #{@rate_timestamp && @rate_timestamp.xmlschema}"
|
81
|
-
end
|
60
|
+
@rate_timestamp = nil
|
82
61
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
end
|
87
|
-
|
88
|
-
until data.empty?
|
89
|
-
line = data.shift
|
90
|
-
break if line =~ /^\s*<\/tr>/i
|
91
|
-
end
|
92
|
-
# $stderr.puts "#{data[0..4].inspect}"
|
62
|
+
eat_lines_until /More currencies\.\.\.<\/a>/i
|
63
|
+
eat_lines_until /^\s*<tr>/i
|
64
|
+
eat_lines_until /^\s*<tr>/i
|
93
65
|
|
94
66
|
# Read first table row to get position for each currency
|
95
67
|
currency = [ ]
|
96
|
-
|
97
|
-
|
98
|
-
break if line =~ /^\s*<\/tr>/i
|
99
|
-
if md = /<td><IMG .+ ALT="([A-Z][A-Z][A-Z])"/i.match(line) #"
|
68
|
+
eat_lines_until /^\s*<\/tr>/i do
|
69
|
+
if md = /<td[^>]+?>.*?\/> ([A-Z][A-Z][A-Z])<\/td>/.match(@line)
|
100
70
|
cur = md[1].intern
|
101
71
|
cur_i = currency.size
|
102
72
|
currency.push(cur)
|
103
|
-
|
73
|
+
$stderr.puts "Found currency header: #{cur.inspect} at #{cur_i}" if @verbose
|
104
74
|
end
|
105
75
|
end
|
76
|
+
raise ParseError, "Currencies header not found" if currency.empty?
|
106
77
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
line = data.shift
|
112
|
-
break if line =~ /^\s*<td>.+1.+USD.+=/
|
113
|
-
end
|
114
|
-
|
115
|
-
until data.empty?
|
116
|
-
line = data.shift
|
117
|
-
break if line =~ /^\s*<\/tr>/i
|
118
|
-
end
|
119
|
-
|
120
|
-
# $stderr.puts "#{data[0..4].inspect}"
|
121
|
-
|
78
|
+
|
79
|
+
# Skip until "1 USD ="
|
80
|
+
eat_lines_until /^\s*<td[^>]+?> 1 +USD =/
|
81
|
+
|
122
82
|
# Read first row of 1 USD = ...
|
123
|
-
|
124
83
|
rate = { }
|
125
|
-
cur_i = -1
|
126
|
-
|
127
|
-
|
128
|
-
break if cur_i < 0 && line =~ /^\s*<\/tr>/i
|
129
|
-
if md = /<td>\s+(\d+\.\d+)\s+<\/td>/.match(line)
|
84
|
+
cur_i = -1
|
85
|
+
eat_lines_until /^\s*<\/tr>/i do
|
86
|
+
if md = /<td[^>]+?>\s*?(\d+\.\d+)\s*?<\/td>/i.match(@line)
|
130
87
|
usd_to_cur = md[1].to_f
|
131
88
|
cur_i = cur_i + 1
|
132
89
|
cur = currency[cur_i]
|
133
|
-
|
90
|
+
raise ParseError, "Currency not found at column #{cur_i}" unless cur
|
134
91
|
next if cur.to_s == PIVOT_CURRENCY.to_s
|
135
92
|
(rate[PIVOT_CURRENCY] ||= {})[cur] = usd_to_cur
|
136
93
|
(rate[cur] ||= { })[PIVOT_CURRENCY] ||= 1.0 / usd_to_cur
|
137
94
|
$stderr.puts "#{cur.inspect} => #{usd_to_cur}" if @verbose
|
138
95
|
end
|
139
96
|
end
|
97
|
+
raise ParseError, "Currency rates not found" if rate.keys.empty?
|
98
|
+
raise ParseError, "Not all rates found" if rate.keys.size != currency.size
|
140
99
|
|
100
|
+
@lines = @line = nil
|
101
|
+
|
141
102
|
rate
|
142
103
|
end
|
143
|
-
|
104
|
+
|
105
|
+
|
106
|
+
def eat_lines_until(rx)
|
107
|
+
until @lines.empty?
|
108
|
+
@line = @lines.shift
|
109
|
+
if md = rx.match(@line)
|
110
|
+
$stderr.puts "\nMATCHED #{@line.inspect} WITH #{rx.inspect} AT LINES:\n#{@lines[0..4].inspect}" if @verbose
|
111
|
+
return md
|
112
|
+
end
|
113
|
+
yield @line if block_given?
|
114
|
+
end
|
115
|
+
raise ParseError, rx.inspect
|
116
|
+
false
|
117
|
+
end
|
118
|
+
|
144
119
|
|
145
120
|
# Return a list of known base rates.
|
146
121
|
def load_rates(time = nil)
|
data/lib/currency/formatter.rb
CHANGED
@@ -5,6 +5,68 @@
|
|
5
5
|
# This class formats a Money value as a String.
|
6
6
|
# Each Currency has a default Formatter.
|
7
7
|
class Currency::Formatter
|
8
|
+
# The underlying object for Currency::Formatter#format.
|
9
|
+
# This object is cloned and initialized with strings created
|
10
|
+
# from Formatter#format.
|
11
|
+
# It handles the Formatter#format string interpolation.
|
12
|
+
class Template
|
13
|
+
@@empty_hash = { }
|
14
|
+
@@empty_hash.freeze
|
15
|
+
|
16
|
+
# The template string.
|
17
|
+
attr_accessor :template
|
18
|
+
|
19
|
+
# The Currency::Money object being formatted.
|
20
|
+
attr_accessor :money
|
21
|
+
# The Currency::Currency object being formatted.
|
22
|
+
attr_accessor :currency
|
23
|
+
|
24
|
+
# The sign: '-' or nil.
|
25
|
+
attr_accessor :sign
|
26
|
+
# The whole part of the value, with thousands_separator or nil.
|
27
|
+
attr_accessor :whole
|
28
|
+
# The fraction part of the value, with decimal_separator or nil.
|
29
|
+
attr_accessor :fraction
|
30
|
+
# The currency symbol or nil.
|
31
|
+
attr_accessor :symbol
|
32
|
+
# The currency code or nil.
|
33
|
+
attr_accessor :code
|
34
|
+
|
35
|
+
|
36
|
+
def initialize(opts = @@empty_hash)
|
37
|
+
opts.each_pair{ | k, v | self.send("#{k}=", v) }
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
# Sets the template string and uncaches the template_proc.
|
42
|
+
def template=(x)
|
43
|
+
if @template != x
|
44
|
+
@template_proc = nil
|
45
|
+
end
|
46
|
+
@template = x
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
# Defines a the self._format template procedure using
|
51
|
+
# the template as a string to be interpolated.
|
52
|
+
def template_proc(template = @template)
|
53
|
+
return @template_proc if @template_proc
|
54
|
+
@template_proc = template || ''
|
55
|
+
# @template_proc = @template_proc.gsub(/[\\"']/) { | x | "\\" + x }
|
56
|
+
@template_proc = "def self._format; \"#{@template_proc}\"; end"
|
57
|
+
self.instance_eval @template_proc
|
58
|
+
@template_proc
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
# Formats the current state using the template.
|
63
|
+
def format
|
64
|
+
template_proc
|
65
|
+
_format
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
|
8
70
|
# Defaults to ','
|
9
71
|
attr_accessor :thousands_separator
|
10
72
|
|
@@ -27,9 +89,14 @@ class Currency::Formatter
|
|
27
89
|
#
|
28
90
|
# Currency::Money(12.45, :EUR).to_s(:html => true; :code => true)
|
29
91
|
# => "€12.45 <span class=\"currency_code\">EUR</span>"
|
30
|
-
|
31
92
|
attr_accessor :html
|
32
93
|
|
94
|
+
# A template string used to format a money value.
|
95
|
+
# Defaults to:
|
96
|
+
#
|
97
|
+
# '#{code}#{code && " "}#{symbol}#{sign}#{whole}#{fraction}'
|
98
|
+
attr_accessor :template
|
99
|
+
|
33
100
|
|
34
101
|
# If passed true, formats for an input field (i.e.: as a number).
|
35
102
|
def as_input_value=(x)
|
@@ -42,6 +109,7 @@ class Currency::Formatter
|
|
42
109
|
self.code = false
|
43
110
|
self.html = false
|
44
111
|
end
|
112
|
+
x
|
45
113
|
end
|
46
114
|
|
47
115
|
|
@@ -66,6 +134,7 @@ class Currency::Formatter
|
|
66
134
|
@symbol = true
|
67
135
|
@code = false
|
68
136
|
@html = false
|
137
|
+
@template = '#{code}#{code && " "}#{symbol}#{sign}#{whole}#{fraction}'
|
69
138
|
|
70
139
|
opt.each_pair{ | k, v | self.send("#{k}=", v) }
|
71
140
|
end
|
@@ -76,16 +145,45 @@ class Currency::Formatter
|
|
76
145
|
end
|
77
146
|
|
78
147
|
|
148
|
+
# Sets the template and the Template#template.
|
149
|
+
def template=(x)
|
150
|
+
if @template_object
|
151
|
+
@template_object.template = x
|
152
|
+
end
|
153
|
+
@template = x
|
154
|
+
end
|
155
|
+
|
156
|
+
|
157
|
+
# Returns the Template object.
|
158
|
+
def template_object
|
159
|
+
return @template_object if @template_object
|
160
|
+
|
161
|
+
@template_object = Template.new
|
162
|
+
@template_object.template = @template if @template
|
163
|
+
# $stderr.puts "template.template = #{@template_object.template.inspect}"
|
164
|
+
@template_object.template_proc # pre-cache before clone.
|
165
|
+
|
166
|
+
@template_object
|
167
|
+
end
|
168
|
+
|
169
|
+
|
79
170
|
def _format(m, currency = nil) # :nodoc:
|
80
171
|
# Get currency.
|
81
172
|
currency ||= m.currency
|
82
173
|
|
174
|
+
# Setup template
|
175
|
+
tmpl = self.template_object.clone
|
176
|
+
# $stderr.puts "template.template = #{tmpl.template.inspect}"
|
177
|
+
tmpl.money = m
|
178
|
+
tmpl.currency = currency
|
179
|
+
|
83
180
|
# Get scaled integer representation for this Currency.
|
84
181
|
# $stderr.puts "m.currency = #{m.currency}, currency => #{currency}"
|
85
182
|
x = m.Money_rep(currency)
|
86
183
|
|
87
184
|
# Remove sign.
|
88
185
|
x = - x if ( neg = x < 0 )
|
186
|
+
tmpl.sign = neg ? '-' : nil
|
89
187
|
|
90
188
|
# Convert to String.
|
91
189
|
x = x.to_s
|
@@ -97,9 +195,9 @@ class Currency::Formatter
|
|
97
195
|
|
98
196
|
# Insert decimal place.
|
99
197
|
whole = x[0 .. currency.format_left]
|
100
|
-
|
198
|
+
fraction = x[currency.format_right .. -1]
|
101
199
|
|
102
|
-
# Do
|
200
|
+
# Do thousands.
|
103
201
|
x = whole
|
104
202
|
if @thousands && (@thousands_separator && ! @thousands_separator.empty?)
|
105
203
|
x.reverse!
|
@@ -108,20 +206,20 @@ class Currency::Formatter
|
|
108
206
|
x.reverse!
|
109
207
|
end
|
110
208
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
209
|
+
# Put whole and fractional parts.
|
210
|
+
tmpl.whole = x
|
211
|
+
tmpl.fraction = @cents && @decimal_separator ? @decimal_separator + fraction : nil
|
212
|
+
|
213
|
+
|
116
214
|
# Add symbol?
|
117
|
-
|
215
|
+
tmpl.symbol = @symbol ? ((@html && currency.symbol_html) || currency.symbol) : nil
|
216
|
+
|
118
217
|
|
119
218
|
# Suffix with currency code.
|
120
|
-
|
121
|
-
x << (' ' + _format_Currency(currency))
|
122
|
-
end
|
219
|
+
tmpl.code = @code ? _format_Currency(currency) : nil
|
123
220
|
|
124
|
-
|
221
|
+
# Ask template to format the components.
|
222
|
+
tmpl.format
|
125
223
|
end
|
126
224
|
|
127
225
|
|
data/lib/currency/money.rb
CHANGED
data/test/config_test.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# Copyright (C) 2006-2007 Kurt Stephens <ruby-currency(at)umleta.com>
|
2
|
+
# See LICENSE.txt for details.
|
3
|
+
|
4
|
+
|
5
|
+
require 'test/test_base'
|
6
|
+
require 'currency'
|
7
|
+
|
8
|
+
module Currency
|
9
|
+
|
10
|
+
class ConfigTest < TestBase
|
11
|
+
def setup
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
15
|
+
############################################
|
16
|
+
# Simple stuff.
|
17
|
+
#
|
18
|
+
|
19
|
+
def test_config
|
20
|
+
assert_kind_of Money, m = Money.new(1.999)
|
21
|
+
assert_equal 199, m.rep
|
22
|
+
|
23
|
+
Config.configure do | c |
|
24
|
+
c.float_ref_filter = Proc.new { | x | x.round }
|
25
|
+
|
26
|
+
assert_kind_of Money, m = Money.new(1.999)
|
27
|
+
assert_equal 200, m.rep
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end # class
|
33
|
+
|
34
|
+
end # module
|
35
|
+
|
36
|
+
|
data/test/formatter_test.rb
CHANGED
@@ -55,22 +55,22 @@ class FormatterTest < TestBase
|
|
55
55
|
def test_code
|
56
56
|
m = test_default
|
57
57
|
assert_equal "$1,234,567.89", m.to_s(:code => false)
|
58
|
-
assert_equal "$1,234,567.89
|
58
|
+
assert_equal "USD $1,234,567.89", m.to_s(:code => true)
|
59
59
|
|
60
60
|
m
|
61
61
|
end
|
62
62
|
|
63
63
|
def test_misc
|
64
64
|
m = ::Currency::Money(12.45, :USD)
|
65
|
-
assert_equal "
|
65
|
+
assert_equal "<span class=\"currency_code\">USD</span> $12.45",
|
66
66
|
m.to_s(:html => true, :code => true)
|
67
67
|
|
68
68
|
m = ::Currency::Money(12.45, :EUR)
|
69
|
-
assert_equal "
|
69
|
+
assert_equal "<span class=\"currency_code\">EUR</span> €12.45",
|
70
70
|
m.to_s(:html => true, :code => true)
|
71
71
|
|
72
|
-
m = ::Currency::Money(
|
73
|
-
assert_equal "
|
72
|
+
m = ::Currency::Money(12345.45, :EUR)
|
73
|
+
assert_equal "<span class=\"currency_code\">EUR</span> €12_345.45",
|
74
74
|
m.to_s(:html => true, :code => true, :thousands_separator => '_')
|
75
75
|
end
|
76
76
|
|
data/test/money_test.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# Copyright (C) 2006-2007 Kurt Stephens <ruby-currency(at)umleta.com>
|
2
|
+
# See LICENSE.txt for details.
|
1
3
|
|
2
4
|
|
3
5
|
require 'test/test_base'
|
@@ -293,7 +295,7 @@ class MoneyTest < TestBase
|
|
293
295
|
assert usd.time == usd2.time
|
294
296
|
end
|
295
297
|
|
296
|
-
end
|
298
|
+
end # class
|
297
299
|
|
298
300
|
end # module
|
299
301
|
|
data/test/test_base.rb
CHANGED
@@ -14,6 +14,9 @@ class TestBase < Test::Unit::TestCase
|
|
14
14
|
super
|
15
15
|
@rate_source ||= get_rate_source
|
16
16
|
Exchange::Rate::Source.default = @rate_source
|
17
|
+
|
18
|
+
# Force non-historical money values.
|
19
|
+
Money.default_time = nil
|
17
20
|
end
|
18
21
|
|
19
22
|
|
@@ -31,8 +34,8 @@ class TestBase < Test::Unit::TestCase
|
|
31
34
|
# Helpers.
|
32
35
|
def assert_equal_float(x, y, eps = 1.0e-8)
|
33
36
|
d = (x * eps).abs
|
34
|
-
assert
|
35
|
-
assert
|
37
|
+
assert((x - d) <= y)
|
38
|
+
assert(y <= (x + d))
|
36
39
|
end
|
37
40
|
|
38
41
|
end # class
|
data/test/xe_test.rb
CHANGED
@@ -16,7 +16,9 @@ class XeTest < TestBase
|
|
16
16
|
|
17
17
|
def get_rate_source
|
18
18
|
source = Exchange::Rate::Source::Xe.new
|
19
|
+
# source.verbose = true
|
19
20
|
deriver = Exchange::Rate::Deriver.new(:source => source)
|
21
|
+
deriver
|
20
22
|
end
|
21
23
|
|
22
24
|
|
@@ -45,7 +47,7 @@ class XeTest < TestBase
|
|
45
47
|
|
46
48
|
assert_kind_of Numeric, m = (eur.to_f / cad.to_f)
|
47
49
|
# $stderr.puts "m = #{m}"
|
48
|
-
assert_equal_float
|
50
|
+
assert_equal_float((1.0 / usd_cad) * usd_eur, m, 0.001)
|
49
51
|
end
|
50
52
|
|
51
53
|
end
|
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-
|
8
|
-
summary: "Currency models currencies, monetary values, foreign exchanges
|
6
|
+
version: 0.4.1
|
7
|
+
date: 2007-03-11 00:00:00 -06: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://currency.rubyforge.org/ http://currency.rubyforge.org/files/README.txt"
|
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
|
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/README.txt"
|
16
16
|
autorequire:
|
17
17
|
default_executable:
|
18
18
|
bindir: bin
|
@@ -42,6 +42,7 @@ files:
|
|
42
42
|
- examples/xe1.rb
|
43
43
|
- lib/currency.rb
|
44
44
|
- lib/currency/active_record.rb
|
45
|
+
- lib/currency/config.rb
|
45
46
|
- lib/currency/core_extensions.rb
|
46
47
|
- lib/currency/currency.rb
|
47
48
|
- lib/currency/currency/factory.rb
|
@@ -72,6 +73,7 @@ files:
|
|
72
73
|
- test/ar_simple_test.rb
|
73
74
|
- test/ar_test_base.rb
|
74
75
|
- test/ar_test_core.rb
|
76
|
+
- test/config_test.rb
|
75
77
|
- test/formatter_test.rb
|
76
78
|
- test/historical_writer_test.rb
|
77
79
|
- test/macro_test.rb
|