acvwilson-currency 0.5.2 → 0.6.0
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/currency.gemspec +4 -4
- data/lib/currency.rb +1 -1
- data/lib/currency/config.rb +26 -24
- data/lib/currency/core_extensions.rb +0 -50
- data/lib/currency/currency.rb +2 -5
- data/lib/currency/currency/factory.rb +14 -4
- data/lib/currency/exchange/rate/source/base.rb +2 -2
- data/lib/currency/exchange/rate/source/federal_reserve.rb +3 -12
- data/lib/currency/exchange/rate/source/provider.rb +7 -10
- data/lib/currency/formatter.rb +0 -2
- data/lib/currency/money.rb +4 -9
- data/spec/ar_column_spec.rb +0 -1
- data/spec/ar_spec_helper.rb +7 -5
- data/spec/config_spec.rb +44 -3
- data/spec/federal_reserve_spec.rb +55 -59
- data/spec/historical_writer_spec.rb +74 -140
- data/spec/spec_helper.rb +4 -4
- metadata +3 -4
- data/spec/ar_core_spec.rb +0 -68
data/currency.gemspec
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
Gem::Specification.new do |s|
|
|
2
2
|
s.name = %q{currency}
|
|
3
|
-
s.version = "0.
|
|
3
|
+
s.version = "0.6.0"
|
|
4
4
|
|
|
5
5
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
6
6
|
s.authors = ["Asa Wilson"]
|
|
7
|
-
s.date = %q{
|
|
7
|
+
s.date = %q{#{Date.today}}
|
|
8
8
|
s.description = %q{Currency conversions for Ruby}
|
|
9
9
|
s.email = ["acvwilson@gmail.com"]
|
|
10
10
|
s.extra_rdoc_files = ["ChangeLog", "COPYING.txt", "LICENSE.txt", "Manifest.txt", "README.txt", "Releases.txt", "TODO.txt"]
|
|
11
|
-
s.files = ["COPYING.txt", "currency.gemspec", "examples/ex1.rb", "examples/xe1.rb", "lib/currency/active_record.rb", "lib/currency/config.rb", "lib/currency/core_extensions.rb", "lib/currency/currency/factory.rb", "lib/currency/currency.rb", "lib/currency/currency_version.rb", "lib/currency/exception.rb", "lib/currency/exchange/rate/deriver.rb", "lib/currency/exchange/rate/source/base.rb", "lib/currency/exchange/rate/source/failover.rb", "lib/currency/exchange/rate/source/federal_reserve.rb", "lib/currency/exchange/rate/source/historical/rate.rb", "lib/currency/exchange/rate/source/historical/rate_loader.rb", "lib/currency/exchange/rate/source/historical/writer.rb", "lib/currency/exchange/rate/source/historical.rb", "lib/currency/exchange/rate/source/new_york_fed.rb", "lib/currency/exchange/rate/source/provider.rb", "lib/currency/exchange/rate/source/test.rb", "lib/currency/exchange/rate/source/the_financials.rb", "lib/currency/exchange/rate/source/timed_cache.rb", "lib/currency/exchange/rate/source/xe.rb", "lib/currency/exchange/rate/source.rb", "lib/currency/exchange/rate.rb", "lib/currency/exchange/time_quantitizer.rb", "lib/currency/exchange.rb", "lib/currency/formatter.rb", "lib/currency/macro.rb", "lib/currency/money.rb", "lib/currency/money_helper.rb", "lib/currency/parser.rb", "lib/currency.rb", "LICENSE.txt", "Manifest.txt", "README.txt", "Releases.txt", "spec/ar_spec_helper.rb", "spec/ar_column_spec.rb", "spec/
|
|
11
|
+
s.files = ["COPYING.txt", "currency.gemspec", "examples/ex1.rb", "examples/xe1.rb", "lib/currency/active_record.rb", "lib/currency/config.rb", "lib/currency/core_extensions.rb", "lib/currency/currency/factory.rb", "lib/currency/currency.rb", "lib/currency/currency_version.rb", "lib/currency/exception.rb", "lib/currency/exchange/rate/deriver.rb", "lib/currency/exchange/rate/source/base.rb", "lib/currency/exchange/rate/source/failover.rb", "lib/currency/exchange/rate/source/federal_reserve.rb", "lib/currency/exchange/rate/source/historical/rate.rb", "lib/currency/exchange/rate/source/historical/rate_loader.rb", "lib/currency/exchange/rate/source/historical/writer.rb", "lib/currency/exchange/rate/source/historical.rb", "lib/currency/exchange/rate/source/new_york_fed.rb", "lib/currency/exchange/rate/source/provider.rb", "lib/currency/exchange/rate/source/test.rb", "lib/currency/exchange/rate/source/the_financials.rb", "lib/currency/exchange/rate/source/timed_cache.rb", "lib/currency/exchange/rate/source/xe.rb", "lib/currency/exchange/rate/source.rb", "lib/currency/exchange/rate.rb", "lib/currency/exchange/time_quantitizer.rb", "lib/currency/exchange.rb", "lib/currency/formatter.rb", "lib/currency/macro.rb", "lib/currency/money.rb", "lib/currency/money_helper.rb", "lib/currency/parser.rb", "lib/currency.rb", "LICENSE.txt", "Manifest.txt", "README.txt", "Releases.txt", "spec/ar_spec_helper.rb", "spec/ar_column_spec.rb", "spec/ar_simple_spec.rb", "spec/config_spec.rb", "spec/federal_reserve_spec.rb", "spec/formatter_spec.rb", "spec/historical_writer_spec.rb", "spec/macro_spec.rb", "spec/money_spec.rb", "spec/new_york_fed_spec.rb", "spec/parser_spec.rb", "spec/spec_helper.rb", "spec/time_quantitizer_spec.rb", "spec/timed_cache_spec.rb", "spec/xe_spec.rb", "TODO.txt"]
|
|
12
12
|
s.has_rdoc = true
|
|
13
13
|
s.homepage = %q{http://currency.rubyforge.org/}
|
|
14
14
|
s.rdoc_options = ["--main", "README.txt"]
|
|
15
15
|
s.require_paths = ["lib"]
|
|
16
16
|
s.rubygems_version = %q{1.2.0}
|
|
17
|
-
s.summary = %q{
|
|
17
|
+
s.summary = %q{#{s.name} #{s.version}}
|
|
18
18
|
end
|
data/lib/currency.rb
CHANGED
|
@@ -140,4 +140,4 @@ require 'currency/exchange/rate/source'
|
|
|
140
140
|
require 'currency/exchange/rate/source/test'
|
|
141
141
|
require 'currency/exchange/time_quantitizer'
|
|
142
142
|
require 'currency/core_extensions'
|
|
143
|
-
require 'active_support'
|
|
143
|
+
require 'active_support' # high(-er) precision rounding
|
data/lib/currency/config.rb
CHANGED
|
@@ -7,38 +7,35 @@
|
|
|
7
7
|
# TO DO:
|
|
8
8
|
#
|
|
9
9
|
# Migrate all class variable configurations to this object.
|
|
10
|
+
# Rewrite this whole class. It is not working at all after first config
|
|
11
|
+
# Threads are bad. Use the Singleton library when rewriting this
|
|
10
12
|
class Currency::Config
|
|
11
|
-
@@default = nil
|
|
12
|
-
|
|
13
13
|
# Returns the default Currency::Config object.
|
|
14
14
|
#
|
|
15
15
|
# If one is not specfied an instance is
|
|
16
16
|
# created. This is a global, not thread-local.
|
|
17
17
|
def self.default
|
|
18
|
-
@@default ||=
|
|
19
|
-
self.new
|
|
18
|
+
@@default ||= self.new
|
|
20
19
|
end
|
|
21
20
|
|
|
22
21
|
# Sets the default Currency::Config object.
|
|
23
22
|
def self.default=(x)
|
|
24
23
|
@@default = x
|
|
24
|
+
Currency::Currency::Factory.reset
|
|
25
|
+
@@default
|
|
25
26
|
end
|
|
26
27
|
|
|
27
|
-
# Returns the current Currency::Config object
|
|
28
|
-
# in the current thread.
|
|
29
|
-
#
|
|
28
|
+
# Returns the current Currency::Config object
|
|
30
29
|
# If #current= has not been called and #default= has not been called,
|
|
31
30
|
# then UndefinedExchange is raised.
|
|
32
31
|
def self.current
|
|
33
|
-
|
|
34
|
-
self.default ||
|
|
35
|
-
(raise ::Currency::Exception::UndefinedConfig, "Currency::Config.default not defined")
|
|
32
|
+
self.default || (raise ::Currency::Exception::UndefinedConfig, "Currency::Config.default not defined")
|
|
36
33
|
end
|
|
37
34
|
|
|
38
35
|
# Sets the current Currency::Config object used
|
|
39
36
|
# in the current thread.
|
|
40
37
|
def self.current=(x)
|
|
41
|
-
|
|
38
|
+
self.default = x
|
|
42
39
|
end
|
|
43
40
|
|
|
44
41
|
# Clones the current configuration and makes it current
|
|
@@ -49,36 +46,29 @@ class Currency::Config
|
|
|
49
46
|
# c.float_ref_filter = Proc.new { | x | x.round }
|
|
50
47
|
# "123.448".money.rep == 12345
|
|
51
48
|
# end
|
|
49
|
+
# TODO: rewrite from scratch
|
|
52
50
|
def self.configure(&blk)
|
|
53
51
|
c_prev = current
|
|
54
52
|
c_new = self.current = current.clone
|
|
55
53
|
result = nil
|
|
56
54
|
begin
|
|
57
55
|
result = yield c_new
|
|
58
|
-
|
|
56
|
+
rescue
|
|
59
57
|
self.current = c_prev
|
|
60
58
|
end
|
|
61
59
|
result
|
|
62
60
|
end
|
|
63
61
|
|
|
64
62
|
|
|
65
|
-
@@identity = Proc.new { |x| x } # :nodoc:
|
|
66
|
-
|
|
67
63
|
# Returns the current Float conversion filter.
|
|
68
64
|
# Can be used to set rounding or truncation policies when converting
|
|
69
65
|
# Float values to Money values.
|
|
70
66
|
# Defaults to an identity function.
|
|
71
67
|
# See Float#Money_rep.
|
|
68
|
+
attr_accessor :float_ref_filter
|
|
72
69
|
def float_ref_filter
|
|
73
|
-
@float_ref_filter ||=
|
|
74
|
-
@@identity
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
# Sets the current Float conversion filter.
|
|
78
|
-
def float_ref_filter=(x)
|
|
79
|
-
@float_ref_filter = x
|
|
70
|
+
@float_ref_filter ||= Proc.new { |x| x }
|
|
80
71
|
end
|
|
81
|
-
|
|
82
72
|
|
|
83
73
|
# Defines the table name for Historical::Rate records.
|
|
84
74
|
# Defaults to 'currency_historical_rates'.
|
|
@@ -86,6 +76,18 @@ class Currency::Config
|
|
|
86
76
|
def historical_table_name
|
|
87
77
|
@historical_table_name ||= 'currency_historical_rates'
|
|
88
78
|
end
|
|
79
|
+
|
|
80
|
+
attr_accessor :scale_exp
|
|
81
|
+
def scale_exp=(val)
|
|
82
|
+
raise ArgumentError, "Invalid scale exponent" unless val.integer?
|
|
83
|
+
raise ArgumentError, "Invalid scale: zero" if val.zero?
|
|
84
|
+
@scale_exp = val
|
|
85
|
+
Currency::Currency::Factory.reset
|
|
86
|
+
end
|
|
89
87
|
|
|
90
|
-
|
|
91
|
-
|
|
88
|
+
attr_reader :scale
|
|
89
|
+
def scale
|
|
90
|
+
10 ** (scale_exp || 2)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
end
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# Copyright (C) 2006-2007 Kurt Stephens <ruby-currency(at)umleta.com>
|
|
2
2
|
# See LICENSE.txt for details.
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
4
|
class Object
|
|
7
5
|
# Exact conversion to Money representation value.
|
|
8
6
|
def money(*opts)
|
|
@@ -10,8 +8,6 @@ class Object
|
|
|
10
8
|
end
|
|
11
9
|
end
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
|
|
15
11
|
class Integer
|
|
16
12
|
# Exact conversion to Money representation value.
|
|
17
13
|
def Money_rep(currency, time = nil)
|
|
@@ -19,59 +15,13 @@ class Integer
|
|
|
19
15
|
end
|
|
20
16
|
end
|
|
21
17
|
|
|
22
|
-
# module Asa
|
|
23
|
-
# module Rounding
|
|
24
|
-
# def self.included(base) #:nodoc:
|
|
25
|
-
# puts "included by #{base.inspect}"
|
|
26
|
-
# base.class_eval do
|
|
27
|
-
# alias_method :round_without_precision, :round
|
|
28
|
-
# alias_method :round, :round_with_precision
|
|
29
|
-
# end
|
|
30
|
-
# end
|
|
31
|
-
#
|
|
32
|
-
# # Rounds the float with the specified precision.
|
|
33
|
-
# #
|
|
34
|
-
# # x = 1.337
|
|
35
|
-
# # x.round # => 1
|
|
36
|
-
# # x.round(1) # => 1.3
|
|
37
|
-
# # x.round(2) # => 1.34
|
|
38
|
-
# def round_with_precision(precision = nil)
|
|
39
|
-
# precision.nil? ? round_without_precision : (self * (10 ** precision)).round / (10 ** precision).to_f
|
|
40
|
-
# end
|
|
41
|
-
#
|
|
42
|
-
# end
|
|
43
|
-
# end
|
|
44
|
-
#
|
|
45
|
-
# class Float
|
|
46
|
-
# include Asa::Rounding
|
|
47
|
-
# # Inexact conversion to Money representation value.
|
|
48
|
-
# def Money_rep(currency, time = nil)
|
|
49
|
-
# Integer(Currency::Config.current.float_ref_filter.call(self * currency.scale))
|
|
50
|
-
# end
|
|
51
|
-
# end
|
|
52
|
-
|
|
53
18
|
class Float
|
|
54
19
|
# Inexact conversion to Money representation value.
|
|
55
20
|
def Money_rep(currency, time = nil)
|
|
56
21
|
Integer(Currency::Config.current.float_ref_filter.call(self * currency.scale))
|
|
57
22
|
end
|
|
58
|
-
|
|
59
|
-
# def round_with_awesome_precision(precision = nil)
|
|
60
|
-
# # puts "self: #{self.inspect}"
|
|
61
|
-
# # puts "precision: #{precision.inspect}"
|
|
62
|
-
# # puts "round_without_precision: #{round_without_precision.inspect}"
|
|
63
|
-
# # puts "self * (10 ** precision): #{(self * (10 ** precision)).inspect}"
|
|
64
|
-
# # puts "(self * (10 ** precision)).round_without_precision: #{((self * (10 ** precision)).round_without_precision).inspect}"
|
|
65
|
-
# # self.to_s.to_f.round_without_precision
|
|
66
|
-
# precision.nil? ? round_without_awesome_precision : (self * (10 ** precision)).round_without_awesome_precision / (10 ** precision).to_f
|
|
67
|
-
# end
|
|
68
|
-
# alias_method :round_without_awesome_precision, :round
|
|
69
|
-
# alias_method :round, :round_with_awesome_precision
|
|
70
23
|
end
|
|
71
24
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
25
|
class String
|
|
76
26
|
# Exact conversion to Money representation value.
|
|
77
27
|
def Money_rep(currency, time = nil)
|
data/lib/currency/currency.rb
CHANGED
|
@@ -44,14 +44,11 @@ class Currency::Currency
|
|
|
44
44
|
|
|
45
45
|
# Create a new currency.
|
|
46
46
|
# This should only be called from Currency::Currency::Factory.
|
|
47
|
-
def initialize(code, symbol = nil, scale = 1000000)
|
|
47
|
+
# def initialize(code, symbol = nil, scale = 1000000)
|
|
48
|
+
def initialize(code, symbol = nil, scale = Currency::Config.current.scale)
|
|
48
49
|
self.code = code
|
|
49
50
|
self.symbol = symbol
|
|
50
51
|
self.scale = scale
|
|
51
|
-
|
|
52
|
-
@formatter =
|
|
53
|
-
@parser =
|
|
54
|
-
nil
|
|
55
52
|
end
|
|
56
53
|
|
|
57
54
|
|
|
@@ -22,6 +22,16 @@ class Currency::Currency::Factory
|
|
|
22
22
|
@currency = nil
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
def self.reset
|
|
26
|
+
default.reset
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def reset
|
|
30
|
+
@currency_by_code = { }
|
|
31
|
+
@currency_by_symbol = { }
|
|
32
|
+
@currency = nil
|
|
33
|
+
end
|
|
34
|
+
|
|
25
35
|
|
|
26
36
|
# Lookup Currency by code.
|
|
27
37
|
def get_by_code(x)
|
|
@@ -60,19 +70,19 @@ class Currency::Currency::Factory
|
|
|
60
70
|
# $stderr.puts "load('USD')"
|
|
61
71
|
currency.code = :USD
|
|
62
72
|
currency.symbol = '$'
|
|
63
|
-
currency.scale = 1000000
|
|
73
|
+
# currency.scale = 1000000
|
|
64
74
|
elsif currency.code == :CAD
|
|
65
75
|
# $stderr.puts "load('CAD')"
|
|
66
76
|
currency.symbol = '$'
|
|
67
|
-
currency.scale = 1000000
|
|
77
|
+
# currency.scale = 1000000
|
|
68
78
|
elsif currency.code == :EUR
|
|
69
79
|
# $stderr.puts "load('CAD')"
|
|
70
80
|
currency.symbol = nil
|
|
71
81
|
currency.symbol_html = '€'
|
|
72
|
-
currency.scale = 1000000
|
|
82
|
+
# currency.scale = 1000000
|
|
73
83
|
else
|
|
74
84
|
currency.symbol = nil
|
|
75
|
-
currency.scale = 1000000
|
|
85
|
+
# currency.scale = 1000000
|
|
76
86
|
end
|
|
77
87
|
|
|
78
88
|
# $stderr.puts "AFTER: load(#{currency.inspect})"
|
|
@@ -41,7 +41,7 @@ class Currency::Exchange::Rate::Source::Base
|
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
|
|
44
|
-
def __subclass_responsibility(
|
|
44
|
+
def __subclass_responsibility(method)
|
|
45
45
|
raise ::Currency::Exception::SubclassResponsibility,
|
|
46
46
|
[
|
|
47
47
|
"#{self.class}#\#{meth}",
|
|
@@ -61,7 +61,7 @@ class Currency::Exchange::Rate::Source::Base
|
|
|
61
61
|
m
|
|
62
62
|
else
|
|
63
63
|
rate = rate(c1, c2, time)
|
|
64
|
-
|
|
64
|
+
raise ::Currency::Exception::UnknownRate, "Cannot convert #{m} from #{c1} to #{c2} at time #{time}" unless rate
|
|
65
65
|
|
|
66
66
|
rate && ::Currency::Money(rate.convert(m, c1), c2, time)
|
|
67
67
|
end
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
# Copyright (C) 2006-2007 Kurt Stephens <ruby-currency(at)umleta.com>
|
|
2
2
|
# See LICENSE.txt for details.
|
|
3
3
|
|
|
4
|
-
require '
|
|
4
|
+
require File.dirname(__FILE__) + '/provider'
|
|
5
5
|
|
|
6
6
|
require 'net/http'
|
|
7
7
|
require 'open-uri'
|
|
8
8
|
|
|
9
|
-
|
|
10
9
|
# Connects to http://www.federalreserve.gov/releases/H10/hist/dat00_<country>.txtb
|
|
11
10
|
# Parses all known currency files.
|
|
12
11
|
#
|
|
@@ -26,13 +25,11 @@ class Currency::Exchange::Rate::Source::FederalReserve < ::Currency::Exchange::R
|
|
|
26
25
|
super(*opt)
|
|
27
26
|
end
|
|
28
27
|
|
|
29
|
-
|
|
30
28
|
# Returns 'federalreserve.gov'.
|
|
31
29
|
def name
|
|
32
30
|
'federalreserve.gov'
|
|
33
31
|
end
|
|
34
32
|
|
|
35
|
-
|
|
36
33
|
# FIXME?
|
|
37
34
|
#def available?(time = nil)
|
|
38
35
|
# time ||= Time.now
|
|
@@ -44,7 +41,6 @@ class Currency::Exchange::Rate::Source::FederalReserve < ::Currency::Exchange::R
|
|
|
44
41
|
@raw_rates = nil
|
|
45
42
|
super
|
|
46
43
|
end
|
|
47
|
-
|
|
48
44
|
|
|
49
45
|
def raw_rates
|
|
50
46
|
rates
|
|
@@ -56,8 +52,7 @@ class Currency::Exchange::Rate::Source::FederalReserve < ::Currency::Exchange::R
|
|
|
56
52
|
# See http://www.jhall.demon.co.uk/currency/by_country.html
|
|
57
53
|
#
|
|
58
54
|
# Some data files list reciprocal rates!
|
|
59
|
-
@@country_to_currency =
|
|
60
|
-
{
|
|
55
|
+
@@country_to_currency = {
|
|
61
56
|
'al' => [ :AUD, :USD ],
|
|
62
57
|
# 'au' => :ASH, # AUSTRIAN SHILLING: pre-EUR?
|
|
63
58
|
'bz' => [ :USD, :BRL ],
|
|
@@ -84,7 +79,6 @@ class Currency::Exchange::Rate::Source::FederalReserve < ::Currency::Exchange::R
|
|
|
84
79
|
've' => [ :USD, :VEB ],
|
|
85
80
|
}
|
|
86
81
|
|
|
87
|
-
|
|
88
82
|
# Parses text file for rates.
|
|
89
83
|
def parse_rates(data = nil)
|
|
90
84
|
data = get_page_content unless data
|
|
@@ -122,7 +116,7 @@ class Currency::Exchange::Rate::Source::FederalReserve < ::Currency::Exchange::R
|
|
|
122
116
|
|
|
123
117
|
rate = m[4].to_f
|
|
124
118
|
|
|
125
|
-
STDERR.puts "#{c1} #{c2} #{rate}\t#{date}" if @verbose
|
|
119
|
+
# STDERR.puts "#{c1} #{c2} #{rate}\t#{date}" if @verbose
|
|
126
120
|
|
|
127
121
|
rates << new_rate(c1, c2, rate, date)
|
|
128
122
|
|
|
@@ -140,7 +134,6 @@ class Currency::Exchange::Rate::Source::FederalReserve < ::Currency::Exchange::R
|
|
|
140
134
|
rates
|
|
141
135
|
end
|
|
142
136
|
|
|
143
|
-
|
|
144
137
|
# Return a list of known base rates.
|
|
145
138
|
def load_rates(time = nil)
|
|
146
139
|
# $stderr.puts "#{self}: load_rates(#{time})" if @verbose
|
|
@@ -152,8 +145,6 @@ class Currency::Exchange::Rate::Source::FederalReserve < ::Currency::Exchange::R
|
|
|
152
145
|
end
|
|
153
146
|
rates
|
|
154
147
|
end
|
|
155
|
-
|
|
156
|
-
|
|
157
148
|
end # class
|
|
158
149
|
|
|
159
150
|
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
# Copyright (C) 2006-2007 Kurt Stephens <ruby-currency(at)umleta.com>
|
|
2
2
|
# See LICENSE.txt for details.
|
|
3
3
|
|
|
4
|
-
require '
|
|
5
|
-
|
|
4
|
+
require File.dirname(__FILE__) + '/../source'
|
|
6
5
|
|
|
7
6
|
# Base class for rate data providers.
|
|
8
7
|
# Assumes that rate sources provide more than one rate per query.
|
|
@@ -31,6 +30,7 @@ class Currency::Exchange::Rate::Source::Provider < Currency::Exchange::Rate::Sou
|
|
|
31
30
|
|
|
32
31
|
# Returns the date to query for rates.
|
|
33
32
|
# Defaults to yesterday.
|
|
33
|
+
# TODO: use ActiveSupport here?
|
|
34
34
|
def date
|
|
35
35
|
@date || (Time.now - 24 * 60 * 60) # yesterday.
|
|
36
36
|
end
|
|
@@ -56,19 +56,14 @@ class Currency::Exchange::Rate::Source::Provider < Currency::Exchange::Rate::Sou
|
|
|
56
56
|
|
|
57
57
|
# Returns the URI string as evaluated with this object.
|
|
58
58
|
def get_uri
|
|
59
|
-
uri = self.uri
|
|
60
|
-
uri = "\"#{uri}\""
|
|
61
|
-
uri = instance_eval(uri)
|
|
59
|
+
uri = instance_eval("\"#{self.uri}\"")
|
|
62
60
|
$stderr.puts "#{self}: uri = #{uri.inspect}" if @verbose
|
|
63
61
|
uri
|
|
64
62
|
end
|
|
65
63
|
|
|
66
|
-
|
|
67
64
|
# Returns the URI content.
|
|
68
65
|
def get_page_content
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
data
|
|
66
|
+
open(get_uri) { |data| data.read }
|
|
72
67
|
end
|
|
73
68
|
|
|
74
69
|
|
|
@@ -96,10 +91,12 @@ class Currency::Exchange::Rate::Source::Provider < Currency::Exchange::Rate::Sou
|
|
|
96
91
|
|
|
97
92
|
# Return a matching base rate.
|
|
98
93
|
def get_rate(c1, c2, time)
|
|
94
|
+
# puts "Getting rates for c1: #{c1} and c2: #{c2} at #{time}\n rates: #{rates.map{|r| "#{r.c1}->#{r.c2}"}.inspect}"
|
|
99
95
|
rates.each do | rate |
|
|
96
|
+
# puts " >#{rate.c1} == #{c1} && #{rate.c2} == #{c2} #{rate.c1 == c1} && #{rate.c2.to_s == c2.to_s}< "
|
|
100
97
|
return rate if
|
|
101
98
|
rate.c1 == c1 &&
|
|
102
|
-
rate.c2 == c2 &&
|
|
99
|
+
rate.c2.to_s == c2.to_s && # FIXME: understand why this second param needs to be cast to String for specs to pass
|
|
103
100
|
(! time || normalize_time(rate.date) == time)
|
|
104
101
|
end
|
|
105
102
|
|
data/lib/currency/formatter.rb
CHANGED
data/lib/currency/money.rb
CHANGED
|
@@ -48,16 +48,13 @@ class Currency::Money
|
|
|
48
48
|
# See #Money_rep(currency) mixin.
|
|
49
49
|
#
|
|
50
50
|
def initialize(x, currency = nil, time = nil)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
# Set ivars.
|
|
54
|
-
currency = ::Currency::Currency.get(currency)
|
|
55
|
-
@currency = currency
|
|
51
|
+
@currency = ::Currency::Currency.get(currency)
|
|
56
52
|
@time = time || ::Currency::Money.default_time
|
|
57
53
|
@time = ::Currency::Money.now if @time == :now
|
|
54
|
+
|
|
58
55
|
if x.kind_of?(String)
|
|
59
|
-
if currency
|
|
60
|
-
m = currency.parser_or_default.parse(x, :currency => currency)
|
|
56
|
+
if @currency
|
|
57
|
+
m = @currency.parser_or_default.parse(x, :currency => @currency)
|
|
61
58
|
else
|
|
62
59
|
m = ::Currency::Parser.default.parse(x)
|
|
63
60
|
end
|
|
@@ -237,8 +234,6 @@ class Currency::Money
|
|
|
237
234
|
|
|
238
235
|
# Formats the Money value as a String.
|
|
239
236
|
def to_s(*opt)
|
|
240
|
-
# raise "huh: #{opt.inspect}"
|
|
241
|
-
|
|
242
237
|
@currency.format(self, *opt)
|
|
243
238
|
end
|
|
244
239
|
|
data/spec/ar_column_spec.rb
CHANGED
data/spec/ar_spec_helper.rb
CHANGED
|
@@ -24,6 +24,7 @@ def ar_setup
|
|
|
24
24
|
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
+
# DB Connection info
|
|
27
28
|
def database_spec
|
|
28
29
|
# TODO: Get from ../config/database.yml:test
|
|
29
30
|
# Create test database on:
|
|
@@ -59,6 +60,7 @@ def database_spec
|
|
|
59
60
|
|
|
60
61
|
end
|
|
61
62
|
|
|
63
|
+
# Run AR migrations UP
|
|
62
64
|
def schema_up
|
|
63
65
|
return unless @currency_test_migration
|
|
64
66
|
begin
|
|
@@ -68,6 +70,8 @@ def schema_up
|
|
|
68
70
|
end
|
|
69
71
|
end
|
|
70
72
|
|
|
73
|
+
|
|
74
|
+
# Run AR migrations DOWN
|
|
71
75
|
def schema_down
|
|
72
76
|
return unless @currency_test_migration
|
|
73
77
|
begin
|
|
@@ -77,10 +81,7 @@ def schema_down
|
|
|
77
81
|
end
|
|
78
82
|
end
|
|
79
83
|
|
|
80
|
-
|
|
81
|
-
# Scaffold
|
|
82
|
-
#
|
|
83
|
-
|
|
84
|
+
# Scaffold: insert stuff into DB so we can test AR integration
|
|
84
85
|
def insert_records
|
|
85
86
|
delete_records
|
|
86
87
|
|
|
@@ -99,6 +100,7 @@ end
|
|
|
99
100
|
|
|
100
101
|
##################################################
|
|
101
102
|
|
|
103
|
+
# TODO: need this?
|
|
102
104
|
def assert_equal_money(a,b)
|
|
103
105
|
a.should_not be_nil
|
|
104
106
|
b.should_not be_nil
|
|
@@ -114,7 +116,7 @@ def assert_equal_money(a,b)
|
|
|
114
116
|
b.amount.rep.should == a.amount.convert(b.amount.currency).rep
|
|
115
117
|
end
|
|
116
118
|
|
|
117
|
-
|
|
119
|
+
# TODO: need this?
|
|
118
120
|
def assert_equal_currency(a,b)
|
|
119
121
|
assert_equal_money a, b
|
|
120
122
|
|
data/spec/config_spec.rb
CHANGED
|
@@ -22,8 +22,49 @@ describe Currency::Config do
|
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
end
|
|
25
|
+
|
|
26
|
+
describe "the scale expression is configurable" do
|
|
27
|
+
before(:all) do
|
|
28
|
+
@config = Currency::Config.new
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
before(:each) do
|
|
32
|
+
Currency::Config.current = nil
|
|
33
|
+
Currency::Config.send(:class_variable_set, "@@default", nil)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "should have a scale_exp setter" do
|
|
37
|
+
Currency::Config.current.should respond_to(:scale_exp=)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "has a 'scale' reader" do
|
|
41
|
+
Currency::Config.current.should respond_to(:scale)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "uses the scale reader from the config when creating new Money object" do
|
|
45
|
+
Currency::Config.should_receive(:current).and_return(@config)
|
|
46
|
+
@config.should_receive(:scale).and_return(100)
|
|
47
|
+
10.money
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "can be configured using a block" do
|
|
51
|
+
Currency::Config.configure do |config|
|
|
52
|
+
config.scale_exp = 6
|
|
53
|
+
end
|
|
25
54
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
55
|
+
10.money.currency.scale_exp.should == 6
|
|
56
|
+
|
|
57
|
+
Currency::Config.configure do |config|
|
|
58
|
+
config.scale_exp = 4
|
|
59
|
+
end
|
|
60
|
+
10.money.currency.scale_exp.should == 4
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "can be configured using straight setters" do
|
|
64
|
+
10.money(:USD).currency.scale_exp.should == 2
|
|
65
|
+
Currency::Config.current.scale_exp = 6
|
|
66
|
+
10.money(:USD).currency.scale_exp.should == 6
|
|
67
|
+
end
|
|
68
|
+
end
|
|
29
69
|
|
|
70
|
+
end
|
|
@@ -1,75 +1,71 @@
|
|
|
1
1
|
# Copyright (C) 2006-2007 Kurt Stephens <ruby-currency(at)umleta.com>
|
|
2
2
|
# See LICENSE.txt for details.
|
|
3
3
|
|
|
4
|
-
require '
|
|
4
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
|
5
|
+
require File.dirname(__FILE__) + '/../lib/currency/exchange/rate/source/federal_reserve'
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
# Uncomment to avoid hitting the FED for every testrun
|
|
8
|
+
Currency::Exchange::Rate::Source::FederalReserve.class_eval do
|
|
9
|
+
def get_page_content
|
|
10
|
+
%Q{
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
SPOT EXCHANGE RATE - DISNEYLAND
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
------------------------------
|
|
15
|
+
14-Nov-08 1.1
|
|
16
|
+
}
|
|
14
17
|
end
|
|
18
|
+
end
|
|
15
19
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
# New York Fed rates are not available on Saturday and Sunday.
|
|
20
|
+
include Currency
|
|
21
|
+
describe "FederalReserve" do
|
|
20
22
|
def available?
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
STDERR.puts "Warning: FederalReserve unavailable on Saturday and Sunday, skipping tests." unless
|
|
23
|
+
unless @available
|
|
24
|
+
@available = @source.available?
|
|
25
|
+
STDERR.puts "Warning: FederalReserve unavailable on Saturday and Sunday, skipping tests." unless @available
|
|
24
26
|
end
|
|
25
|
-
|
|
27
|
+
@available
|
|
26
28
|
end
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
deriver
|
|
29
|
+
|
|
30
|
+
# Called by the before(:all) in spec_helper
|
|
31
|
+
# Overriding here to force FederalReserve Exchange.
|
|
32
|
+
# TODO: when refactoring the whole spec to test only specific FedralReserve Stuff, make sure this one goes away
|
|
33
|
+
def get_rate_source(source = nil)
|
|
34
|
+
@source ||= Exchange::Rate::Source::FederalReserve.new(:verbose => false)
|
|
35
|
+
@deriver ||= Exchange::Rate::Deriver.new(:source => @source, :verbose => @source.verbose)
|
|
34
36
|
end
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
it "usd cad" do
|
|
39
|
-
return unless available?
|
|
40
|
-
|
|
41
|
-
# yesterday = Time.now.to_date - 1
|
|
42
|
-
|
|
43
|
-
rates = Exchange::Rate::Source.default.source.raw_rates.should_not == nil
|
|
44
|
-
#assert_not_nil rates[:USD]
|
|
45
|
-
#assert_not_nil usd_cad = rates[:USD][:CAD]
|
|
46
|
-
|
|
47
|
-
usd = Money.new(123.45, :USD).should_not == nil
|
|
48
|
-
cad = usd.convert(:CAD).should_not == nil
|
|
49
|
-
|
|
50
|
-
# assert_kind_of Numeric, m = (cad.to_f / usd.to_f)
|
|
51
|
-
# $stderr.puts "m = #{m}"
|
|
52
|
-
# assert_equal_float usd_cad, m, 0.001
|
|
37
|
+
|
|
38
|
+
def get_rates
|
|
39
|
+
@rates ||= @source.raw_rates
|
|
53
40
|
end
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
#assert_kind_of Numeric, m = (eur.to_f / cad.to_f)
|
|
68
|
-
# $stderr.puts "m = #{m}"
|
|
69
|
-
#assert_equal_float (1.0 / usd_cad) * usd_eur, m, 0.001
|
|
41
|
+
|
|
42
|
+
before(:all) do
|
|
43
|
+
get_rate_source
|
|
44
|
+
get_rates
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
before(:each) do
|
|
48
|
+
get_rate_source
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "can retrieve rates from the FED" do
|
|
52
|
+
@rates.should_not be_nil
|
|
70
53
|
end
|
|
71
54
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
end # module
|
|
55
|
+
it "can convert from USD to CAD" do
|
|
56
|
+
usd = Money.new(123.45, :USD)
|
|
75
57
|
|
|
58
|
+
cad = usd.convert(:CAD)
|
|
59
|
+
cad.should_not be_nil
|
|
60
|
+
cad.to_f.should be_kind_of(Numeric)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "can do conversions from AUD to USD to JPY" do
|
|
64
|
+
aud = Money.new(123.45, :AUD)
|
|
65
|
+
usd = aud.convert(:USD)
|
|
66
|
+
jpy = usd.convert(:JPY)
|
|
67
|
+
jpy.should_not be_nil
|
|
68
|
+
jpy.to_f.should be_kind_of(Numeric)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
end
|
|
@@ -1,56 +1,42 @@
|
|
|
1
1
|
# Copyright (C) 2006-2007 Kurt Stephens <ruby-currency(at)umleta.com>
|
|
2
2
|
# See LICENSE.txt for details.
|
|
3
|
+
require File.dirname(__FILE__) + '/ar_spec_helper'
|
|
3
4
|
|
|
4
|
-
require '
|
|
5
|
+
require File.dirname(__FILE__) + '/../lib/currency/exchange/rate/source/historical'
|
|
6
|
+
require File.dirname(__FILE__) + '/../lib/currency/exchange/rate/source/historical/writer'
|
|
7
|
+
require File.dirname(__FILE__) + '/../lib/currency/exchange/rate/source/xe'
|
|
8
|
+
require File.dirname(__FILE__) + '/../lib/currency/exchange/rate/source/new_york_fed'
|
|
5
9
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
10
|
+
include Currency
|
|
11
|
+
RATE_CLASS = Exchange::Rate::Source::Historical::Rate
|
|
12
|
+
TABLE_NAME = RATE_CLASS.table_name
|
|
9
13
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
require 'currency/exchange/rate/source/historical/writer'
|
|
14
|
-
require 'currency/exchange/rate/source/xe'
|
|
15
|
-
require 'currency/exchange/rate/source/new_york_fed'
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
module Currency
|
|
19
|
-
|
|
20
|
-
class HistoricalWriterTest < ArTestBase
|
|
21
|
-
|
|
22
|
-
RATE_CLASS = Exchange::Rate::Source::Historical::Rate
|
|
23
|
-
TABLE_NAME = RATE_CLASS.table_name
|
|
24
|
-
|
|
25
|
-
class HistoricalRateMigration < AR_M
|
|
26
|
-
def self.up
|
|
27
|
-
RATE_CLASS.__create_table(self)
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def self.down
|
|
31
|
-
drop_table TABLE_NAME.intern
|
|
32
|
-
end
|
|
14
|
+
class HistoricalRateMigration < ActiveRecord::Migration
|
|
15
|
+
def self.up
|
|
16
|
+
RATE_CLASS.__create_table(self)
|
|
33
17
|
end
|
|
34
18
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
@currency_test_migration = HistoricalRateMigration
|
|
38
|
-
super
|
|
39
|
-
|
|
40
|
-
@src = Exchange::Rate::Source::Xe.new
|
|
41
|
-
@src2 = Exchange::Rate::Source::NewYorkFed.new
|
|
19
|
+
def self.down
|
|
20
|
+
drop_table TABLE_NAME.to_sym
|
|
42
21
|
end
|
|
22
|
+
end
|
|
43
23
|
|
|
44
|
-
|
|
45
|
-
before do
|
|
46
|
-
|
|
47
|
-
|
|
24
|
+
describe "HistoricalWriter" do
|
|
25
|
+
before(:all) do
|
|
26
|
+
ActiveRecord::Base.establish_connection(database_spec)
|
|
27
|
+
@currency_test_migration ||= HistoricalRateMigration
|
|
28
|
+
schema_down
|
|
29
|
+
schema_up
|
|
30
|
+
@xe_src = Exchange::Rate::Source::Xe.new
|
|
31
|
+
@fed_src = Exchange::Rate::Source::NewYorkFed.new
|
|
48
32
|
end
|
|
49
|
-
|
|
50
33
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
34
|
+
after(:all) do
|
|
35
|
+
schema_down
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def setup_writer(source)
|
|
39
|
+
writer = Exchange::Rate::Source::Historical::Writer.new
|
|
54
40
|
writer.time_quantitizer = :current
|
|
55
41
|
writer.required_currencies = [ :USD, :GBP, :EUR, :CAD ]
|
|
56
42
|
writer.base_currencies = [ :USD ]
|
|
@@ -58,130 +44,78 @@ class HistoricalWriterTest < ArTestBase
|
|
|
58
44
|
writer.reciprocal_rates = true
|
|
59
45
|
writer.all_rates = true
|
|
60
46
|
writer.identity_rates = false
|
|
61
|
-
|
|
47
|
+
writer.source = source
|
|
62
48
|
writer
|
|
63
49
|
end
|
|
64
50
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
writer = test_writer
|
|
68
|
-
writer.source = @src
|
|
69
|
-
rates = writer.write_rates
|
|
70
|
-
rates.should_not == nil
|
|
71
|
-
rates.size.should > 0
|
|
72
|
-
12, rates.size.should_not == nil
|
|
73
|
-
assert_h_rates(rates, writer)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
def writer_src2
|
|
78
|
-
writer = test_writer
|
|
79
|
-
writer.source = @src2
|
|
80
|
-
return unless writer.source.available?
|
|
51
|
+
it "can read, parse and write XE data" do
|
|
52
|
+
writer = setup_writer(@xe_src)
|
|
81
53
|
rates = writer.write_rates
|
|
82
|
-
rates.should_not == nil
|
|
83
|
-
rates.size.should > 0
|
|
84
54
|
rates.size.should == 12
|
|
85
55
|
assert_h_rates(rates, writer)
|
|
86
56
|
end
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
assert_raises(::RuntimeError) { writer.selected_rates }
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
it "historical rates" do
|
|
100
|
-
# Make sure there are historical Rates avail for today.
|
|
101
|
-
writer_src
|
|
102
|
-
writer_src2
|
|
103
|
-
|
|
104
|
-
# Force Historical Rate Source.
|
|
105
|
-
source = Exchange::Rate::Source::Historical.new
|
|
106
|
-
deriver = Exchange::Rate::Deriver.new(:source => source)
|
|
107
|
-
Exchange::Rate::Source.default = deriver
|
|
108
|
-
|
|
109
|
-
rates = source.get_raw_rates.should_not == nil
|
|
110
|
-
rates.empty?.should_not == true
|
|
111
|
-
# $stderr.puts "historical rates = #{rates.inspect}"
|
|
112
|
-
|
|
113
|
-
rates = source.get_rates.should_not == nil
|
|
114
|
-
rates.empty?.should_not == true
|
|
115
|
-
# $stderr.puts "historical rates = #{rates.inspect}"
|
|
116
|
-
|
|
117
|
-
m_usd = ::Currency.Money('1234.56', :USD, :now).should_not == nil
|
|
118
|
-
# $stderr.puts "m_usd = #{m_usd.to_s(:code => true)}"
|
|
119
|
-
m_eur = m_usd.convert(:EUR).should_not == nil
|
|
120
|
-
# $stderr.puts "m_eur = #{m_eur.to_s(:code => true)}"
|
|
121
|
-
|
|
57
|
+
|
|
58
|
+
it "can read, parse and write NewYorkFed data (will fail on weekends)" do
|
|
59
|
+
if @fed_src.available?
|
|
60
|
+
writer = setup_writer(@fed_src)
|
|
61
|
+
rates = writer.write_rates
|
|
62
|
+
rates.size.should == 12
|
|
63
|
+
assert_h_rates(rates, writer)
|
|
64
|
+
end
|
|
122
65
|
end
|
|
123
|
-
|
|
124
|
-
|
|
66
|
+
|
|
125
67
|
def assert_h_rates(rates, writer = nil)
|
|
126
|
-
hr0 = rates[0]
|
|
68
|
+
hr0 = rates[0]
|
|
69
|
+
hr0.should_not be_nil
|
|
127
70
|
rates.each do | hr |
|
|
128
71
|
found_hr = nil
|
|
129
72
|
begin
|
|
130
|
-
found_hr = hr.find_matching_this(:first)
|
|
73
|
+
found_hr = hr.find_matching_this(:first)
|
|
74
|
+
found_hr.should_not be_nil
|
|
131
75
|
rescue Object => err
|
|
132
76
|
raise "#{hr.inspect}: #{err}:\n#{err.backtrace.inspect}"
|
|
133
77
|
end
|
|
134
|
-
|
|
135
|
-
hr0.should_not == nil
|
|
136
|
-
|
|
137
|
-
hr.date.should == hr0.date
|
|
138
|
-
hr.date_0.should == hr0.date_0
|
|
139
|
-
hr.date_1.should == hr0.date_1
|
|
140
|
-
hr.source.should == hr0.source
|
|
141
|
-
|
|
142
78
|
assert_equal_rate(hr, found_hr)
|
|
143
79
|
assert_rate_defaults(hr, writer)
|
|
80
|
+
|
|
81
|
+
hr.instance_eval do
|
|
82
|
+
date.should == hr0.date
|
|
83
|
+
date_0.should == hr0.date_0
|
|
84
|
+
date_1.should == hr0.date_1
|
|
85
|
+
source.should == hr0.source
|
|
86
|
+
end
|
|
144
87
|
end
|
|
145
88
|
end
|
|
146
89
|
|
|
147
|
-
|
|
148
90
|
def assert_equal_rate(hr0, hr)
|
|
91
|
+
tollerance = 0.00001
|
|
149
92
|
hr.c1.to_s.should == hr0.c1.to_s
|
|
150
93
|
hr.c2.to_s.should == hr0.c2.to_s
|
|
151
94
|
hr.source.should == hr0.source
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
95
|
+
|
|
96
|
+
hr0.rate.should be_close(hr.rate, tollerance)
|
|
97
|
+
hr0.rate_avg.should be_close(hr.rate_avg, tollerance)
|
|
98
|
+
hr0.rate_samples.should == hr.rate_samples.should
|
|
99
|
+
|
|
100
|
+
hr0.rate_lo.should be_close(hr.rate_lo, tollerance)
|
|
101
|
+
hr0.rate_hi.should be_close(hr.rate_hi, tollerance)
|
|
102
|
+
hr0.rate_date_0.should be_close(hr.rate_date_0, tollerance)
|
|
103
|
+
hr0.rate_date_1.should be_close(hr.rate_date_1, tollerance)
|
|
104
|
+
|
|
105
|
+
hr0.date.should == hr.date
|
|
106
|
+
hr0.date_0.should == hr.date_0
|
|
107
|
+
hr0.date_1.should == hr.date_1
|
|
108
|
+
hr0.derived.should == hr.derived
|
|
163
109
|
end
|
|
164
110
|
|
|
165
|
-
|
|
166
111
|
def assert_rate_defaults(hr, writer)
|
|
167
|
-
hr.source
|
|
168
|
-
hr.rate_avg.should
|
|
169
|
-
|
|
170
|
-
hr.rate_lo.should
|
|
171
|
-
hr.rate_hi.should
|
|
172
|
-
hr.rate_date_0.should
|
|
173
|
-
hr.rate_date_1.should
|
|
112
|
+
hr.source.should == writer.source.name
|
|
113
|
+
hr.rate_avg.should == hr.rate
|
|
114
|
+
hr.rate_samples.should == 1
|
|
115
|
+
hr.rate_lo.should == hr.rate
|
|
116
|
+
hr.rate_hi.should == hr.rate
|
|
117
|
+
hr.rate_date_0.should == hr.rate
|
|
118
|
+
hr.rate_date_1.should == hr.rate
|
|
174
119
|
end
|
|
175
120
|
|
|
176
|
-
|
|
177
|
-
def assert_equal_float(x1, x2, eps = 0.00001)
|
|
178
|
-
eps = (x1 * eps).abs
|
|
179
|
-
assert((x1 - eps) <= x2)
|
|
180
|
-
assert((x1 + eps) >= x2)
|
|
181
|
-
end
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
end # module
|
|
187
|
-
|
|
121
|
+
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -5,16 +5,16 @@ require 'spec'
|
|
|
5
5
|
require File.dirname(__FILE__) + '/../lib/currency'
|
|
6
6
|
require File.dirname(__FILE__) + '/../lib/currency/exchange/rate/source/test'
|
|
7
7
|
|
|
8
|
-
def setup
|
|
9
|
-
rate_source ||= get_rate_source
|
|
8
|
+
def setup(source = nil)
|
|
9
|
+
rate_source ||= get_rate_source(source)
|
|
10
10
|
Currency::Exchange::Rate::Source.default = rate_source
|
|
11
11
|
|
|
12
12
|
# Force non-historical money values.
|
|
13
13
|
Currency::Money.default_time = nil
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
def get_rate_source
|
|
17
|
-
source
|
|
16
|
+
def get_rate_source(source = nil)
|
|
17
|
+
source ||= Currency::Exchange::Rate::Source::Test.instance
|
|
18
18
|
Currency::Exchange::Rate::Deriver.new(:source => source)
|
|
19
19
|
end
|
|
20
20
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: acvwilson-currency
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Asa Wilson
|
|
@@ -9,7 +9,7 @@ autorequire:
|
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
11
|
|
|
12
|
-
date: 2008-11-
|
|
12
|
+
date: 2008-11-18 06:18:56.586682 -08:00
|
|
13
13
|
default_executable:
|
|
14
14
|
dependencies: []
|
|
15
15
|
|
|
@@ -70,7 +70,6 @@ files:
|
|
|
70
70
|
- Releases.txt
|
|
71
71
|
- spec/ar_spec_helper.rb
|
|
72
72
|
- spec/ar_column_spec.rb
|
|
73
|
-
- spec/ar_core_spec.rb
|
|
74
73
|
- spec/ar_simple_spec.rb
|
|
75
74
|
- spec/config_spec.rb
|
|
76
75
|
- spec/federal_reserve_spec.rb
|
|
@@ -112,6 +111,6 @@ rubyforge_project:
|
|
|
112
111
|
rubygems_version: 1.2.0
|
|
113
112
|
signing_key:
|
|
114
113
|
specification_version: 2
|
|
115
|
-
summary:
|
|
114
|
+
summary: "#{s.name} #{s.version}"
|
|
116
115
|
test_files: []
|
|
117
116
|
|
data/spec/ar_core_spec.rb
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
# Copyright (C) 2006-2007 Kurt Stephens <ruby-currency(at)umleta.com>
|
|
2
|
-
# See LICENSE.txt for details.
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
# =================================================================
|
|
6
|
-
# = TODO: IS THIS STUFF ACTUALLY NEEDED? IF SO, MOVE TO AR HELPER =
|
|
7
|
-
# =================================================================
|
|
8
|
-
require 'test/ar_test_base'
|
|
9
|
-
|
|
10
|
-
module Currency
|
|
11
|
-
|
|
12
|
-
class ArTestCore < ArTestBase
|
|
13
|
-
|
|
14
|
-
##################################################
|
|
15
|
-
# Basic CurrenyTest AR::B class
|
|
16
|
-
#
|
|
17
|
-
|
|
18
|
-
TABLE_NAME = 'currency_test'
|
|
19
|
-
|
|
20
|
-
class CurrencyTestMigration < AR_M
|
|
21
|
-
def self.up
|
|
22
|
-
create_table TABLE_NAME.intern do |t|
|
|
23
|
-
t.column :name, :string
|
|
24
|
-
t.column :amount, :integer # Money
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def self.down
|
|
29
|
-
drop_table TABLE_NAME.intern
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
class CurrencyTest < AR_B
|
|
35
|
-
set_table_name TABLE_NAME
|
|
36
|
-
attr_money :amount
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
##################################################
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
before do
|
|
44
|
-
@currency_test_migration ||= CurrencyTestMigration
|
|
45
|
-
@currency_test ||= CurrencyTest
|
|
46
|
-
super
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def teardown
|
|
51
|
-
super
|
|
52
|
-
# schema_down
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
##################################################
|
|
57
|
-
#
|
|
58
|
-
#
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
it "insert" do
|
|
62
|
-
insert_records
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
end # module
|
|
68
|
-
|