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.
Files changed (57) hide show
  1. data/COPYING.txt +339 -0
  2. data/ChangeLog +8 -0
  3. data/LICENSE.txt +65 -0
  4. data/Manifest.txt +58 -0
  5. data/README.txt +51 -0
  6. data/Releases.txt +155 -0
  7. data/TODO.txt +9 -0
  8. data/currency.gemspec +18 -0
  9. data/examples/ex1.rb +13 -0
  10. data/examples/xe1.rb +20 -0
  11. data/lib/currency.rb +143 -0
  12. data/lib/currency/active_record.rb +265 -0
  13. data/lib/currency/config.rb +91 -0
  14. data/lib/currency/core_extensions.rb +83 -0
  15. data/lib/currency/currency.rb +175 -0
  16. data/lib/currency/currency/factory.rb +121 -0
  17. data/lib/currency/currency_version.rb +6 -0
  18. data/lib/currency/exception.rb +119 -0
  19. data/lib/currency/exchange.rb +48 -0
  20. data/lib/currency/exchange/rate.rb +214 -0
  21. data/lib/currency/exchange/rate/deriver.rb +157 -0
  22. data/lib/currency/exchange/rate/source.rb +89 -0
  23. data/lib/currency/exchange/rate/source/base.rb +166 -0
  24. data/lib/currency/exchange/rate/source/failover.rb +63 -0
  25. data/lib/currency/exchange/rate/source/federal_reserve.rb +160 -0
  26. data/lib/currency/exchange/rate/source/historical.rb +79 -0
  27. data/lib/currency/exchange/rate/source/historical/rate.rb +184 -0
  28. data/lib/currency/exchange/rate/source/historical/rate_loader.rb +186 -0
  29. data/lib/currency/exchange/rate/source/historical/writer.rb +220 -0
  30. data/lib/currency/exchange/rate/source/new_york_fed.rb +127 -0
  31. data/lib/currency/exchange/rate/source/provider.rb +120 -0
  32. data/lib/currency/exchange/rate/source/test.rb +50 -0
  33. data/lib/currency/exchange/rate/source/the_financials.rb +191 -0
  34. data/lib/currency/exchange/rate/source/timed_cache.rb +198 -0
  35. data/lib/currency/exchange/rate/source/xe.rb +165 -0
  36. data/lib/currency/exchange/time_quantitizer.rb +111 -0
  37. data/lib/currency/formatter.rb +310 -0
  38. data/lib/currency/macro.rb +321 -0
  39. data/lib/currency/money.rb +298 -0
  40. data/lib/currency/money_helper.rb +13 -0
  41. data/lib/currency/parser.rb +193 -0
  42. data/spec/ar_column_spec.rb +76 -0
  43. data/spec/ar_core_spec.rb +68 -0
  44. data/spec/ar_simple_spec.rb +23 -0
  45. data/spec/config_spec.rb +29 -0
  46. data/spec/federal_reserve_spec.rb +75 -0
  47. data/spec/formatter_spec.rb +72 -0
  48. data/spec/historical_writer_spec.rb +187 -0
  49. data/spec/macro_spec.rb +109 -0
  50. data/spec/money_spec.rb +355 -0
  51. data/spec/new_york_fed_spec.rb +73 -0
  52. data/spec/parser_spec.rb +105 -0
  53. data/spec/spec_helper.rb +25 -0
  54. data/spec/time_quantitizer_spec.rb +115 -0
  55. data/spec/timed_cache_spec.rb +95 -0
  56. data/spec/xe_spec.rb +50 -0
  57. 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