easy_rails_money 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,12 +3,41 @@ module EasyRailsMoney
3
3
  module Migration
4
4
  module TableDefinition
5
5
  # called for create_table
6
-
6
+
7
+ # Adds a common currency column
8
+ #
9
+ # Usually we create an currency column for each money
10
+ # columns. We can have multiple money columns in the same
11
+ # record, in which case we can have a single currency
12
+ # column. This helper creates that common curremcy column
13
+ #
14
+ # @return is not important and can change
15
+ #
16
+ # @see EasyRailsMoney::ActiveRecord::Migration::SchemaStatements#remove_currency
7
17
  def currency
8
18
  remove_currency_columns
9
19
  column :currency, :string
10
20
  end
11
-
21
+
22
+ # Creates one or two columns to represent a Money object in the named table
23
+ #
24
+ # An integer column for storing Money in its base unit
25
+ # eg. cents for a Dollar denomination and a string for storing
26
+ # its currency name. Can think of it as a persisted or serialized
27
+ # Money object in the database. The integer column is suffixed
28
+ # with '_money' to aid in reflection ie. to find all money
29
+ # columns. Likewise the currency column is suffixed with '_currency'
30
+ # If does not create an individual currency column if a
31
+ # common currency column is defined
32
+ #
33
+ # @param column_names [Array|Symbol|String] List of money columns to add
34
+ # @return is not important and can change
35
+ #
36
+ # @note If we have defined a currency column for a record then only the integer column is defined.
37
+ # @see EasyRailsMoney::ActiveRecord::Migration::SchemaStatements#add_money
38
+ # @see EasyRailsMoney::ActiveRecord::Migration::Table#money
39
+ # @see EasyRailsMoney::ActiveRecord::Migration::TableDefinition#currency
40
+ # @see EasyRailsMoney::ActiveRecord::Migration::SchemaStatements#remove_money
12
41
  def money(*column_names)
13
42
  column_names.each do |name|
14
43
  column "#{name}_money", :integer
@@ -18,6 +47,7 @@ module EasyRailsMoney
18
47
  end
19
48
  end
20
49
 
50
+ protected
21
51
  def remove_currency_columns
22
52
  columns.delete_if { |x| x.name =~ /_currency/ }
23
53
  end
@@ -1,3 +1,3 @@
1
1
  module EasyRailsMoney
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -6,147 +6,214 @@ if defined? ActiveRecord
6
6
 
7
7
  require 'active_record/schema_dumper'
8
8
 
9
- class CreateLoan < ActiveRecord::Migration
10
- def change
11
- suppress_messages do
12
- create_table :loans do |t|
13
- t.string :name
9
+ # migrations used in tests. our factories/fixtures
10
+ # their class names are the same if they are functionally
11
+ # equivalent, but are organized in different modules depending on
12
+ # whether it is implemented using
13
+ # schema_statements, create_table or change_table
14
+ module SchemaStatements
15
+ class CreateLoanAndMoney < ActiveRecord::Migration
16
+ def change
17
+ suppress_messages do
18
+ create_table :loans do |t|
19
+ t.string :name
20
+ end
21
+ add_money :loans, :principal
14
22
  end
15
23
  end
16
24
  end
17
- end
18
25
 
19
- class AddPrincipalToLoan < ActiveRecord::Migration
20
- def change
21
- suppress_messages do
22
- change_table :loans do |t|
23
- t.money :principal
26
+ class CreateLoanWithCurrency < ActiveRecord::Migration
27
+ def change
28
+ suppress_messages do
29
+ create_table :loans do |t|
30
+ t.string :name
31
+ t.currency
32
+ end
33
+ add_money :loans, :principal, :repaid, :npa
24
34
  end
25
35
  end
26
36
  end
27
- end
28
37
 
29
- class CreateLoanWithPrincipal < ActiveRecord::Migration
30
- def change
31
- suppress_messages do
32
- create_table :loans do |t|
33
- t.string :name
38
+ class RemoveMoneyColumnsFromLoan < ActiveRecord::Migration
39
+ def change
40
+ suppress_messages do
41
+ remove_money :loans, :principal, :repaid, :npa
34
42
  end
35
- add_money :loans, :principal
36
43
  end
37
44
  end
38
- end
39
45
 
40
- class RemovePrincipalFromLoan < ActiveRecord::Migration
41
- def change
42
- suppress_messages do
43
- remove_money :loans, :principal
46
+ class RemoveMoneyColumnsExceptPrincipalFromLoan < ActiveRecord::Migration
47
+ def change
48
+ suppress_messages do
49
+ remove_money :loans, :repaid, :npa
50
+ end
44
51
  end
45
52
  end
46
- end
47
53
 
48
- class CreateLoanWithPrincipalUsingTableApi < ActiveRecord::Migration
49
- def change
50
- suppress_messages do
51
- create_table :loans do |t|
52
- t.string :name
53
- t.money :principal
54
+ class RemovePrincipalFromLoan < ActiveRecord::Migration
55
+ def change
56
+ suppress_messages do
57
+ remove_money :loans, :principal
54
58
  end
55
59
  end
56
60
  end
57
- end
58
61
 
59
- class RemovePrincipalFromLoanUsingTableApi < ActiveRecord::Migration
60
- def change
61
- suppress_messages do
62
- change_table :loans do |t|
63
- t.remove_money :principal
62
+ class RemoveCurrencyFromLoan < ActiveRecord::Migration
63
+ def change
64
+ suppress_messages do
65
+ remove_currency :loans
64
66
  end
65
67
  end
66
68
  end
67
- end
69
+ end # module SchemaStatements
68
70
 
69
- class CreateLoanWithMultipleMoneyColumns < ActiveRecord::Migration
70
- def change
71
- suppress_messages do
72
- create_table :loans, force: true do |t|
73
- t.string :name
74
- t.money :principal
75
- t.money :repaid
76
- t.money :npa
71
+ module ChangeTable
72
+ class AddPrincipalToLoan < ActiveRecord::Migration
73
+ def change
74
+ suppress_messages do
75
+ change_table :loans do |t|
76
+ t.money :principal
77
+ end
77
78
  end
78
79
  end
79
80
  end
80
- end
81
81
 
82
- class CreateLoanWithSingleCurrencyColumnGivenLast < ActiveRecord::Migration
83
- def change
84
- suppress_messages do
85
- create_table :loans, force: true do |t|
86
- t.string :name
87
- t.money :principal
88
- t.money :repaid
89
- t.money :npa
90
- t.currency
82
+ class RemoveCurrencyFromLoan < ActiveRecord::Migration
83
+ def change
84
+ suppress_messages do
85
+ change_table :loans, force: true do |t|
86
+ t.remove_currency
87
+ end
91
88
  end
92
89
  end
93
90
  end
94
- end
95
91
 
96
- class CreateLoanWithSingleCurrencyColumnGivenFirst < ActiveRecord::Migration
97
- def change
98
- suppress_messages do
99
- create_table :loans, force: true do |t|
100
- t.string :name
101
- t.currency
102
- t.money :principal
103
- t.money :repaid
104
- t.money :npa
92
+ class RemovePrincipalFromLoan < ActiveRecord::Migration
93
+ def change
94
+ suppress_messages do
95
+ change_table :loans do |t|
96
+ t.remove_money :principal
97
+ end
98
+ end
99
+ end
100
+ end
101
+
102
+ class AddSingleCurrencyToLoan < ActiveRecord::Migration
103
+ def change
104
+ suppress_messages do
105
+ change_table :loans, force: true do |t|
106
+ t.currency
107
+ end
105
108
  end
106
109
  end
107
110
  end
108
- end
109
111
 
110
- class CreateLoanWithSingleCurrencyColumnOrderDoesNotMatter < ActiveRecord::Migration
111
- def change
112
- suppress_messages do
113
- create_table :loans, force: true do |t|
114
- t.string :name
115
- t.money :principal
116
- t.money :repaid
117
- t.currency
118
- t.money :npa
112
+ class RemoveMoneyColumnsFromLoan < ActiveRecord::Migration
113
+ def change
114
+ suppress_messages do
115
+ change_table :loans, force: true do |t|
116
+ t.remove_money :principal, :repaid, :npa
117
+ end
119
118
  end
120
119
  end
121
120
  end
122
- end
123
121
 
124
- class RemoveCurrencyFromLoan < ActiveRecord::Migration
125
- def change
126
- suppress_messages do
127
- change_table :loans, force: true do |t|
128
- t.remove_currency
122
+ class RemoveMoneyColumnsExceptPrincipalFromLoan < ActiveRecord::Migration
123
+ def change
124
+ suppress_messages do
125
+ change_table :loans, force: true do |t|
126
+ t.remove_money :repaid, :npa
127
+ end
129
128
  end
130
129
  end
131
130
  end
132
- end
131
+ end # module ChangeTable
133
132
 
134
- class AddSingleCurrencyToLoan < ActiveRecord::Migration
135
- def change
136
- suppress_messages do
137
- change_table :loans, force: true do |t|
138
- t.currency
133
+ module CreateTableDefinition
134
+ class CreateLoan < ActiveRecord::Migration
135
+ def change
136
+ suppress_messages do
137
+ create_table :loans do |t|
138
+ t.string :name
139
+ end
139
140
  end
140
141
  end
141
142
  end
142
- end
143
+
144
+ class CreateLoanAndMoney < ActiveRecord::Migration
145
+ def change
146
+ suppress_messages do
147
+ create_table :loans do |t|
148
+ t.string :name
149
+ t.money :principal
150
+ end
151
+ end
152
+ end
153
+ end
154
+
155
+ class CreateLoanWithCurrency < ActiveRecord::Migration
156
+ def change
157
+ suppress_messages do
158
+ create_table :loans, force: true do |t|
159
+ t.string :name
160
+ t.money :principal
161
+ t.money :repaid
162
+ t.money :npa
163
+ t.currency
164
+ end
165
+ end
166
+ end
167
+ end
168
+
169
+ class CreateLoanWithoutCurrency < ActiveRecord::Migration
170
+ def change
171
+ suppress_messages do
172
+ create_table :loans, force: true do |t|
173
+ t.string :name
174
+ t.money :principal
175
+ t.money :repaid
176
+ t.money :npa
177
+ end
178
+ end
179
+ end
180
+ end
181
+
182
+ class CreateLoanWithCurrencySpecifiedFirst < ActiveRecord::Migration
183
+ def change
184
+ suppress_messages do
185
+ create_table :loans, force: true do |t|
186
+ t.string :name
187
+ t.currency
188
+ t.money :principal
189
+ t.money :repaid
190
+ t.money :npa
191
+ end
192
+ end
193
+ end
194
+ end
195
+
196
+ class CreateLoanWithCurrencySpecifiedInBetween < ActiveRecord::Migration
197
+ def change
198
+ suppress_messages do
199
+ create_table :loans, force: true do |t|
200
+ t.string :name
201
+ t.money :principal
202
+ t.money :repaid
203
+ t.currency
204
+ t.money :npa
205
+ end
206
+ end
207
+ end
208
+ end
209
+ end # module CreateTableDefinition
143
210
 
144
211
  # class Loan < ActiveRecord::Base
145
212
  # attr_accessible :principal, :name
146
213
  # # money :principal
147
214
  # end
148
215
 
149
- describe "migration" do
216
+ describe "Migrating Money columns" do
150
217
 
151
218
  let(:schema_with_principal) do
152
219
  <<-EOF.strip_spaces
@@ -158,6 +225,16 @@ if defined? ActiveRecord
158
225
  EOF
159
226
  end
160
227
 
228
+ let(:schema_with_principal_and_single_currency_column) do
229
+ <<-EOF.strip_spaces
230
+ create_table "loans", :force => true do |t|
231
+ t.string "name"
232
+ t.integer "principal_money"
233
+ t.string "currency"
234
+ end
235
+ EOF
236
+ end
237
+
161
238
  let(:schema_with_only_name) do
162
239
  <<-EOF.strip_spaces
163
240
  create_table "loans", :force => true do |t|
@@ -192,75 +269,132 @@ EOF
192
269
  EOF
193
270
  end
194
271
 
195
- context "schema_statements" do
196
- before(:each) do
197
- migrate CreateLoanWithPrincipal
198
- end
272
+ context "and testing schema statements", :schema_statements do
273
+ context "which have one currency column for each money column" do
274
+ before(:each) do
275
+ migrate SchemaStatements::CreateLoanAndMoney
276
+ end
199
277
 
200
- describe "add_money" do
201
- it "creates integer column for money and a string column for currency" do
202
- expect(dump_schema).to eq schema_with_principal
278
+ describe "#add_money" do
279
+ it "creates two columns for each money attribute. one to store the lower denomination as an integer and the currency as a string" do
280
+ expect(dump_schema).to eq schema_with_principal
281
+ end
203
282
  end
204
- end
205
283
 
206
- describe "remove_money" do
207
- it "remove integer column for money and a string column for currency" do
208
- expect { migrate RemovePrincipalFromLoan }.to change { dump_schema }.from(schema_with_principal).to(schema_with_only_name)
284
+ describe "#remove_money" do
285
+ it "drops two columns for each money attribute. one which stored the lower denomination as an integer and the currency as a string" do
286
+ expect { migrate SchemaStatements::RemovePrincipalFromLoan }.to change { dump_schema }.from(schema_with_principal).to(schema_with_only_name)
287
+ end
209
288
  end
210
289
  end
211
- end
212
290
 
213
- context "table_statements" do
214
- before(:each) do
215
- migrate CreateLoanWithPrincipalUsingTableApi
216
- end
217
-
218
- describe "add_money" do
219
- it "creates integer column for money and a string column for currency" do
220
- expect(dump_schema).to eq schema_with_principal
291
+ context "which has a single currency", :single_currency do
292
+ before(:each) do
293
+ migrate SchemaStatements::CreateLoanWithCurrency
221
294
  end
222
- end
223
-
224
- describe "remove_money" do
225
- it "remove integer column for money and a string column for currency" do
226
- expect { migrate RemovePrincipalFromLoanUsingTableApi }.to change { dump_schema }.from(schema_with_principal).to(schema_with_only_name)
295
+
296
+ describe "#add_money" do
297
+ it "creates one column for each money attribute, to store the lower denomination as an integer. currency is stored in a common column" do
298
+ expect(dump_schema).to eq schema_with_single_currency_column
299
+ end
227
300
  end
228
- end
229
- end
230
301
 
231
- context "single currency column", :single_currency do
232
- it "creates integer columns for money and a single string column for currency" do
233
- migrate CreateLoanWithSingleCurrencyColumnGivenLast
234
- expect(dump_schema).to eq schema_with_single_currency_column
235
- end
302
+ describe "#remove_money" do
303
+ it "drops the money column for each money attribute and the common currency column as well", :fixme, :fixme_need_to_clear_table_cache do
304
+ expect { migrate SchemaStatements::RemoveMoneyColumnsFromLoan }.to change { dump_schema }.from(schema_with_single_currency_column).to(schema_with_only_name)
305
+ end
236
306
 
237
- context "order does not matter" do
238
- it "creates integer columns for money and a single string column for currency even when currency column is given first" do
239
- migrate CreateLoanWithSingleCurrencyColumnGivenFirst
240
- expect(dump_schema).to eq schema_with_single_currency_column
307
+ it "drops the money column for each money attribute but keeps the common currency column because some money columns still remain" do
308
+ expect { migrate SchemaStatements::RemoveMoneyColumnsExceptPrincipalFromLoan }.to change { dump_schema }.
309
+ from(schema_with_single_currency_column).
310
+ to(schema_with_principal_and_single_currency_column)
311
+ end
241
312
  end
242
313
 
243
- it "creates integer columns for money and a single string column for currency even when currency column is given in between" do
244
- migrate CreateLoanWithSingleCurrencyColumnOrderDoesNotMatter
245
- expect(dump_schema).to eq schema_with_single_currency_column
314
+ describe "#remove_currency" do
315
+ it "drops the common currency column and adds a currency columns to each of the existing money columns" do
316
+ expect { migrate SchemaStatements::RemoveCurrencyFromLoan }.to change { dump_schema }.from(schema_with_single_currency_column).to(schema_with_multiple_currency_columns)
317
+ end
318
+
319
+ pending "remove currency while side-by-side adding a money column"
246
320
  end
247
321
  end
322
+ end # context "schema_statements"
248
323
 
249
- it "can remove the currency column later" do
250
- migrate CreateLoanWithSingleCurrencyColumnGivenLast
251
- expect { migrate RemoveCurrencyFromLoan }.to change { dump_schema }.from(schema_with_single_currency_column).to(schema_with_multiple_currency_columns)
252
- end
324
+ context "and testing table statements", :table_statements do
325
+ context "which have one currency column for each money column" do
326
+ before(:each) do
327
+ migrate CreateTableDefinition::CreateLoanAndMoney
328
+ end
329
+
330
+ describe "#add_money" do
331
+ it "creates two columns for each money attribute. one to store the lower denomination as an integer and the currency as a string" do
332
+ expect(dump_schema).to eq schema_with_principal
333
+ end
334
+ end
253
335
 
254
- it "can add a single currrency column later" do
255
- migrate CreateLoanWithMultipleMoneyColumns
256
- expect { migrate AddSingleCurrencyToLoan }.to change { dump_schema }.from(schema_with_multiple_currency_columns).to(schema_with_single_currency_column)
336
+ describe "#remove_money" do
337
+ it "drops two columns for each money attribute. one which stored the lower denomination as an integer and the currency as a string" do
338
+ expect { migrate ChangeTable::RemovePrincipalFromLoan }.to change { dump_schema }.from(schema_with_principal).to(schema_with_only_name)
339
+ end
340
+ end
257
341
  end
258
- end
342
+
343
+ context "which has a single currency", :single_currency do
344
+ describe "#add_money" do
345
+ context "and tests that order of statements does not matter" do
346
+ it "creates money and common currency cilumns when currency column is specified last" do
347
+ migrate CreateTableDefinition::CreateLoanWithCurrency
348
+ expect(dump_schema).to eq schema_with_single_currency_column
349
+ end
350
+
351
+ it "creates money and common currency cilumns when currency column is specified first" do
352
+ migrate CreateTableDefinition::CreateLoanWithCurrencySpecifiedFirst
353
+ expect(dump_schema).to eq schema_with_single_currency_column
354
+ end
355
+
356
+ it "creates money and common currency cilumns when currency column is specified in-between" do
357
+ migrate CreateTableDefinition::CreateLoanWithCurrencySpecifiedInBetween
358
+ expect(dump_schema).to eq schema_with_single_currency_column
359
+ end
360
+ end
361
+ end
362
+
363
+ describe "#remove_money" do
364
+ before(:each) do
365
+ migrate CreateTableDefinition::CreateLoanWithCurrency
366
+ end
367
+
368
+ it "drops the money column for each money attribute and the common currency column as well" do
369
+ expect { migrate ChangeTable::RemoveMoneyColumnsFromLoan }.to change { dump_schema }.from(schema_with_single_currency_column).to(schema_with_only_name)
370
+ end
371
+
372
+ it "drops the money column for each money attribute but keeps the common currency column because some money columns still remain" do
373
+ expect { migrate ChangeTable::RemoveMoneyColumnsExceptPrincipalFromLoan }.to change { dump_schema }.
374
+ from(schema_with_single_currency_column).
375
+ to(schema_with_principal_and_single_currency_column)
376
+ end
377
+ end
378
+
379
+ describe "#remove_currency" do
380
+ it "drops the common currency column and adds a currency columns to each of the existing money columns" do
381
+ migrate CreateTableDefinition::CreateLoanWithCurrency
382
+ expect { migrate ChangeTable::RemoveCurrencyFromLoan }.to change { dump_schema }.from(schema_with_single_currency_column).to(schema_with_multiple_currency_columns)
383
+ end
384
+ end
385
+
386
+ it "can add a single currrency column later" do
387
+ migrate CreateTableDefinition::CreateLoanWithoutCurrency
388
+ expect { migrate ChangeTable::AddSingleCurrencyToLoan }.to change { dump_schema }.from(schema_with_multiple_currency_columns).to(schema_with_single_currency_column)
389
+ end
390
+ end # context "which has a single currency"
391
+ end # context "and testing table statements"
259
392
 
260
393
  it "can add a money column later" do
261
- migrate CreateLoan
262
- expect { migrate AddPrincipalToLoan }.to change { dump_schema }.from(schema_with_only_name).to(schema_with_principal)
394
+ migrate CreateTableDefinition::CreateLoan
395
+ expect { migrate ChangeTable::AddPrincipalToLoan }.to change { dump_schema }.from(schema_with_only_name).to(schema_with_principal)
263
396
  end
264
397
 
265
- end # describe "migration"
398
+ pending "separate up and down migration methods. using add_money and remove_money"
399
+ end # describe "Migrating Money columns"
266
400
  end # if defined? ActiveRecord