currency 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 and rates.
23
- Pulls live rates from http://xe.com/.
24
- Supports ActiveRecord.
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" unless opts[:allow_nil]
204
- validate << "\nvalidates_format_of :#{currency_column}, :with => /^[A-Z][A-Z][A-Z]$/\n" if currency_column && ! opts[:allow_nil]
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
+
@@ -24,7 +24,7 @@ end
24
24
  class Float
25
25
  # Inexact conversion to Money representation value.
26
26
  def Money_rep(currency, time = nil)
27
- Integer(self * currency.scale)
27
+ Integer(Currency::Config.current.float_ref_filter.call(self * currency.scale))
28
28
  end
29
29
  end
30
30
 
@@ -1,5 +1,5 @@
1
1
  module Currency
2
- CurrencyVersion = '0.4.0'
2
+ CurrencyVersion = '0.4.1'
3
3
  end
4
4
  # DO NOT EDIT
5
5
  # This file is auto-generated by build scripts.
@@ -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.xe_rates[:USD][:CAD] => 1.0134
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(/[\r\n]/)
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
- # Look for date.
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
- until data.empty?
84
- line = data.shift
85
- break if line =~ /Confused about how to use the rates/i
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
- until data.empty?
97
- line = data.shift
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
- # $stderr.puts "Found currency header: #{cur.inspect} at #{cur_i}"
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
- # $stderr.puts "#{data[0..4].inspect}"
108
-
109
- # Skip blank <tr>
110
- until data.empty?
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&nbsp;+USD&nbsp;=/
81
+
122
82
  # Read first row of 1 USD = ...
123
-
124
83
  rate = { }
125
- cur_i = -1
126
- until data.empty?
127
- line = data.shift
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
- next unless cur
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)
@@ -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
  # => "&#8364;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
- decimal = x[currency.format_right .. -1]
198
+ fraction = x[currency.format_right .. -1]
101
199
 
102
- # Do commas
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
- x << @decimal_separator + decimal if @cents && @decimal_separator
112
-
113
- # Put sign back.
114
- x = '-' + x if neg
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
- x = ((@html && currency.symbol_html) || currency.symbol || '') + x if @symbol
215
+ tmpl.symbol = @symbol ? ((@html && currency.symbol_html) || currency.symbol) : nil
216
+
118
217
 
119
218
  # Suffix with currency code.
120
- if @code
121
- x << (' ' + _format_Currency(currency))
122
- end
219
+ tmpl.code = @code ? _format_Currency(currency) : nil
123
220
 
124
- x
221
+ # Ask template to format the components.
222
+ tmpl.format
125
223
  end
126
224
 
127
225
 
@@ -150,7 +150,7 @@ class Currency::Money
150
150
  self
151
151
  else
152
152
  time = self.time if time == :money
153
- Exchange::Rate::Source.current.convert(self, currency, time)
153
+ ::Currency::Exchange::Rate::Source.current.convert(self, currency, time)
154
154
  end
155
155
  end
156
156
 
@@ -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
+
@@ -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 USD", m.to_s(:code => true)
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 "$12.45 <span class=\"currency_code\">USD</span>",
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 "&#8364;12.45 <span class=\"currency_code\">EUR</span>",
69
+ assert_equal "<span class=\"currency_code\">EUR</span> &#8364;12.45",
70
70
  m.to_s(:html => true, :code => true)
71
71
 
72
- m = ::Currency::Money(12.45, :EUR)
73
- assert_equal "&#8364;12.45 <span class=\"currency_code\">EUR</span>",
72
+ m = ::Currency::Money(12345.45, :EUR)
73
+ assert_equal "<span class=\"currency_code\">EUR</span> &#8364;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 (x - d) <= y
35
- assert y <= (x + d)
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 (1.0 / usd_cad) * usd_eur, m, 0.001
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.0
7
- date: 2007-02-21 00:00:00 -05:00
8
- summary: "Currency models currencies, monetary values, foreign exchanges and rates. Pulls live rates from http://xe.com/. Supports ActiveRecord. For more details, see: http://currency.rubyforge.org/files/lib/currency_rb.html http://currency.rubyforge.org/files/README.txt http://currency.rubyforge.org/"
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 and rates. Pulls live rates from http://xe.com/. Supports ActiveRecord. For more details, see: http://currency.rubyforge.org/files/lib/currency_rb.html http://currency.rubyforge.org/files/README.txt http://currency.rubyforge.org/"
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