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 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