acvwilson-currency 0.6.4 → 0.7

Sign up to get free protection for your applications and to get access to all the features.
data/currency.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = %q{currency}
3
- s.version = "0.6.4"
3
+ s.version = "0.7"
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", "David Palm"]
@@ -145,27 +145,29 @@ module Currency::ActiveRecord
145
145
  column = opts[:column] || opts[:attr_name]
146
146
  opts[:column] = column
147
147
 
148
+ # TODO: rewrite with define_method (dvd, 15-03-2009)
148
149
  if column.to_s != attr_name.to_s
149
150
  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
151
+ alias :before_money_#{column}=, :#{column}=
156
152
 
153
+ def #{column}=(__value)
154
+ @{attr_name} = nil # uncache
155
+ before_money#{column} = __value
156
+ end
157
157
  end_eval
158
- end
159
158
 
159
+ end
160
+ alias_accessor ||= ''
161
+
160
162
  currency = opts[:currency]
161
163
 
162
164
  currency_column = opts[:currency_column]
163
165
  if currency_column && ! currency_column.kind_of?(String)
164
- currency_column = currency_column.to_s
165
166
  currency_column = "#{column}_currency"
166
167
  end
168
+
167
169
  if currency_column
168
- read_currency = "read_attribute(:#{currency_column.to_s})"
170
+ read_currency = "read_attribute(:#{currency_column})"
169
171
  write_currency = "write_attribute(:#{currency_column}, #{attr_name}_money.nil? ? nil : #{attr_name}_money.currency.code.to_s)"
170
172
  end
171
173
  opts[:currency_column] = currency_column
@@ -187,6 +189,7 @@ end_eval
187
189
  read_time = "self.#{time}"
188
190
  end
189
191
  opts[:time] = time
192
+
190
193
  if opts[:time_update]
191
194
  write_time = "self.#{time} = #{attr_name}_money && #{attr_name}_money.time"
192
195
  end
@@ -201,63 +204,66 @@ end_eval
201
204
 
202
205
  validate_allow_nil = opts[:allow_nil] ? ', :allow_nil => true' : ''
203
206
  validate = "# Validation\n"
204
- validate << "\nvalidates_numericality_of :#{attr_name}#{validate_allow_nil}\n"
207
+ validate << "\nvalidates_numericality_of :#{attr_name} #{validate_allow_nil}\n"
205
208
  validate << "\nvalidates_format_of :#{currency_column}, :with => /^[A-Z][A-Z][A-Z]$/#{validate_allow_nil}\n" if currency_column
206
- # validate << "\nbefore_validation :debug_#{attr_name}_before_validate\n"
207
- #
208
- # validate << %Q{
209
- # def debug_#{attr_name}_before_validate
210
- # logger.debug "\tValidating #{attr_name}. Allow nils? #{validate_allow_nil}"
211
- # logger.debug "\t\t'#{attr_name}': '\#\{#{attr_name}.inspect\}' (class: '\#\{#{attr_name}.class\}')"
212
- # logger.debug "\t\tcurrency column, '#{currency_column}': '\#\{#{currency_column}.inspect\}' (class: '\#\{#{currency_column}.class\}'), matches '/^[A-Z][A-Z][A-Z]$/': \#\{'#{currency_column}'.match(/^[A-Z][A-Z][A-Z]$/).to_a.inspect\}"
213
- # end
214
- # }
215
-
216
- alias_accessor ||= ''
217
-
218
- module_eval (opts[:module_eval] = x = <<-"end_eval"), __FILE__, __LINE__
219
- #{validate}
220
-
221
- #{alias_accessor}
222
-
223
- def #{attr_name}
224
- # $stderr.puts " \#{self.class.name}##{attr_name}"
225
- unless @#{attr_name}
226
- #{attr_name}_rep = read_attribute(:#{column})
227
- unless #{attr_name}_rep.nil?
228
- @#{attr_name} = ::Currency::Money.new_rep(#{attr_name}_rep, #{read_currency} || #{currency}, #{read_time} || #{time})
229
- #{read_preferred_currency}
230
- end
231
- end
232
- @#{attr_name}
233
- end
234
-
235
- def #{attr_name}=(value)
236
- if value.nil? || value.to_s.strip == ''
237
- #{attr_name}_money = nil
238
- elsif value.kind_of?(Integer) || value.kind_of?(String) || value.kind_of?(Float)
239
- #{attr_name}_money = ::Currency::Money(value, #{currency})
240
- #{write_preferred_currency}
241
- elsif value.kind_of?(::Currency::Money)
242
- #{attr_name}_money = value
243
- #{write_preferred_currency}
244
- #{write_currency ? write_currency : "#{attr_name}_money = #{attr_name}_money.convert(#{currency})"}
245
- else
246
- raise ::Currency::Exception::InvalidMoneyValue, value
247
- end
248
-
249
- @#{attr_name} = #{attr_name}_money # TODO: Really needed? Isn't the write_attribute enough?
209
+
210
+ # =================================================================================================
211
+ # = Define the currency_column setter, so that the Money object changes when the currency changes =
212
+ # =================================================================================================
213
+ if currency_column
214
+ currency_column_setter = %Q{
215
+ def #{currency_column}=(currency_code)
216
+ @#{attr_name} = nil
217
+ write_attribute(:#{currency_column}, currency_code)
218
+ end
219
+ }
220
+ class_eval currency_column_setter, __FILE__, __LINE__
221
+ end
222
+
223
+ class_eval (opts[:module_eval] = x = <<-"end_eval"), __FILE__, __LINE__
224
+ #{validate}
225
+
226
+ #{alias_accessor}
227
+
228
+ # Getter
229
+ def #{attr_name}
230
+ unless @#{attr_name}
231
+ rep = read_attribute(:#{column})
232
+ unless rep.nil?
233
+ @#{attr_name} = ::Currency::Money.new_rep(rep, #{read_currency} || #{currency}, #{read_time} || #{time})
234
+ #{read_preferred_currency}
235
+ end
236
+ end
237
+ @#{attr_name}
238
+ end
239
+
240
+ # Setter
241
+ def #{attr_name}=(value)
242
+ if value.nil? || value.to_s.strip == ''
243
+ #{attr_name}_money = nil
244
+ elsif value.kind_of?(Integer) || value.kind_of?(String) || value.kind_of?(Float)
245
+ #{attr_name}_money = ::Currency::Money(value, #{read_currency})
246
+ #{write_preferred_currency}
247
+ elsif value.kind_of?(::Currency::Money)
248
+ #{attr_name}_money = value
249
+ #{write_preferred_currency}
250
+ #{write_currency ? write_currency : "#{attr_name}_money = #{attr_name}_money.convert(#{currency})"}
251
+ else
252
+ raise ::Currency::Exception::InvalidMoneyValue, value
253
+ end
254
+
255
+ @#{attr_name} = #{attr_name}_money # TODO: Really needed? Isn't the write_attribute enough? (answer: no, because the getter method does an "if @#{attr_name}" to check if it's set)
250
256
 
251
- write_attribute(:#{column}, #{attr_name}_money.nil? ? nil : #{money_rep})
252
- #{write_time}
257
+ write_attribute(:#{column}, #{attr_name}_money.nil? ? nil : #{attr_name}_money.rep)
258
+ #{write_time}
253
259
 
254
- value
255
- end
256
-
257
- def #{attr_name}_before_type_cast
258
- #{attr_name}.to_f if #{attr_name}
259
- end
260
+ value
261
+ end
260
262
 
263
+ def #{attr_name}_before_type_cast
264
+ #{attr_name}.to_f if #{attr_name}
265
+ end
266
+
261
267
  end_eval
262
268
  =begin
263
269
  Replaced the _before_type_cast because it's buggy and weird:
data/lib/currency.rb CHANGED
@@ -130,7 +130,7 @@ require 'currency/exception'
130
130
  require 'currency/money'
131
131
  require 'currency/currency'
132
132
  require 'currency/currency/factory'
133
- require 'currency/money'
133
+ require 'currency/money' # TODO: Why require this twice? (dvd, 15-03-2009)
134
134
  require 'currency/parser'
135
135
  require 'currency/formatter' # require this one before the parser and enjoy the weird bugs!
136
136
  require 'currency/exchange'
@@ -1,23 +1,80 @@
1
1
  # Copyright (C) 2006-2007 Kurt Stephens <ruby-currency(at)umleta.com>
2
2
  # Copyright (C) 2008 Asa Wilson <acvwilson(at)gmail.com>
3
+ # Copyright (C) 2009 David Palm <dvdplm(at)gmail.com>
3
4
  # See LICENSE.txt for details.
4
5
 
5
6
  require File.dirname(__FILE__) + '/ar_spec_helper'
6
7
 
7
- describe Currency::ActiveRecord do
8
- it "simple" do
9
- # TODO: move insert_records into a before block?
10
- insert_records
8
+ class Dog < ActiveRecord::Base
9
+ attr_money :price, :currency_column => true, :allow_nil => true
10
+ end
11
11
 
12
- usd = @currency_test.find(@usd.id)
13
- usd.should_not be_nil
14
- assert_equal_currency usd, @usd
12
+ describe "extending ActiveRecord" do
13
+ describe "attr_money" do
14
+ before do
15
+ Dog.connection.execute("INSERT INTO dogs VALUES(null, 'fido', 1500, 'USD')") # NOTE: by-passing AR here to achieve clean slate (dvd, 15-03-2009)
16
+ @dog = Dog.first
17
+ end
15
18
 
16
- cad = @currency_test.find(@cad.id)
17
- cad.should_not == nil
18
- assert_equal_money cad, @cad
19
+ describe "retrieving money values" do
20
+ it "sets up the Money object at first read" do
21
+ pending
22
+ end
23
+
24
+ it "returns the ivar on subsequent reads" do
25
+ pending
26
+ end
27
+
28
+ it "does not setup a Money object if the db column does not contain an integer to use for money rep" do
29
+ pending
30
+ end
31
+
32
+ it "casts the currency to the preferred one, if a preferred currency was set" do
33
+ pending
34
+ end
35
+ end
36
+
37
+ describe "currency column" do
38
+ before do
39
+ Dog.connection.execute("INSERT INTO dogs VALUES(null, 'fido', 1500, 'USD')") # NOTE: by-passing AR here to achieve clean slate (dvd, 15-03-2009)
40
+ @dog = Dog.first
41
+ end
19
42
 
20
- cad.amount.currency.code.should == :USD
21
- end
22
- end
43
+ it "changes the currency when the value on the currency column changes" do
44
+ @dog.price.currency.code.should == :USD
45
+ @dog.update_attributes(:price_currency => 'EUR')
46
+ @dog.price.currency.code.should == :EUR
47
+ end
48
+
49
+ it "does NOT convert to the new currency when the currency column changes" do
50
+ @dog.price.rep.should == 1500
51
+ @dog.update_attributes(:price_currency => :EUR)
52
+ @dog.price.rep.should == 1500
53
+ end
54
+ end
55
+
56
+ describe "saving" do
57
+ it "saves the price with the default currency when set to 10.money" do
58
+ @dog.price = 10.money
59
+ @dog.price.should == Currency::Money("10")
60
+ end
61
+
62
+ it "saves the price with the currency of the Money object" do
63
+ @dog.price = 10.money(:EUR)
64
+ @dog.price.should == Currency::Money("10", "EUR")
65
+ end
66
+
67
+ it "can change just the currency" do
68
+ @dog.price_currency = 'CAD'
69
+ @dog.save
70
+ @dog.price.should == Currency::Money("15", "CAD")
71
+ end
72
+
73
+ it "can save changes using update_attributes" do
74
+ @dog.update_attributes(:price => 5, :price_currency => 'CAD')
75
+ @dog.price.should == 5.money('CAD')
76
+ end
77
+ end
23
78
 
79
+ end
80
+ end
@@ -8,6 +8,42 @@ require 'active_record'
8
8
  require 'active_record/migration'
9
9
  require File.dirname(__FILE__) + '/../lib/currency/active_record'
10
10
 
11
+ config = YAML::load(IO.read(File.dirname(__FILE__) + '/db/database.yml'))
12
+ ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
13
+ # ActiveRecord::Base.establish_connection(config['mysql_debug'])
14
+ ActiveRecord::Base.establish_connection(config['sqlite3mem'])
15
+
16
+ ActiveRecord::Migration.verbose = false
17
+ load(File.dirname(__FILE__) + "/db/schema.rb")
18
+
19
+ # ============================================
20
+ # = Load some currency symbols (171 records) =
21
+ # ============================================
22
+ currency_codes = IO.read(File.dirname(__FILE__) + '/db/currency_codes.sql')
23
+ currency_codes.each_line do |sql_insert|
24
+ ActiveRecord::Base.connection.execute(sql_insert)
25
+ end
26
+
27
+ # ================================
28
+ # = Load some rates (84 records) =
29
+ # ================================
30
+ rates = IO.read(File.dirname(__FILE__) + '/db/currency_historical_rates.sql')
31
+ rates.each_line do |sql_insert|
32
+ ActiveRecord::Base.connection.execute(sql_insert)
33
+ end
34
+
35
+ AR_M = ActiveRecord::Migration
36
+ AR_B = ActiveRecord::Base
37
+
38
+
39
+
40
+ =begin
41
+ require File.dirname(__FILE__) + '/spec_helper'
42
+
43
+ require 'active_record'
44
+ require 'active_record/migration'
45
+ require File.dirname(__FILE__) + '/../lib/currency/active_record'
46
+
11
47
  AR_M = ActiveRecord::Migration
12
48
  AR_B = ActiveRecord::Base
13
49
 
@@ -124,4 +160,5 @@ def assert_equal_currency(a,b)
124
160
  b.amount.currency.should == a.amount.currency
125
161
  b.amount.currency.code.should == a.amount.currency.code
126
162
 
127
- end
163
+ end
164
+ =end
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.6.4
4
+ version: "0.7"
5
5
  platform: ruby
6
6
  authors:
7
7
  - Asa Wilson
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2009-02-05 06:05:45.477389 -08:00
13
+ date: 2009-03-15 11:25:57.897576 -07:00
14
14
  default_executable:
15
15
  dependencies: []
16
16
 
@@ -1,56 +0,0 @@
1
- require File.dirname(__FILE__) + '/ar_spec_helper'
2
-
3
- ##################################################
4
- # Basic CurrenyTest AR::B class
5
- #
6
-
7
- # TODO: Move elsewhere, combine with other AR tests
8
-
9
- TABLE_NAME = 'currency_column_test'
10
-
11
- class CurrencyColumnTestMigration < AR_M
12
- def self.up
13
- create_table TABLE_NAME.intern do |t|
14
- t.column :name, :string
15
- t.column :amount, :integer # Money
16
- t.column :amount_currency, :string, :size => 3 # Money.currency.code
17
- end
18
- end
19
-
20
- def self.down
21
- drop_table TABLE_NAME.intern
22
- end
23
- end
24
-
25
- class CurrencyColumnTest < AR_B
26
- set_table_name TABLE_NAME
27
- attr_money :amount, :currency_column => true
28
- end
29
-
30
- ##################################################
31
-
32
- describe "ActiveRecord macros" do
33
- before(:all) do
34
- AR_B.establish_connection(database_spec)
35
- @currency_test_migration ||= CurrencyColumnTestMigration
36
- @currency_test ||= CurrencyColumnTest
37
- schema_down
38
- schema_up
39
- end
40
-
41
- after(:all) do
42
- schema_down
43
- end
44
-
45
- it "can store and retrieve money values from a DB and automagically transfomr them to Money" do
46
- insert_records
47
-
48
- usd = @currency_test.find(@usd.id)
49
- usd.should == @usd
50
- usd.object_id.should_not == @usd.object_id # not same object
51
-
52
- cad = @currency_test.find(@cad.id)
53
- cad.should == @cad
54
- cad.object_id.should_not == @cad.object_id # not same object
55
- end
56
- end