acvwilson-currency 0.5.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/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
|