low_card_tables 1.0.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 (61) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.travis.yml +59 -0
  4. data/Gemfile +17 -0
  5. data/LICENSE +21 -0
  6. data/README.md +75 -0
  7. data/Rakefile +6 -0
  8. data/lib/low_card_tables.rb +72 -0
  9. data/lib/low_card_tables/active_record/base.rb +55 -0
  10. data/lib/low_card_tables/active_record/migrations.rb +223 -0
  11. data/lib/low_card_tables/active_record/relation.rb +35 -0
  12. data/lib/low_card_tables/active_record/scoping.rb +87 -0
  13. data/lib/low_card_tables/errors.rb +74 -0
  14. data/lib/low_card_tables/has_low_card_table/base.rb +114 -0
  15. data/lib/low_card_tables/has_low_card_table/low_card_association.rb +273 -0
  16. data/lib/low_card_tables/has_low_card_table/low_card_associations_manager.rb +143 -0
  17. data/lib/low_card_tables/has_low_card_table/low_card_dynamic_method_manager.rb +224 -0
  18. data/lib/low_card_tables/has_low_card_table/low_card_objects_manager.rb +80 -0
  19. data/lib/low_card_tables/low_card_table/base.rb +184 -0
  20. data/lib/low_card_tables/low_card_table/cache.rb +214 -0
  21. data/lib/low_card_tables/low_card_table/cache_expiration/exponential_cache_expiration_policy.rb +151 -0
  22. data/lib/low_card_tables/low_card_table/cache_expiration/fixed_cache_expiration_policy.rb +23 -0
  23. data/lib/low_card_tables/low_card_table/cache_expiration/has_cache_expiration.rb +100 -0
  24. data/lib/low_card_tables/low_card_table/cache_expiration/no_caching_expiration_policy.rb +13 -0
  25. data/lib/low_card_tables/low_card_table/cache_expiration/unlimited_cache_expiration_policy.rb +13 -0
  26. data/lib/low_card_tables/low_card_table/row_collapser.rb +175 -0
  27. data/lib/low_card_tables/low_card_table/row_manager.rb +681 -0
  28. data/lib/low_card_tables/low_card_table/table_unique_index.rb +134 -0
  29. data/lib/low_card_tables/version.rb +4 -0
  30. data/lib/low_card_tables/version_support.rb +52 -0
  31. data/low_card_tables.gemspec +69 -0
  32. data/spec/low_card_tables/helpers/database_helper.rb +148 -0
  33. data/spec/low_card_tables/helpers/query_spy_helper.rb +47 -0
  34. data/spec/low_card_tables/helpers/system_helpers.rb +63 -0
  35. data/spec/low_card_tables/system/basic_system_spec.rb +254 -0
  36. data/spec/low_card_tables/system/bulk_system_spec.rb +334 -0
  37. data/spec/low_card_tables/system/caching_system_spec.rb +531 -0
  38. data/spec/low_card_tables/system/migrations_system_spec.rb +747 -0
  39. data/spec/low_card_tables/system/options_system_spec.rb +581 -0
  40. data/spec/low_card_tables/system/queries_system_spec.rb +142 -0
  41. data/spec/low_card_tables/system/validations_system_spec.rb +88 -0
  42. data/spec/low_card_tables/unit/active_record/base_spec.rb +53 -0
  43. data/spec/low_card_tables/unit/active_record/migrations_spec.rb +207 -0
  44. data/spec/low_card_tables/unit/active_record/relation_spec.rb +47 -0
  45. data/spec/low_card_tables/unit/active_record/scoping_spec.rb +101 -0
  46. data/spec/low_card_tables/unit/has_low_card_table/base_spec.rb +79 -0
  47. data/spec/low_card_tables/unit/has_low_card_table/low_card_association_spec.rb +287 -0
  48. data/spec/low_card_tables/unit/has_low_card_table/low_card_associations_manager_spec.rb +190 -0
  49. data/spec/low_card_tables/unit/has_low_card_table/low_card_dynamic_method_manager_spec.rb +234 -0
  50. data/spec/low_card_tables/unit/has_low_card_table/low_card_objects_manager_spec.rb +70 -0
  51. data/spec/low_card_tables/unit/low_card_table/base_spec.rb +207 -0
  52. data/spec/low_card_tables/unit/low_card_table/cache_expiration/exponential_cache_expiration_policy_spec.rb +128 -0
  53. data/spec/low_card_tables/unit/low_card_table/cache_expiration/fixed_cache_expiration_policy_spec.rb +25 -0
  54. data/spec/low_card_tables/unit/low_card_table/cache_expiration/has_cache_expiration_policy_spec.rb +100 -0
  55. data/spec/low_card_tables/unit/low_card_table/cache_expiration/no_caching_expiration_policy_spec.rb +14 -0
  56. data/spec/low_card_tables/unit/low_card_table/cache_expiration/unlimited_cache_expiration_policy_spec.rb +14 -0
  57. data/spec/low_card_tables/unit/low_card_table/cache_spec.rb +282 -0
  58. data/spec/low_card_tables/unit/low_card_table/row_collapser_spec.rb +109 -0
  59. data/spec/low_card_tables/unit/low_card_table/row_manager_spec.rb +918 -0
  60. data/spec/low_card_tables/unit/low_card_table/table_unique_index_spec.rb +117 -0
  61. metadata +206 -0
@@ -0,0 +1,581 @@
1
+ require 'low_card_tables'
2
+ require 'low_card_tables/helpers/database_helper'
3
+ require 'low_card_tables/helpers/system_helpers'
4
+
5
+ describe "LowCardTables association options" do
6
+ include LowCardTables::Helpers::SystemHelpers
7
+
8
+ before :each do
9
+ @dh = LowCardTables::Helpers::DatabaseHelper.new
10
+ @dh.setup_activerecord!
11
+ end
12
+
13
+ it "should exclude any columns marked with :exclude_column_names" do
14
+ migrate do
15
+ drop_table :lctables_spec_user_statuses rescue nil
16
+ create_table :lctables_spec_user_statuses do |t|
17
+ t.boolean :deleted, :null => false
18
+ t.boolean :deceased
19
+ t.string :gender, :null => false
20
+ t.integer :donation_level
21
+ end
22
+
23
+ add_index :lctables_spec_user_statuses, [ :deleted, :deceased, :gender ], :unique => true, :name => 'index_lctables_spec_user_statuses_on_all'
24
+
25
+ drop_table :lctables_spec_users rescue nil
26
+ create_table :lctables_spec_users do |t|
27
+ t.string :name, :null => false
28
+ t.integer :user_status_id, :null => false, :limit => 2
29
+ end
30
+ end
31
+
32
+ define_model_class(:UserStatusExcludeColumnNames, :lctables_spec_user_statuses) do
33
+ is_low_card_table :exclude_column_names => [ :donation_level ]
34
+ end
35
+
36
+ define_model_class(:UserExcludeColumnNames, :lctables_spec_users) do
37
+ has_low_card_table :status, :class => :UserStatusExcludeColumnNames, :foreign_key => :user_status_id
38
+ end
39
+
40
+ ::UserStatusExcludeColumnNames.count.should == 0
41
+
42
+ user1 = ::UserExcludeColumnNames.new
43
+ user1.name = 'User1'
44
+ user1.deleted = false
45
+ user1.deceased = false
46
+ user1.gender = 'female'
47
+ user1.status.donation_level = 15
48
+
49
+ user1.respond_to?(:donation_level).should_not be
50
+ user1.save!
51
+
52
+ ::UserStatusExcludeColumnNames.count.should == 1
53
+ ::UserStatusExcludeColumnNames.first.donation_level.should be_nil
54
+ ::UserStatusExcludeColumnNames.update_all("donation_level = 35")
55
+
56
+ user2 = ::UserExcludeColumnNames.new
57
+ user2.name = 'User2'
58
+ user2.deleted = false
59
+ user2.deceased = false
60
+ user2.gender = 'female'
61
+ user2.status.donation_level = 27
62
+
63
+ user2.save!
64
+
65
+ user1.user_status_id.should == user2.user_status_id
66
+ ::UserStatusExcludeColumnNames.count.should == 1
67
+ ::UserStatusExcludeColumnNames.first.donation_level.should == 35
68
+ end
69
+
70
+ it "should exclude :created_at and :updated_at by default, but use them" do
71
+ migrate do
72
+ drop_table :lctables_spec_user_statuses rescue nil
73
+ create_table :lctables_spec_user_statuses do |t|
74
+ t.boolean :deleted, :null => false
75
+ t.boolean :deceased
76
+ t.string :gender, :null => false
77
+
78
+ t.timestamps
79
+ end
80
+
81
+ add_index :lctables_spec_user_statuses, [ :deleted, :deceased, :gender ], :unique => true, :name => 'index_lctables_spec_user_statuses_on_all'
82
+
83
+ drop_table :lctables_spec_users rescue nil
84
+ create_table :lctables_spec_users do |t|
85
+ t.string :name, :null => false
86
+ t.integer :user_status_id, :null => false, :limit => 2
87
+ end
88
+ end
89
+
90
+ define_model_class(:UserStatusExcludeCreatedUpdated, :lctables_spec_user_statuses) { is_low_card_table }
91
+
92
+ define_model_class(:UserExcludeCreatedUpdated, :lctables_spec_users) do
93
+ has_low_card_table :status, :class => :UserStatusExcludeCreatedUpdated, :foreign_key => :user_status_id
94
+ end
95
+
96
+ ::UserStatusExcludeCreatedUpdated.count.should == 0
97
+
98
+ user1 = ::UserExcludeCreatedUpdated.new
99
+ user1.name = 'User1'
100
+ user1.deleted = false
101
+ user1.deceased = false
102
+ user1.gender = 'female'
103
+
104
+ start_time = Time.now.to_i
105
+ user1.save!
106
+ end_time = Time.now.to_i
107
+
108
+ ::UserStatusExcludeCreatedUpdated.count.should == 1
109
+ ::UserStatusExcludeCreatedUpdated.first.created_at.to_i.should >= start_time
110
+ ::UserStatusExcludeCreatedUpdated.first.created_at.to_i.should <= end_time
111
+ ::UserStatusExcludeCreatedUpdated.first.updated_at.to_i.should >= start_time
112
+ ::UserStatusExcludeCreatedUpdated.first.updated_at.to_i.should <= end_time
113
+
114
+ user2 = ::UserExcludeCreatedUpdated.new
115
+ user2.name = 'User2'
116
+ user2.deleted = false
117
+ user2.deceased = false
118
+ user2.gender = 'female'
119
+
120
+ user2.save!
121
+
122
+ user1.user_status_id.should == user2.user_status_id
123
+ ::UserStatusExcludeCreatedUpdated.count.should == 1
124
+ ::UserStatusExcludeCreatedUpdated.first.created_at.to_i.should >= start_time
125
+ ::UserStatusExcludeCreatedUpdated.first.created_at.to_i.should <= end_time
126
+ ::UserStatusExcludeCreatedUpdated.first.updated_at.to_i.should >= start_time
127
+ ::UserStatusExcludeCreatedUpdated.first.updated_at.to_i.should <= end_time
128
+ end
129
+ context "with standard setup" do
130
+ before :each do
131
+ create_standard_system_spec_tables!
132
+ create_standard_system_spec_models!
133
+ end
134
+
135
+ after :each do
136
+ drop_standard_system_spec_tables!
137
+ end
138
+
139
+ it "should allow multiple references from a table to the same low-card table, and method delegation should be from the last one added" do
140
+ migrate do
141
+ add_column :lctables_spec_users, :old_user_status_id, :integer
142
+ end
143
+
144
+ ::User.reset_column_information
145
+ class ::User < ::ActiveRecord::Base
146
+ has_low_card_table :old_status, :class => ::UserStatus, :foreign_key => :old_user_status_id
147
+ end
148
+
149
+ user1 = ::User.new
150
+
151
+ user1.name = 'User1'
152
+
153
+ user1.deleted = false
154
+ user1.deceased = false
155
+ user1.gender = 'female'
156
+ user1.donation_level = 8
157
+
158
+ user1.status.deleted = true
159
+ user1.status.deceased = false
160
+ user1.status.gender = 'male'
161
+ user1.status.donation_level = 3
162
+
163
+ user1.save!
164
+
165
+ user1.user_status_id.should_not == user1.old_user_status_id
166
+
167
+ user1_again = ::User.find(user1.id)
168
+
169
+ user1_again.user_status_id.should == user1.user_status_id
170
+ user1_again.old_user_status_id.should == user1.old_user_status_id
171
+
172
+ user1_again.status.deleted.should == true
173
+ user1_again.status.deceased.should == false
174
+ user1_again.status.gender.should == 'male'
175
+ user1_again.status.donation_level.should == 3
176
+
177
+ user1_again.old_status.deleted.should == false
178
+ user1_again.old_status.deceased.should == false
179
+ user1_again.old_status.gender.should == 'female'
180
+ user1_again.old_status.donation_level.should == 8
181
+ end
182
+
183
+ it "should not blow away methods that are already there, in the class itself, but still allow calls to super" do
184
+ define_model_class(:UserTest, :lctables_spec_users) do
185
+ def deleted
186
+ [ @_other_deleted, super ]
187
+ end
188
+
189
+ def deleted=(x)
190
+ @_other_deleted ||= [ ]
191
+ @_other_deleted << x
192
+ super(x)
193
+ end
194
+
195
+ has_low_card_table :status, :class => ::UserStatus, :foreign_key => :user_status_id
196
+ end
197
+
198
+ user1 = ::UserTest.new
199
+
200
+ user1.deleted.should == [ nil, nil ]
201
+ user1.deleted = true
202
+ user1.deleted.should == [ [ true ], true ]
203
+ user1.deleted = false
204
+ user1.deleted.should == [ [ true, false ], false ]
205
+ end
206
+
207
+ it "should override methods defined in a superclass" do
208
+ class RandomSuperclass < ::ActiveRecord::Base
209
+ self.table_name = :lctables_spec_users
210
+
211
+ def deleted
212
+ raise "should never run"
213
+ end
214
+
215
+ def deleted=(x)
216
+ raise "should never run"
217
+ end
218
+ end
219
+
220
+ class UserTest1 < RandomSuperclass
221
+ has_low_card_table :status, :class => ::UserStatus, :foreign_key => :user_status_id
222
+ end
223
+
224
+ user1 = ::UserTest1.new
225
+ user1.name = 'User1'
226
+
227
+ user1.deleted.should == nil
228
+ user1.deleted = true
229
+ user1.deleted.should == true
230
+ user1.deceased = false
231
+ user1.gender = 'female'
232
+ user1.donation_level = 10
233
+ user1.save!
234
+
235
+ user1.deleted.should == true
236
+ user1.deleted = false
237
+ user1.deleted.should == false
238
+ user1.save!
239
+
240
+ user1.deleted.should == false
241
+ end
242
+
243
+ it "should override methods defined in a module, when included before" do
244
+ module RandomModule
245
+ def deleted
246
+ raise "should never run"
247
+ end
248
+
249
+ def deleted=(x)
250
+ raise "should never run"
251
+ end
252
+ end
253
+
254
+ class UserTest2 < ::ActiveRecord::Base
255
+ include RandomModule
256
+
257
+ self.table_name = :lctables_spec_users
258
+ has_low_card_table :status, :class => ::UserStatus, :foreign_key => :user_status_id
259
+ end
260
+
261
+ user1 = ::UserTest2.new
262
+ user1.name = 'User1'
263
+
264
+ user1.deleted.should == nil
265
+ user1.deleted = true
266
+ user1.deleted.should == true
267
+ user1.deceased = false
268
+ user1.gender = 'female'
269
+ user1.donation_level = 10
270
+ user1.save!
271
+
272
+ user1.deleted.should == true
273
+ user1.deleted = false
274
+ user1.deleted.should == false
275
+ user1.save!
276
+
277
+ user1.deleted.should == false
278
+ end
279
+
280
+ it "should not override methods defined in a module, when included after" do
281
+ module RandomModule
282
+ def deleted
283
+ "foo#{@_deleted}"
284
+ end
285
+
286
+ def deleted=(x)
287
+ @_deleted = x
288
+ end
289
+ end
290
+
291
+ class UserTest3 < ::ActiveRecord::Base
292
+ self.table_name = :lctables_spec_users
293
+ has_low_card_table :status, :class => ::UserStatus, :foreign_key => :user_status_id
294
+
295
+ include RandomModule
296
+ end
297
+
298
+ user1 = ::UserTest3.new
299
+ user1.name = 'User1'
300
+
301
+ user1.deleted.should == 'foo'
302
+ user1.deleted = 'bar'
303
+ user1.deleted.should == 'foobar'
304
+ end
305
+
306
+ it "should allow prefixing delegated methods with the association name easily" do
307
+ define_model_class(:User, :lctables_spec_users) { has_low_card_table :status, :prefix => true }
308
+
309
+ user1 = ::User.new
310
+ user1.name = 'User1'
311
+
312
+ lambda { user1.deleted }.should raise_error(NoMethodError)
313
+ lambda { user1.deceased }.should raise_error(NoMethodError)
314
+ lambda { user1.gender }.should raise_error(NoMethodError)
315
+ lambda { user1.donation_level }.should raise_error(NoMethodError)
316
+ lambda { user1.deleted = true }.should raise_error(NoMethodError)
317
+ lambda { user1.deceased = true }.should raise_error(NoMethodError)
318
+ lambda { user1.gender = 'male' }.should raise_error(NoMethodError)
319
+ lambda { user1.donation_level = 10 }.should raise_error(NoMethodError)
320
+
321
+ user1.status_deleted = true
322
+ user1.status_deceased = false
323
+ user1.status_gender = 'female'
324
+ user1.status_donation_level = 10
325
+
326
+ user1.save!
327
+
328
+ user1.status_deleted.should == true
329
+ user1.status_deceased.should == false
330
+ user1.status_gender.should == 'female'
331
+ user1.status_donation_level.should == 10
332
+
333
+ user1.status.deleted.should == true
334
+ user1.status.deceased.should == false
335
+ user1.status.gender.should == 'female'
336
+ user1.status.donation_level.should == 10
337
+ end
338
+
339
+ %w{symbol string}.each do |prefix_type|
340
+ it "should allow prefixing delegated methods with any arbitrary #{prefix_type}" do
341
+ prefix = 'foo'
342
+ prefix = prefix.to_sym if prefix_type == 'symbol'
343
+ define_model_class(:User, :lctables_spec_users) { has_low_card_table :status, :prefix => prefix }
344
+
345
+ user1 = ::User.new
346
+ user1.name = 'User1'
347
+
348
+ lambda { user1.deleted }.should raise_error(NoMethodError)
349
+ lambda { user1.deceased }.should raise_error(NoMethodError)
350
+ lambda { user1.gender }.should raise_error(NoMethodError)
351
+ lambda { user1.donation_level }.should raise_error(NoMethodError)
352
+ lambda { user1.deleted = true }.should raise_error(NoMethodError)
353
+ lambda { user1.deceased = true }.should raise_error(NoMethodError)
354
+ lambda { user1.gender = 'male' }.should raise_error(NoMethodError)
355
+ lambda { user1.donation_level = 10 }.should raise_error(NoMethodError)
356
+
357
+ user1.foo_deleted = true
358
+ user1.foo_deceased = false
359
+ user1.foo_gender = 'female'
360
+ user1.foo_donation_level = 10
361
+
362
+ user1.save!
363
+
364
+ user1.foo_deleted.should == true
365
+ user1.foo_deceased.should == false
366
+ user1.foo_gender.should == 'female'
367
+ user1.foo_donation_level.should == 10
368
+
369
+ user1.status.deleted.should == true
370
+ user1.status.deceased.should == false
371
+ user1.status.gender.should == 'female'
372
+ user1.status.donation_level.should == 10
373
+ end
374
+ end
375
+
376
+ it "should allow defining an association twice, and the second one should win" do
377
+ define_model_class(:User, :lctables_spec_users) do
378
+ has_low_card_table :status
379
+ has_low_card_table :status, :prefix => :foo
380
+ end
381
+
382
+ user1 = ::User.new
383
+ user1.name = 'User1'
384
+
385
+ lambda { user1.deleted }.should raise_error(NoMethodError)
386
+ lambda { user1.deceased }.should raise_error(NoMethodError)
387
+ lambda { user1.gender }.should raise_error(NoMethodError)
388
+ lambda { user1.donation_level }.should raise_error(NoMethodError)
389
+ lambda { user1.deleted = true }.should raise_error(NoMethodError)
390
+ lambda { user1.deceased = true }.should raise_error(NoMethodError)
391
+ lambda { user1.gender = 'male' }.should raise_error(NoMethodError)
392
+ lambda { user1.donation_level = 10 }.should raise_error(NoMethodError)
393
+
394
+ user1.foo_deleted = true
395
+ user1.foo_deceased = false
396
+ user1.foo_gender = 'female'
397
+ user1.foo_donation_level = 10
398
+
399
+ user1.save!
400
+
401
+ user1.foo_deleted.should == true
402
+ user1.foo_deceased.should == false
403
+ user1.foo_gender.should == 'female'
404
+ user1.foo_donation_level.should == 10
405
+
406
+ user1.status.deleted.should == true
407
+ user1.status.deceased.should == false
408
+ user1.status.gender.should == 'female'
409
+ user1.status.donation_level.should == 10
410
+ end
411
+
412
+ it "should allow delegating no methods from the has_low_card_table class" do
413
+ define_model_class(:User, :lctables_spec_users) { has_low_card_table :status, :delegate => false }
414
+
415
+ user1 = ::User.new
416
+ user1.name = 'User1'
417
+
418
+ lambda { user1.deleted }.should raise_error(NoMethodError)
419
+ lambda { user1.deceased }.should raise_error(NoMethodError)
420
+ lambda { user1.gender }.should raise_error(NoMethodError)
421
+ lambda { user1.donation_level }.should raise_error(NoMethodError)
422
+ lambda { user1.deleted = true }.should raise_error(NoMethodError)
423
+ lambda { user1.deceased = true }.should raise_error(NoMethodError)
424
+ lambda { user1.gender = 'male' }.should raise_error(NoMethodError)
425
+ lambda { user1.donation_level = 10 }.should raise_error(NoMethodError)
426
+
427
+ user1.status.deleted = true
428
+ user1.status.deceased = false
429
+ user1.status.gender = 'female'
430
+ user1.status.donation_level = 10
431
+
432
+ user1.save!
433
+
434
+ user1.status.deleted.should == true
435
+ user1.status.deceased.should == false
436
+ user1.status.gender.should == 'female'
437
+ user1.status.donation_level.should == 10
438
+ end
439
+
440
+ it "should allow delegating just specified methods from the has_low_card_table class" do
441
+ define_model_class(:User, :lctables_spec_users) { has_low_card_table :status, :delegate => [ 'deleted', :gender ] }
442
+
443
+ user1 = ::User.new
444
+ user1.name = 'User1'
445
+
446
+ lambda { user1.deceased }.should raise_error(NoMethodError)
447
+ lambda { user1.donation_level }.should raise_error(NoMethodError)
448
+ lambda { user1.deceased = true }.should raise_error(NoMethodError)
449
+ lambda { user1.donation_level = 10 }.should raise_error(NoMethodError)
450
+
451
+ user1.deleted = true
452
+ user1.status.deceased = false
453
+ user1.gender = 'female'
454
+ user1.status.donation_level = 10
455
+
456
+ user1.save!
457
+
458
+ user1.deleted.should == true
459
+ user1.status.deleted.should == true
460
+ user1.status.deceased.should == false
461
+ user1.gender.should == 'female'
462
+ user1.status.gender.should == 'female'
463
+ user1.status.donation_level.should == 10
464
+ end
465
+
466
+ it "should allow delegating all methods from the has_low_card_table class except what's excluded" do
467
+ define_model_class(:User, :lctables_spec_users) { has_low_card_table :status, :delegate => { :except => [ 'deceased', :donation_level ] } }
468
+
469
+ user1 = ::User.new
470
+ user1.name = 'User1'
471
+
472
+ lambda { user1.deceased }.should raise_error(NoMethodError)
473
+ lambda { user1.donation_level }.should raise_error(NoMethodError)
474
+ lambda { user1.deceased = true }.should raise_error(NoMethodError)
475
+ lambda { user1.donation_level = 10 }.should raise_error(NoMethodError)
476
+
477
+ user1.deleted = true
478
+ user1.status.deceased = false
479
+ user1.gender = 'female'
480
+ user1.status.donation_level = 10
481
+
482
+ user1.save!
483
+
484
+ user1.deleted.should == true
485
+ user1.status.deleted.should == true
486
+ user1.status.deceased.should == false
487
+ user1.gender.should == 'female'
488
+ user1.status.gender.should == 'female'
489
+ user1.status.donation_level.should == 10
490
+ end
491
+
492
+ it "should blow up if asked to delegate or exclude methods that aren't there" do
493
+ e = nil
494
+ begin
495
+ define_model_class(:User, :lctables_spec_users) { has_low_card_table :status, :delegate => [ :foo ] }
496
+ rescue ArgumentError => x
497
+ e = x
498
+ end
499
+
500
+ e.message.should match(/foo/mi)
501
+ e.message.should match(/deleted/mi)
502
+ e.message.should match(/deceased/mi)
503
+ e.message.should match(/gender/mi)
504
+ e.message.should match(/donation_level/mi)
505
+
506
+ e = nil
507
+ begin
508
+ define_model_class(:User, :lctables_spec_users) { has_low_card_table :status, :delegate => { :except => [ :foo ] } }
509
+ rescue ArgumentError => x
510
+ e = x
511
+ end
512
+
513
+ e.message.should match(/foo/mi)
514
+ e.message.should match(/deleted/mi)
515
+ e.message.should match(/deceased/mi)
516
+ e.message.should match(/gender/mi)
517
+ e.message.should match(/donation_level/mi)
518
+ end
519
+
520
+ it "should combine :prefix and :delegate correctly" do
521
+ define_model_class(:User, :lctables_spec_users) { has_low_card_table :status, :prefix => :foo, :delegate => { :except => [ 'deceased', :donation_level ] } }
522
+
523
+ user1 = ::User.new
524
+ user1.name = 'User1'
525
+
526
+ lambda { user1.foo_deceased }.should raise_error(NoMethodError)
527
+ lambda { user1.foo_donation_level }.should raise_error(NoMethodError)
528
+ lambda { user1.foo_deceased = true }.should raise_error(NoMethodError)
529
+ lambda { user1.foo_donation_level = 10 }.should raise_error(NoMethodError)
530
+
531
+ user1.foo_deleted = true
532
+ user1.status.deceased = false
533
+ user1.foo_gender = 'female'
534
+ user1.status.donation_level = 10
535
+
536
+ user1.save!
537
+
538
+ user1.foo_deleted.should == true
539
+ user1.status.deleted.should == true
540
+ user1.status.deceased.should == false
541
+ user1.foo_gender.should == 'female'
542
+ user1.status.gender.should == 'female'
543
+ user1.status.donation_level.should == 10
544
+ end
545
+
546
+ %w{symbol string class}.each do |specification_type|
547
+ it "should allow specifying the target class manually as a #{specification_type}, and the foreign key manually" do
548
+ define_model_class(:Foobar, :lctables_spec_user_statuses) { is_low_card_table }
549
+
550
+ specification = case specification_type
551
+ when 'symbol' then :Foobar
552
+ when 'string' then 'Foobar'
553
+ when 'class' then Foobar
554
+ else raise "Unknown specification_type: #{specification_type.inspect}"
555
+ end
556
+
557
+ define_model_class(:Barbaz, :lctables_spec_users) { has_low_card_table :status, :class => specification, :foreign_key => :user_status_id }
558
+
559
+ user1 = ::Barbaz.new
560
+
561
+ user1.name = 'User1'
562
+
563
+ user1.deleted = false
564
+ user1.deceased = false
565
+ user1.gender = 'female'
566
+ user1.donation_level = 8
567
+
568
+ user1.save!
569
+
570
+ user1_again = ::Barbaz.find(user1.id)
571
+
572
+ user1_again.user_status_id.should == user1.user_status_id
573
+
574
+ user1_again.status.deleted.should == false
575
+ user1_again.status.deceased.should == false
576
+ user1_again.status.gender.should == 'female'
577
+ user1_again.status.donation_level.should == 8
578
+ end
579
+ end
580
+ end
581
+ end