acvwilson-currency 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING.txt +339 -0
- data/ChangeLog +8 -0
- data/LICENSE.txt +65 -0
- data/Manifest.txt +58 -0
- data/README.txt +51 -0
- data/Releases.txt +155 -0
- data/TODO.txt +9 -0
- data/currency.gemspec +18 -0
- data/examples/ex1.rb +13 -0
- data/examples/xe1.rb +20 -0
- data/lib/currency.rb +143 -0
- data/lib/currency/active_record.rb +265 -0
- data/lib/currency/config.rb +91 -0
- data/lib/currency/core_extensions.rb +83 -0
- data/lib/currency/currency.rb +175 -0
- data/lib/currency/currency/factory.rb +121 -0
- data/lib/currency/currency_version.rb +6 -0
- data/lib/currency/exception.rb +119 -0
- data/lib/currency/exchange.rb +48 -0
- data/lib/currency/exchange/rate.rb +214 -0
- data/lib/currency/exchange/rate/deriver.rb +157 -0
- data/lib/currency/exchange/rate/source.rb +89 -0
- data/lib/currency/exchange/rate/source/base.rb +166 -0
- data/lib/currency/exchange/rate/source/failover.rb +63 -0
- data/lib/currency/exchange/rate/source/federal_reserve.rb +160 -0
- data/lib/currency/exchange/rate/source/historical.rb +79 -0
- data/lib/currency/exchange/rate/source/historical/rate.rb +184 -0
- data/lib/currency/exchange/rate/source/historical/rate_loader.rb +186 -0
- data/lib/currency/exchange/rate/source/historical/writer.rb +220 -0
- data/lib/currency/exchange/rate/source/new_york_fed.rb +127 -0
- data/lib/currency/exchange/rate/source/provider.rb +120 -0
- data/lib/currency/exchange/rate/source/test.rb +50 -0
- data/lib/currency/exchange/rate/source/the_financials.rb +191 -0
- data/lib/currency/exchange/rate/source/timed_cache.rb +198 -0
- data/lib/currency/exchange/rate/source/xe.rb +165 -0
- data/lib/currency/exchange/time_quantitizer.rb +111 -0
- data/lib/currency/formatter.rb +310 -0
- data/lib/currency/macro.rb +321 -0
- data/lib/currency/money.rb +298 -0
- data/lib/currency/money_helper.rb +13 -0
- data/lib/currency/parser.rb +193 -0
- data/spec/ar_column_spec.rb +76 -0
- data/spec/ar_core_spec.rb +68 -0
- data/spec/ar_simple_spec.rb +23 -0
- data/spec/config_spec.rb +29 -0
- data/spec/federal_reserve_spec.rb +75 -0
- data/spec/formatter_spec.rb +72 -0
- data/spec/historical_writer_spec.rb +187 -0
- data/spec/macro_spec.rb +109 -0
- data/spec/money_spec.rb +355 -0
- data/spec/new_york_fed_spec.rb +73 -0
- data/spec/parser_spec.rb +105 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/time_quantitizer_spec.rb +115 -0
- data/spec/timed_cache_spec.rb +95 -0
- data/spec/xe_spec.rb +50 -0
- metadata +117 -0
data/README.txt
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
= Currency
|
2
|
+
|
3
|
+
This is the git@cdscm Currency package.
|
4
|
+
|
5
|
+
== Installation
|
6
|
+
|
7
|
+
gem install currency
|
8
|
+
|
9
|
+
== Documentation
|
10
|
+
|
11
|
+
"Project Info":http://rubyforge.org/projects/currency/
|
12
|
+
|
13
|
+
"API Documentation":http://currency.rubyforge.org/
|
14
|
+
|
15
|
+
The RubyForge package currency
|
16
|
+
implements an object-oriented representation of currencies, monetary values, foreign exchanges and rates.
|
17
|
+
|
18
|
+
Currency::Money uses a scaled integer representation of the monetary value and performs accurate conversions from string values.
|
19
|
+
|
20
|
+
See also: http://umleta.com/node/5
|
21
|
+
|
22
|
+
== Home page
|
23
|
+
|
24
|
+
* {Currency Home}[git@cdscm:currency.git]
|
25
|
+
|
26
|
+
== Additional directories
|
27
|
+
|
28
|
+
[./lib/...] the Currency library
|
29
|
+
[./test/...] unit and functional test
|
30
|
+
[./examples/...] example programs
|
31
|
+
|
32
|
+
== Credits
|
33
|
+
|
34
|
+
Currency was developed by:
|
35
|
+
|
36
|
+
* Kurt Stephens -- ruby-currency(at)umleta.com, sponsored by umleta.com
|
37
|
+
|
38
|
+
== License
|
39
|
+
|
40
|
+
* See LICENSE.txt
|
41
|
+
|
42
|
+
== Copyright
|
43
|
+
|
44
|
+
* Copyright (C) 2006-2007 Kurt Stephens <ruby-currency(at)umleta.com>
|
45
|
+
|
46
|
+
== Contributors
|
47
|
+
|
48
|
+
* Steffen Rusitschka
|
49
|
+
|
50
|
+
|
51
|
+
|
data/Releases.txt
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
= Currency Release History
|
2
|
+
|
3
|
+
== Release 0.4.11: 2007/11/02
|
4
|
+
|
5
|
+
CRITICAL FIXES
|
6
|
+
|
7
|
+
* parser.rb - uncommitted typos.
|
8
|
+
|
9
|
+
== Release 0.4.10: 2007/11/01
|
10
|
+
|
11
|
+
CRITICAL FIXES
|
12
|
+
|
13
|
+
* xe.rb - http://xe.com format change: Handle inline div in rates table.
|
14
|
+
* bin/currency_historical_rate_load - script for pulling rates from sources into historical rate table.
|
15
|
+
* exception.rb - Currency::Exception::Base can take Array with optional key/values.
|
16
|
+
* exception.rb - Additional exception classes.
|
17
|
+
* ALL - use raise instead of throw throughout.
|
18
|
+
|
19
|
+
|
20
|
+
== Release 0.4.9: 2007/11/01
|
21
|
+
|
22
|
+
** IGNORE THIS RELEASE**
|
23
|
+
|
24
|
+
* Broken rubyforge config.
|
25
|
+
|
26
|
+
== Release 0.4.7: 2007/06/25
|
27
|
+
|
28
|
+
CRITICAL FIXES
|
29
|
+
|
30
|
+
* NewYorkFed: CRITICAL FIX:
|
31
|
+
|
32
|
+
Rates for USDAUD, USDEUR, USDNZD and USDGBP were reciprocals.
|
33
|
+
See http://www.newyorkfed.org/markets/fxrates/noon.cfm
|
34
|
+
|
35
|
+
* FederalReserve: Added support for historical rates from http://www.federalreserve.gov/releases/H10/hist
|
36
|
+
* Provider#get_rate(): Return first rate immediately.
|
37
|
+
* Rate::Writable for rate summary computation support.
|
38
|
+
* Rate: collect_rate(): fixed rate_date_1.
|
39
|
+
* Historical::Rate: to_rate(): takes optional class.
|
40
|
+
* Historical::Rate: from_rate(): fixed rate_samples.
|
41
|
+
|
42
|
+
== Release 0.4.6: 2007/05/29
|
43
|
+
|
44
|
+
* NewYorkFed: changed FEXtime to FEXTIME.
|
45
|
+
* Fixed Rate#collect_rates, source, rate_date_0, rate_date_1.
|
46
|
+
|
47
|
+
== Release 0.4.5: 2007/05/29
|
48
|
+
|
49
|
+
* Historical::Rate table name can be configured in Currency::Config.current.historical_table_name
|
50
|
+
* Fixed Rate::Source::TheFinancials.
|
51
|
+
* Examples: use Currency.Money(), not Currency::Money.new().
|
52
|
+
|
53
|
+
== Release 0.4.4: 2007/04/01
|
54
|
+
|
55
|
+
MAY NOT BE BACKWARDS-COMPATIBLE
|
56
|
+
|
57
|
+
* Fixed TimedCache.
|
58
|
+
* Updated documentation.
|
59
|
+
* Added support for Parser#time = :now.
|
60
|
+
* Added support for Time in Formatter and Parser using Time#xmlschema.
|
61
|
+
* Money#inspect now appends Money#time, if set.
|
62
|
+
|
63
|
+
== Release 0.4.3: 2007/04/01
|
64
|
+
|
65
|
+
* Added available? checks for NewYorkFed.
|
66
|
+
* Created new UnavailableRates exception for rate providers that return no rates (New York Fed on weekends).
|
67
|
+
* Fixed xe.com rate dates.
|
68
|
+
* Refactored exceptions.
|
69
|
+
* Fixed comments.
|
70
|
+
|
71
|
+
== Release 0.4.2: 2007/03/11
|
72
|
+
|
73
|
+
* Missing Manifest changes
|
74
|
+
* Missing Contributors
|
75
|
+
|
76
|
+
== Release 0.4.1: 2007/03/10
|
77
|
+
|
78
|
+
Some changes are not backwards-compatible
|
79
|
+
|
80
|
+
* Fixed Rate::Source::Xe; site format changed, more robust parser.
|
81
|
+
* Added Currency::Config.
|
82
|
+
* Support for filtering Float values before casting to Money, based on suggestions for rounding by Steffen Rusitschka.
|
83
|
+
* Fixed :allow_nil in ActiveRecord money macro based on fix by Steffen Rusitschka.
|
84
|
+
* Fixed package scoping issue in Money.
|
85
|
+
* Added support for Formatter#template string
|
86
|
+
* 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.
|
87
|
+
|
88
|
+
== Release 0.4.0: 2007/02/21
|
89
|
+
|
90
|
+
=== MAJOR CHANGES IN THIS RELEASE FOR HISTORICAL RATE DATA
|
91
|
+
|
92
|
+
Some changes are not backwards-compatible
|
93
|
+
|
94
|
+
* ActiveRecord::Base.money macro is deprecated, use ActiveRecord::Base.attr_money macro.
|
95
|
+
* Currency::Exchange is now Currency::Exchange::Rate::Source
|
96
|
+
NOTE: Currency::Exchange::* is reserved for buying/selling currencies, not for providing rate data.
|
97
|
+
* Refactored xe.com homepage rate source as a Currency::Exchange::Rate::Source::Xe.
|
98
|
+
* Refactored Currency::Exchange::Test as Currency::Exchange::Rate::Source::Test.
|
99
|
+
* Support for historical money values and rates using ActiveRecord.
|
100
|
+
* Added Rate::Source::Historical::Writer.
|
101
|
+
* Added newyorkfed.org XML rate source.
|
102
|
+
* Added thefinancials.com XML rate source.
|
103
|
+
* Refactored rate deriviation into Currency::Exchange::Rate::Deriver.
|
104
|
+
* Refactored rate caching into Currency::Exchange::Rate::Source::TimedCache.
|
105
|
+
* Added Money attribute macros for classes not using ActiveRecord.
|
106
|
+
* Refactored time-based rate caching into Currency::Exchange::Rate::Source::TimedCache.
|
107
|
+
* Refactored Currency::Currency#format into Currency::Formatter.
|
108
|
+
NOTE: old formatting options as :no_* no longer supported.
|
109
|
+
* Refactored Currency::Currency#parse into Currency::Parser.
|
110
|
+
* Currency::CurrencyFactory is now Currency::Currency::Factory.
|
111
|
+
* Preliminary Currency::Exchange::Rate::Source::Failover.
|
112
|
+
* Added copyright notices: LICENSE.txt, COPYING.txt.
|
113
|
+
|
114
|
+
== Release 0.3.3: 2006/10/31
|
115
|
+
|
116
|
+
* Inclusion of README.txt and Releases.txt into documentation.
|
117
|
+
|
118
|
+
== Release 0.3.2: 2006/10/31
|
119
|
+
|
120
|
+
* BOO!
|
121
|
+
* Added expiration of rates in Xe.
|
122
|
+
* Fixed Currency.symbol formatting when Currency.symbol.nil?
|
123
|
+
* Added more Money tests.
|
124
|
+
|
125
|
+
== Release 0.3.1: 2006/10/31
|
126
|
+
|
127
|
+
* Remove debug puts.
|
128
|
+
|
129
|
+
== Release 0.3.0: 2006/10/31
|
130
|
+
|
131
|
+
* ActiveRecord money :*_field options are now named :*_column.
|
132
|
+
* More ActiveRecord tests
|
133
|
+
|
134
|
+
== Release 0.2.1: 2006/10/31
|
135
|
+
|
136
|
+
* Fixed Manifest.txt
|
137
|
+
|
138
|
+
== Release 0.2.0: 2006/10/31
|
139
|
+
|
140
|
+
* Restructured namespace
|
141
|
+
* Added more documentation
|
142
|
+
* Added ActiveRecord tests
|
143
|
+
|
144
|
+
== Release 0.1.2: 2006/10/30
|
145
|
+
|
146
|
+
* Rakefile now uses Hoe
|
147
|
+
|
148
|
+
== Release 0.1.1: 2006/10/30
|
149
|
+
|
150
|
+
* Fixes gem packaging errors.
|
151
|
+
|
152
|
+
== Release 0.1.0: 2006/10/29
|
153
|
+
|
154
|
+
* Initial Release
|
155
|
+
|
data/TODO.txt
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
|
2
|
+
= Currency To Do List
|
3
|
+
|
4
|
+
* Clean up and normalize all exceptions:
|
5
|
+
** Rate sources should add :source => source, etc.
|
6
|
+
* Refactor all configuration class variables into Currency::Config
|
7
|
+
* Refactor all cached values into objects that can be reinstantiated on a per-thread basis
|
8
|
+
* Support http://www.xe.com/ucc/full.php rate queries.
|
9
|
+
|
data/currency.gemspec
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = %q{currency}
|
3
|
+
s.version = "0.5.0"
|
4
|
+
|
5
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
6
|
+
s.authors = ["Asa Wilson"]
|
7
|
+
s.date = %q{2008-11-14}
|
8
|
+
s.description = %q{Currency conversions for Ruby}
|
9
|
+
s.email = ["acvwilson@gmail.com"]
|
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_base_spec.rb", "spec/ar_column_spec.rb", "spec/ar_core_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
|
+
s.has_rdoc = true
|
13
|
+
s.homepage = %q{http://currency.rubyforge.org/}
|
14
|
+
s.rdoc_options = ["--main", "README.txt"]
|
15
|
+
s.require_paths = ["lib"]
|
16
|
+
s.rubygems_version = %q{1.2.0}
|
17
|
+
s.summary = %q{currency 0.5.0}
|
18
|
+
end
|
data/examples/ex1.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
|
3
|
+
require 'currency'
|
4
|
+
require 'currency/exchange/rate/source/test'
|
5
|
+
|
6
|
+
x = Currency.Money("1,203.43", :USD)
|
7
|
+
|
8
|
+
puts x.to_s
|
9
|
+
puts (x * 10).to_s
|
10
|
+
puts (x * 33333).inspect
|
11
|
+
|
12
|
+
puts x.currency.code.inspect
|
13
|
+
|
data/examples/xe1.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
|
3
|
+
require 'currency'
|
4
|
+
require 'currency/exchange/rate/source/xe'
|
5
|
+
|
6
|
+
ex = Currency::Exchange::Rate::Source::Xe.new()
|
7
|
+
Currency::Exchange::Rate::Source.current = ex
|
8
|
+
|
9
|
+
puts ex.inspect
|
10
|
+
puts ex.parse_page_rates.inspect
|
11
|
+
|
12
|
+
usd = Currency.Money("1", 'USD')
|
13
|
+
|
14
|
+
puts "usd = #{usd}"
|
15
|
+
|
16
|
+
cad = usd.convert(:CAD)
|
17
|
+
puts "cad = #{cad}"
|
18
|
+
|
19
|
+
|
20
|
+
|
data/lib/currency.rb
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
# Copyright (C) 2006-2007 Kurt Stephens <ruby-currency(at)umleta.com>
|
2
|
+
#
|
3
|
+
# See LICENSE.txt for details.
|
4
|
+
#
|
5
|
+
# = Currency
|
6
|
+
#
|
7
|
+
# The Currency package provides an object-oriented model of:
|
8
|
+
#
|
9
|
+
# * currencies
|
10
|
+
# * exchanges
|
11
|
+
# * exchange rates
|
12
|
+
# * exchange rate sources
|
13
|
+
# * monetary values
|
14
|
+
#
|
15
|
+
# The core classes are:
|
16
|
+
#
|
17
|
+
# * Currency::Money - uses a scaled integer representation of a monetary value and performs accurate conversions to and from string values.
|
18
|
+
# * Currency::Currency - provides an object-oriented representation of a currency.
|
19
|
+
# * Currency::Exchange::Base - the base class for a currency exchange rate provider.
|
20
|
+
# * Currency::Exchange::Rate::Source::Base - the base class for an on-demand currency exchange rate data provider.
|
21
|
+
# * Currency::Exchange::Rate::Source::Provider - the base class for a bulk exchange rate data provider.
|
22
|
+
# * Currency::Exchange::Rate - represents a exchange rate between two currencies.
|
23
|
+
#
|
24
|
+
#
|
25
|
+
# The example below uses Currency::Exchange::Xe to automatically get
|
26
|
+
# exchange rates from http://xe.com/ :
|
27
|
+
#
|
28
|
+
# require 'currency'
|
29
|
+
# require 'currency/exchange/rate/deriver'
|
30
|
+
# require 'currency/exchange/rate/source/xe'
|
31
|
+
# require 'currency/exchange/rate/source/timed_cache'
|
32
|
+
#
|
33
|
+
# # Rate source initialization
|
34
|
+
# provider = Currency::Exchange::Rate::Source::Xe.new
|
35
|
+
# deriver = Currency::Exchange::Rate::Deriver.new(:source => provider)
|
36
|
+
# cache = Currency::Exchange::Rate::Source::TimedCache.new(:source => deriver)
|
37
|
+
# Currency::Exchange::Rate::Source.default = cache
|
38
|
+
#
|
39
|
+
# usd = Currency::Money('6.78', :USD)
|
40
|
+
# puts "usd = #{usd.format}"
|
41
|
+
# cad = usd.convert(:CAD)
|
42
|
+
# puts "cad = #{cad.format}"
|
43
|
+
#
|
44
|
+
# == ActiveRecord Suppport
|
45
|
+
#
|
46
|
+
# This package also contains ActiveRecord support for money values:
|
47
|
+
#
|
48
|
+
# require 'currency'
|
49
|
+
# require 'currency/active_record'
|
50
|
+
#
|
51
|
+
# class Entry < ActiveRecord::Base
|
52
|
+
# money :amount
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# In the example above, the entries.amount database column is an INTEGER that represents US cents.
|
56
|
+
# The currency code of the money value can be stored in an additional database column or a default currency can be used.
|
57
|
+
#
|
58
|
+
# == Recent Enhancements
|
59
|
+
#
|
60
|
+
# === Storage and retrival of historical exchange rates
|
61
|
+
#
|
62
|
+
# * See Currency::Exchange::Rate::Source::Historical
|
63
|
+
# * See Currency::Exchange::Rate::Source::Historical::Writer
|
64
|
+
#
|
65
|
+
# === Automatic derivation of rates from base rates.
|
66
|
+
#
|
67
|
+
# * See Currency::Exchange::Rate::Deriver
|
68
|
+
#
|
69
|
+
# === Rate caching
|
70
|
+
#
|
71
|
+
# * See Currency::Exchange::Rate::Source::TimedCache
|
72
|
+
#
|
73
|
+
# === Rate Providers
|
74
|
+
#
|
75
|
+
# * See Currency::Exchange::Rate::Source::Xe
|
76
|
+
# * See Currency::Exchange::Rate::Source::NewYorkFed
|
77
|
+
# * See Currency::Exchange::Rate::Source::TheFinancials
|
78
|
+
#
|
79
|
+
# === Customizable formatting and parsing
|
80
|
+
#
|
81
|
+
# * See Currency::Formatter
|
82
|
+
# * See Currency::Parser
|
83
|
+
#
|
84
|
+
# == Future Enhancements
|
85
|
+
#
|
86
|
+
# * Support for inflationary rates within a currency, e.g. $10 USD in the year 1955 converted to 2006 USD.
|
87
|
+
#
|
88
|
+
# == SVN Repo
|
89
|
+
#
|
90
|
+
# svn checkout svn://rubyforge.org/var/svn/currency/currency/trunk
|
91
|
+
#
|
92
|
+
# == Examples
|
93
|
+
#
|
94
|
+
# See the examples/ and test/ directorys
|
95
|
+
#
|
96
|
+
# == Author
|
97
|
+
#
|
98
|
+
# Kurt Stephens http://kurtstephens.com
|
99
|
+
#
|
100
|
+
# == Support
|
101
|
+
#
|
102
|
+
# http://rubyforge.org/forum/forum.php?forum_id=7643
|
103
|
+
#
|
104
|
+
# == Copyright
|
105
|
+
#
|
106
|
+
# Copyright (C) 2006-2007 Kurt Stephens <ruby-currency(at)umleta.com>
|
107
|
+
#
|
108
|
+
# See LICENSE.txt for details.
|
109
|
+
#
|
110
|
+
module Currency
|
111
|
+
# Use this function instead of Money#new:
|
112
|
+
#
|
113
|
+
# Currency::Money("12.34", :CAD)
|
114
|
+
#
|
115
|
+
# Do not do this:
|
116
|
+
#
|
117
|
+
# Currency::Money.new("12.34", :CAD)
|
118
|
+
#
|
119
|
+
# See Money#new.
|
120
|
+
def self.Money(*opts)
|
121
|
+
Money.new(*opts)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
$:.unshift(File.expand_path(File.dirname(__FILE__))) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
126
|
+
|
127
|
+
require 'currency/currency_version'
|
128
|
+
require 'currency/config'
|
129
|
+
require 'currency/exception'
|
130
|
+
require 'currency/money'
|
131
|
+
require 'currency/currency'
|
132
|
+
require 'currency/currency/factory'
|
133
|
+
require 'currency/money'
|
134
|
+
require 'currency/formatter'
|
135
|
+
require 'currency/parser'
|
136
|
+
require 'currency/exchange'
|
137
|
+
require 'currency/exchange/rate'
|
138
|
+
require 'currency/exchange/rate/deriver'
|
139
|
+
require 'currency/exchange/rate/source'
|
140
|
+
require 'currency/exchange/rate/source/test'
|
141
|
+
require 'currency/exchange/time_quantitizer'
|
142
|
+
require 'currency/core_extensions'
|
143
|
+
require 'active_support'
|
@@ -0,0 +1,265 @@
|
|
1
|
+
# Copyright (C) 2006-2007 Kurt Stephens <ruby-currency(at)umleta.com>
|
2
|
+
# See LICENSE.txt for details.
|
3
|
+
|
4
|
+
require 'active_record/base'
|
5
|
+
require File.join(File.dirname(__FILE__), '..', 'currency')
|
6
|
+
|
7
|
+
# See Currency::ActiveRecord::ClassMethods
|
8
|
+
class ActiveRecord::Base
|
9
|
+
@@money_attributes = { }
|
10
|
+
|
11
|
+
# Called by money macro when a money attribute
|
12
|
+
# is created.
|
13
|
+
def self.register_money_attribute(attr_opts)
|
14
|
+
(@@money_attributes[attr_opts[:class]] ||= { })[attr_opts[:attr_name]] = attr_opts
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns an array of option hashes for all the money attributes of
|
18
|
+
# this class.
|
19
|
+
#
|
20
|
+
# Superclass attributes are not included.
|
21
|
+
def self.money_attributes_for_class(cls)
|
22
|
+
(@@money_atttributes[cls] || { }).values
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
# Iterates through all known money attributes in all classes.
|
27
|
+
#
|
28
|
+
# each_money_attribute { | money_opts |
|
29
|
+
# ...
|
30
|
+
# }
|
31
|
+
def self.each_money_attribute(&blk)
|
32
|
+
@@money_attributes.each do | cls, hash |
|
33
|
+
hash.each do | attr_name, attr_opts |
|
34
|
+
yield attr_opts
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end # class
|
40
|
+
|
41
|
+
|
42
|
+
# See Currency::ActiveRecord::ClassMethods
|
43
|
+
module Currency::ActiveRecord
|
44
|
+
|
45
|
+
def self.append_features(base) # :nodoc:
|
46
|
+
# $stderr.puts " Currency::ActiveRecord#append_features(#{base})"
|
47
|
+
super
|
48
|
+
base.extend(ClassMethods)
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
# == ActiveRecord Suppport
|
54
|
+
#
|
55
|
+
# Support for Money attributes in ActiveRecord::Base subclasses:
|
56
|
+
#
|
57
|
+
# require 'currency'
|
58
|
+
# require 'currency/active_record'
|
59
|
+
#
|
60
|
+
# class Entry < ActiveRecord::Base
|
61
|
+
# attr_money :amount
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
module ClassMethods
|
65
|
+
|
66
|
+
# Deprecated: use attr_money.
|
67
|
+
def money(*args)
|
68
|
+
$stderr.puts "WARNING: money(#{args.inspect}) deprecated, use attr_money: in #{caller(1)[0]}"
|
69
|
+
attr_money(*args)
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
# Defines a Money object attribute that is bound
|
74
|
+
# to a database column. The database column to store the
|
75
|
+
# Money value representation is assumed to be
|
76
|
+
# INTEGER and will store Money#rep values.
|
77
|
+
#
|
78
|
+
# Options:
|
79
|
+
#
|
80
|
+
# :column => undef
|
81
|
+
#
|
82
|
+
# Defines the column to use for storing the money value.
|
83
|
+
# Defaults to the attribute name.
|
84
|
+
#
|
85
|
+
# If this column is different from the attribute name,
|
86
|
+
# the money object will intercept column=(x) to flush
|
87
|
+
# any cached Money object.
|
88
|
+
#
|
89
|
+
# :currency => currency_code (e.g.: :USD)
|
90
|
+
#
|
91
|
+
# Defines the Currency to use for storing a normalized Money
|
92
|
+
# value.
|
93
|
+
#
|
94
|
+
# All Money values will be converted to this Currency before
|
95
|
+
# storing. This allows SQL summary operations,
|
96
|
+
# like SUM(), MAX(), AVG(), etc., to produce meaningful results,
|
97
|
+
# regardless of the initial currency specified. If this
|
98
|
+
# option is used, subsequent reads will be in the specified
|
99
|
+
# normalization :currency.
|
100
|
+
#
|
101
|
+
# :currency_column => undef
|
102
|
+
#
|
103
|
+
# Defines the name of the CHAR(3) column used to store and
|
104
|
+
# retrieve the Money's Currency code. If this option is used, each
|
105
|
+
# record may use a different Currency to store the result, such
|
106
|
+
# that SQL summary operations, like SUM(), MAX(), AVG(),
|
107
|
+
# may return meaningless results.
|
108
|
+
#
|
109
|
+
# :currency_preferred_column => undef
|
110
|
+
#
|
111
|
+
# Defines the name of a CHAR(3) column used to store and
|
112
|
+
# retrieve the Money's Currency code. This option can be used
|
113
|
+
# with normalized Money values to retrieve the Money value
|
114
|
+
# in its original Currency, while
|
115
|
+
# allowing SQL summary operations on the normalized Money values
|
116
|
+
# to still be valid.
|
117
|
+
#
|
118
|
+
# :time => undef
|
119
|
+
#
|
120
|
+
# Defines the name of attribute used to
|
121
|
+
# retrieve the Money's time. If this option is used, each
|
122
|
+
# Money value will use this attribute during historical Currency
|
123
|
+
# conversions.
|
124
|
+
#
|
125
|
+
# Money values can share a time value with other attributes
|
126
|
+
# (e.g. a created_on column).
|
127
|
+
#
|
128
|
+
# If this option is true, the money time attribute will be named
|
129
|
+
# "#{attr_name}_time" and :time_update will be true.
|
130
|
+
#
|
131
|
+
# :time_update => undef
|
132
|
+
#
|
133
|
+
# If true, the Money time value is updated upon setting the
|
134
|
+
# money attribute.
|
135
|
+
#
|
136
|
+
def attr_money(attr_name, *opts)
|
137
|
+
opts = Hash[*opts]
|
138
|
+
|
139
|
+
attr_name = attr_name.to_s
|
140
|
+
opts[:class] = self
|
141
|
+
opts[:table] = self.table_name
|
142
|
+
opts[:attr_name] = attr_name.intern
|
143
|
+
::ActiveRecord::Base.register_money_attribute(opts)
|
144
|
+
|
145
|
+
column = opts[:column] || opts[:attr_name]
|
146
|
+
opts[:column] = column
|
147
|
+
|
148
|
+
if column.to_s != attr_name.to_s
|
149
|
+
alias_accessor = <<-"end_eval"
|
150
|
+
alias :before_money_#{column}=, :#{column}=
|
151
|
+
|
152
|
+
def #{column}=(__value)
|
153
|
+
@{attr_name} = nil # uncache
|
154
|
+
before_money#{column} = __value
|
155
|
+
end
|
156
|
+
|
157
|
+
end_eval
|
158
|
+
end
|
159
|
+
|
160
|
+
currency = opts[:currency]
|
161
|
+
|
162
|
+
currency_column = opts[:currency_column]
|
163
|
+
if currency_column && ! currency_column.kind_of?(String)
|
164
|
+
currency_column = currency_column.to_s
|
165
|
+
currency_column = "#{column}_currency"
|
166
|
+
end
|
167
|
+
if currency_column
|
168
|
+
read_currency = "read_attribute(:#{currency_column.to_s})"
|
169
|
+
write_currency = "write_attribute(:#{currency_column}, #{attr_name}_money.nil? ? nil : #{attr_name}_money.currency.code.to_s)"
|
170
|
+
end
|
171
|
+
opts[:currency_column] = currency_column
|
172
|
+
|
173
|
+
currency_preferred_column = opts[:currency_preferred_column]
|
174
|
+
if currency_preferred_column
|
175
|
+
currency_preferred_column = currency_preferred_column.to_s
|
176
|
+
read_preferred_currency = "@#{attr_name} = @#{attr_name}.convert(read_attribute(:#{currency_preferred_column}))"
|
177
|
+
write_preferred_currency = "write_attribute(:#{currency_preferred_column}, @#{attr_name}_money.currency.code)"
|
178
|
+
end
|
179
|
+
|
180
|
+
time = opts[:time]
|
181
|
+
write_time = ''
|
182
|
+
if time
|
183
|
+
if time == true
|
184
|
+
time = "#{attr_name}_time"
|
185
|
+
opts[:time_update] = true
|
186
|
+
end
|
187
|
+
read_time = "self.#{time}"
|
188
|
+
end
|
189
|
+
opts[:time] = time
|
190
|
+
if opts[:time_update]
|
191
|
+
write_time = "self.#{time} = #{attr_name}_money && #{attr_name}_money.time"
|
192
|
+
end
|
193
|
+
|
194
|
+
currency ||= ':USD'
|
195
|
+
time ||= 'nil'
|
196
|
+
|
197
|
+
read_currency ||= currency
|
198
|
+
read_time ||= time
|
199
|
+
|
200
|
+
money_rep ||= "#{attr_name}_money.rep"
|
201
|
+
|
202
|
+
validate_allow_nil = opts[:allow_nil] ? ', :allow_nil => true' : ''
|
203
|
+
validate = "# Validation\n"
|
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
|
206
|
+
|
207
|
+
|
208
|
+
alias_accessor ||= ''
|
209
|
+
|
210
|
+
module_eval (opts[:module_eval] = x = <<-"end_eval"), __FILE__, __LINE__
|
211
|
+
#{validate}
|
212
|
+
|
213
|
+
#{alias_accessor}
|
214
|
+
|
215
|
+
def #{attr_name}
|
216
|
+
# $stderr.puts " \#{self.class.name}##{attr_name}"
|
217
|
+
unless @#{attr_name}
|
218
|
+
#{attr_name}_rep = read_attribute(:#{column})
|
219
|
+
unless #{attr_name}_rep.nil?
|
220
|
+
@#{attr_name} = ::Currency::Money.new_rep(#{attr_name}_rep, #{read_currency} || #{currency}, #{read_time} || #{time})
|
221
|
+
#{read_preferred_currency}
|
222
|
+
end
|
223
|
+
end
|
224
|
+
@#{attr_name}
|
225
|
+
end
|
226
|
+
|
227
|
+
def #{attr_name}=(value)
|
228
|
+
if value.nil?
|
229
|
+
#{attr_name}_money = nil
|
230
|
+
elsif value.kind_of?(Integer) || value.kind_of?(String) || value.kind_of?(Float)
|
231
|
+
#{attr_name}_money = ::Currency::Money(value, #{currency})
|
232
|
+
#{write_preferred_currency}
|
233
|
+
elsif value.kind_of?(::Currency::Money)
|
234
|
+
#{attr_name}_money = value
|
235
|
+
#{write_preferred_currency}
|
236
|
+
#{write_currency ? write_currency : "#{attr_name}_money = #{attr_name}_money.convert(#{currency})"}
|
237
|
+
else
|
238
|
+
raise ::Currency::Exception::InvalidMoneyValue, value
|
239
|
+
end
|
240
|
+
|
241
|
+
@#{attr_name} = #{attr_name}_money
|
242
|
+
|
243
|
+
write_attribute(:#{column}, #{attr_name}_money.nil? ? nil : #{money_rep})
|
244
|
+
#{write_time}
|
245
|
+
|
246
|
+
value
|
247
|
+
end
|
248
|
+
|
249
|
+
def #{attr_name}_before_type_cast
|
250
|
+
# FIXME: User cannot specify Currency
|
251
|
+
x = #{attr_name}
|
252
|
+
x &&= x.format(:symbol => false, :currency => false, :thousands => false)
|
253
|
+
x
|
254
|
+
end
|
255
|
+
|
256
|
+
end_eval
|
257
|
+
# $stderr.puts " CODE = #{x}"
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
|
263
|
+
ActiveRecord::Base.class_eval do
|
264
|
+
include Currency::ActiveRecord
|
265
|
+
end
|