activerecord 1.10.1 → 1.11.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (84) hide show
  1. data/CHANGELOG +187 -19
  2. data/RUNNING_UNIT_TESTS +11 -0
  3. data/lib/active_record.rb +3 -1
  4. data/lib/active_record/acts/list.rb +25 -14
  5. data/lib/active_record/acts/nested_set.rb +4 -4
  6. data/lib/active_record/acts/tree.rb +18 -1
  7. data/lib/active_record/associations.rb +90 -17
  8. data/lib/active_record/associations/association_collection.rb +44 -5
  9. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +17 -4
  10. data/lib/active_record/associations/has_many_association.rb +13 -3
  11. data/lib/active_record/associations/has_one_association.rb +19 -0
  12. data/lib/active_record/base.rb +292 -268
  13. data/lib/active_record/callbacks.rb +14 -14
  14. data/lib/active_record/connection_adapters/abstract_adapter.rb +137 -75
  15. data/lib/active_record/connection_adapters/db2_adapter.rb +10 -8
  16. data/lib/active_record/connection_adapters/mysql_adapter.rb +91 -64
  17. data/lib/active_record/connection_adapters/oci_adapter.rb +6 -6
  18. data/lib/active_record/connection_adapters/postgresql_adapter.rb +113 -60
  19. data/lib/active_record/connection_adapters/sqlite_adapter.rb +15 -12
  20. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +159 -132
  21. data/lib/active_record/fixtures.rb +59 -12
  22. data/lib/active_record/locking.rb +10 -9
  23. data/lib/active_record/migration.rb +112 -5
  24. data/lib/active_record/query_cache.rb +64 -0
  25. data/lib/active_record/timestamp.rb +10 -8
  26. data/lib/active_record/validations.rb +121 -26
  27. data/rakefile +16 -10
  28. data/test/aaa_create_tables_test.rb +26 -48
  29. data/test/abstract_unit.rb +3 -0
  30. data/test/aggregations_test.rb +19 -19
  31. data/test/association_callbacks_test.rb +110 -0
  32. data/test/associations_go_eager_test.rb +48 -14
  33. data/test/associations_test.rb +344 -142
  34. data/test/base_test.rb +150 -31
  35. data/test/binary_test.rb +7 -0
  36. data/test/callbacks_test.rb +24 -5
  37. data/test/column_alias_test.rb +2 -2
  38. data/test/connections/native_sqlserver_odbc/connection.rb +26 -0
  39. data/test/deprecated_associations_test.rb +27 -28
  40. data/test/deprecated_finder_test.rb +8 -9
  41. data/test/finder_test.rb +52 -17
  42. data/test/fixtures/author.rb +39 -0
  43. data/test/fixtures/categories.yml +7 -0
  44. data/test/fixtures/categories_posts.yml +8 -0
  45. data/test/fixtures/category.rb +2 -0
  46. data/test/fixtures/comment.rb +3 -1
  47. data/test/fixtures/comments.yml +43 -1
  48. data/test/fixtures/companies.yml +14 -0
  49. data/test/fixtures/company.rb +1 -1
  50. data/test/fixtures/computers.yml +2 -1
  51. data/test/fixtures/db_definitions/db2.sql +7 -2
  52. data/test/fixtures/db_definitions/mysql.drop.sql +2 -0
  53. data/test/fixtures/db_definitions/mysql.sql +11 -6
  54. data/test/fixtures/db_definitions/oci.sql +7 -2
  55. data/test/fixtures/db_definitions/postgresql.drop.sql +3 -1
  56. data/test/fixtures/db_definitions/postgresql.sql +8 -5
  57. data/test/fixtures/db_definitions/sqlite.drop.sql +2 -0
  58. data/test/fixtures/db_definitions/sqlite.sql +9 -4
  59. data/test/fixtures/db_definitions/sqlserver.drop.sql +2 -0
  60. data/test/fixtures/db_definitions/sqlserver.sql +12 -7
  61. data/test/fixtures/developer.rb +8 -1
  62. data/test/fixtures/migrations/3_innocent_jointable.rb +12 -0
  63. data/test/fixtures/post.rb +8 -2
  64. data/test/fixtures/posts.yml +21 -0
  65. data/test/fixtures/project.rb +14 -1
  66. data/test/fixtures/subscriber.rb +3 -0
  67. data/test/fixtures_test.rb +14 -0
  68. data/test/inheritance_test.rb +30 -22
  69. data/test/lifecycle_test.rb +3 -4
  70. data/test/locking_test.rb +2 -4
  71. data/test/migration_test.rb +186 -0
  72. data/test/mixin_nested_set_test.rb +19 -19
  73. data/test/mixin_test.rb +88 -88
  74. data/test/modules_test.rb +5 -10
  75. data/test/multiple_db_test.rb +2 -0
  76. data/test/pk_test.rb +8 -12
  77. data/test/reflection_test.rb +8 -4
  78. data/test/schema_test_postgresql.rb +63 -0
  79. data/test/thread_safety_test.rb +4 -1
  80. data/test/transactions_test.rb +9 -2
  81. data/test/unconnected_test.rb +1 -0
  82. data/test/validations_test.rb +151 -8
  83. metadata +11 -5
  84. data/test/migration_mysql.rb +0 -104
@@ -17,10 +17,8 @@ raise "ActiveRecord should have barked on bad collection keys" unless bad_collec
17
17
 
18
18
 
19
19
  class AssociationsTest < Test::Unit::TestCase
20
- def setup
21
- create_fixtures "accounts", "companies", "developers", "projects", "developers_projects", "computers"
22
- @signals37 = Firm.find(1)
23
- end
20
+ fixtures :accounts, :companies, :developers, :projects, :developers_projects,
21
+ :computers
24
22
 
25
23
  def test_force_reload
26
24
  firm = Firm.new("name" => "A New Firm, Inc")
@@ -63,23 +61,20 @@ class AssociationsTest < Test::Unit::TestCase
63
61
  end
64
62
 
65
63
  class HasOneAssociationsTest < Test::Unit::TestCase
66
- def setup
67
- create_fixtures "accounts", "companies", "developers", "projects", "developers_projects"
68
- @signals37 = Firm.find(1)
69
- end
64
+ fixtures :accounts, :companies, :developers, :projects, :developers_projects
70
65
 
71
66
  def test_has_one
72
- assert_equal @signals37.account, Account.find(1)
73
- assert_equal Account.find(1).credit_limit, @signals37.account.credit_limit
67
+ assert_equal companies(:first_firm).account, Account.find(1)
68
+ assert_equal Account.find(1).credit_limit, companies(:first_firm).account.credit_limit
74
69
  end
75
70
 
76
71
  def test_triple_equality
77
- assert Account === @signals37.account
72
+ assert Account === companies(:first_firm).account
78
73
  end
79
74
 
80
75
  def test_type_mismatch
81
- assert_raises(ActiveRecord::AssociationTypeMismatch) { @signals37.account = 1 }
82
- assert_raises(ActiveRecord::AssociationTypeMismatch) { @signals37.account = Project.find(1) }
76
+ assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).account = 1 }
77
+ assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).account = Project.find(1) }
83
78
  end
84
79
 
85
80
  def test_natural_assignment
@@ -90,19 +85,48 @@ class HasOneAssociationsTest < Test::Unit::TestCase
90
85
  end
91
86
 
92
87
  def test_natural_assignment_to_nil
93
- old_account_id = @signals37.account.id
94
- @signals37.account = nil
95
- @signals37.save
96
- assert_nil @signals37.account
88
+ old_account_id = companies(:first_firm).account.id
89
+ companies(:first_firm).account = nil
90
+ companies(:first_firm).save
91
+ assert_nil companies(:first_firm).account
97
92
  # account is dependent, therefore is destroyed when reference to owner is lost
98
93
  assert_raises(ActiveRecord::RecordNotFound) { Account.find(old_account_id) }
99
94
  end
95
+
96
+ def test_assignment_without_replacement
97
+ apple = Firm.create("name" => "Apple")
98
+ citibank = Account.create("credit_limit" => 10)
99
+ apple.account = citibank
100
+ assert_equal apple.id, citibank.firm_id
101
+
102
+ hsbc = apple.build_account({ :credit_limit => 20}, false)
103
+ assert_equal apple.id, hsbc.firm_id
104
+ hsbc.save
105
+ assert_equal apple.id, citibank.firm_id
106
+
107
+ nykredit = apple.create_account({ :credit_limit => 30}, false)
108
+ assert_equal apple.id, nykredit.firm_id
109
+ assert_equal apple.id, citibank.firm_id
110
+ assert_equal apple.id, hsbc.firm_id
111
+ end
112
+
113
+ def test_assignment_without_replacement_on_create
114
+ apple = Firm.create("name" => "Apple")
115
+ citibank = Account.create("credit_limit" => 10)
116
+ apple.account = citibank
117
+ assert_equal apple.id, citibank.firm_id
118
+
119
+ hsbc = apple.create_account({:credit_limit => 10}, false)
120
+ assert_equal apple.id, hsbc.firm_id
121
+ hsbc.save
122
+ assert_equal apple.id, citibank.firm_id
123
+ end
100
124
 
101
125
  def test_dependence
102
126
  firm = Firm.find(1)
103
127
  assert !firm.account.nil?
104
128
  firm.destroy
105
- assert_equal 1, Account.find_all.length
129
+ assert_equal 1, Account.count
106
130
  end
107
131
 
108
132
  def test_succesful_build_association
@@ -227,56 +251,53 @@ end
227
251
 
228
252
 
229
253
  class HasManyAssociationsTest < Test::Unit::TestCase
230
- fixtures :accounts, :companies, :developers, :projects, :developers_projects, :topics
231
-
232
- def setup
233
- @signals37 = Firm.find(1)
234
- end
254
+ fixtures :accounts, :companies, :developers, :projects,
255
+ :developers_projects, :topics
235
256
 
236
257
  def force_signal37_to_load_all_clients_of_firm
237
- @signals37.clients_of_firm.each {|f| }
258
+ companies(:first_firm).clients_of_firm.each {|f| }
238
259
  end
239
260
 
240
261
  def test_counting
241
- assert_equal 2, Firm.find_first.clients.count
262
+ assert_equal 2, Firm.find(:first).clients.count
242
263
  end
243
264
 
244
265
  def test_finding
245
- assert_equal 2, Firm.find_first.clients.length
266
+ assert_equal 2, Firm.find(:first).clients.length
246
267
  end
247
268
 
248
269
  def test_finding_default_orders
249
- assert_equal "Summit", Firm.find_first.clients.first.name
270
+ assert_equal "Summit", Firm.find(:first).clients.first.name
250
271
  end
251
272
 
252
273
  def test_finding_with_different_class_name_and_order
253
- assert_equal "Microsoft", Firm.find_first.clients_sorted_desc.first.name
274
+ assert_equal "Microsoft", Firm.find(:first).clients_sorted_desc.first.name
254
275
  end
255
276
 
256
277
  def test_finding_with_foreign_key
257
- assert_equal "Microsoft", Firm.find_first.clients_of_firm.first.name
278
+ assert_equal "Microsoft", Firm.find(:first).clients_of_firm.first.name
258
279
  end
259
280
 
260
281
  def test_finding_with_condition
261
- assert_equal "Microsoft", Firm.find_first.clients_like_ms.first.name
282
+ assert_equal "Microsoft", Firm.find(:first).clients_like_ms.first.name
262
283
  end
263
284
 
264
285
  def test_finding_using_sql
265
- firm = Firm.find_first
286
+ firm = Firm.find(:first)
266
287
  first_client = firm.clients_using_sql.first
267
288
  assert_not_nil first_client
268
289
  assert_equal "Microsoft", first_client.name
269
290
  assert_equal 1, firm.clients_using_sql.size
270
- assert_equal 1, Firm.find_first.clients_using_sql.size
291
+ assert_equal 1, Firm.find(:first).clients_using_sql.size
271
292
  end
272
293
 
273
294
  def test_counting_using_sql
274
- assert_equal 1, Firm.find_first.clients_using_counter_sql.size
275
- assert_equal 0, Firm.find_first.clients_using_zero_counter_sql.size
295
+ assert_equal 1, Firm.find(:first).clients_using_counter_sql.size
296
+ assert_equal 0, Firm.find(:first).clients_using_zero_counter_sql.size
276
297
  end
277
298
 
278
299
  def test_counting_non_existant_items_using_sql
279
- assert_equal 0, Firm.find_first.no_clients_using_counter_sql.size
300
+ assert_equal 0, Firm.find(:first).no_clients_using_counter_sql.size
280
301
  end
281
302
 
282
303
  def test_belongs_to_sanity
@@ -295,7 +316,7 @@ class HasManyAssociationsTest < Test::Unit::TestCase
295
316
  end
296
317
 
297
318
  def test_find_ids
298
- firm = Firm.find_first
319
+ firm = Firm.find(:first)
299
320
 
300
321
  assert_raises(ActiveRecord::RecordNotFound) { firm.clients.find }
301
322
 
@@ -324,43 +345,52 @@ class HasManyAssociationsTest < Test::Unit::TestCase
324
345
  def test_find_all_sanitized
325
346
  firm = Firm.find_first
326
347
  assert_equal firm.clients.find_all("name = 'Summit'"), firm.clients.find_all(["name = '%s'", "Summit"])
348
+ summit = firm.clients.find(:all, :conditions => "name = 'Summit'")
349
+ assert_equal summit, firm.clients.find(:all, :conditions => ["name = ?", "Summit"])
350
+ assert_equal summit, firm.clients.find(:all, :conditions => ["name = :name", { :name => "Summit" }])
327
351
  end
328
352
 
329
353
  def test_find_first
330
354
  firm = Firm.find_first
355
+ client2 = Client.find(2)
331
356
  assert_equal firm.clients.first, firm.clients.find_first
332
- assert_equal Client.find(2), firm.clients.find_first("type = 'Client'")
357
+ assert_equal client2, firm.clients.find_first("type = 'Client'")
358
+ assert_equal client2, firm.clients.find(:first, :conditions => "type = 'Client'")
333
359
  end
334
360
 
335
361
  def test_find_first_sanitized
336
- assert_equal Client.find(2), Firm.find_first.clients.find_first(["type = ?", "Client"])
362
+ firm = Firm.find_first
363
+ client2 = Client.find(2)
364
+ assert_equal client2, firm.clients.find_first(["type = ?", "Client"])
365
+ assert_equal client2, firm.clients.find(:first, :conditions => ['type = ?', 'Client'])
366
+ assert_equal client2, firm.clients.find(:first, :conditions => ['type = :type', { :type => 'Client' }])
337
367
  end
338
368
 
339
369
  def test_find_in_collection
340
- assert_equal Client.find(2).name, @signals37.clients.find(2).name
341
- assert_raises(ActiveRecord::RecordNotFound) { @signals37.clients.find(6) }
370
+ assert_equal Client.find(2).name, companies(:first_firm).clients.find(2).name
371
+ assert_raises(ActiveRecord::RecordNotFound) { companies(:first_firm).clients.find(6) }
342
372
  end
343
373
 
344
374
  def test_adding
345
375
  force_signal37_to_load_all_clients_of_firm
346
376
  natural = Client.new("name" => "Natural Company")
347
- @signals37.clients_of_firm << natural
348
- assert_equal 2, @signals37.clients_of_firm.size # checking via the collection
349
- assert_equal 2, @signals37.clients_of_firm(true).size # checking using the db
350
- assert_equal natural, @signals37.clients_of_firm.last
377
+ companies(:first_firm).clients_of_firm << natural
378
+ assert_equal 2, companies(:first_firm).clients_of_firm.size # checking via the collection
379
+ assert_equal 2, companies(:first_firm).clients_of_firm(true).size # checking using the db
380
+ assert_equal natural, companies(:first_firm).clients_of_firm.last
351
381
  end
352
382
 
353
383
  def test_adding_a_mismatch_class
354
- assert_raises(ActiveRecord::AssociationTypeMismatch) { @signals37.clients_of_firm << nil }
355
- assert_raises(ActiveRecord::AssociationTypeMismatch) { @signals37.clients_of_firm << 1 }
356
- assert_raises(ActiveRecord::AssociationTypeMismatch) { @signals37.clients_of_firm << Topic.find(1) }
384
+ assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << nil }
385
+ assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << 1 }
386
+ assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << Topic.find(1) }
357
387
  end
358
388
 
359
389
  def test_adding_a_collection
360
390
  force_signal37_to_load_all_clients_of_firm
361
- @signals37.clients_of_firm.concat([Client.new("name" => "Natural Company"), Client.new("name" => "Apple")])
362
- assert_equal 3, @signals37.clients_of_firm.size
363
- assert_equal 3, @signals37.clients_of_firm(true).size
391
+ companies(:first_firm).clients_of_firm.concat([Client.new("name" => "Natural Company"), Client.new("name" => "Apple")])
392
+ assert_equal 3, companies(:first_firm).clients_of_firm.size
393
+ assert_equal 3, companies(:first_firm).clients_of_firm(true).size
364
394
  end
365
395
 
366
396
  def test_adding_before_save
@@ -406,51 +436,51 @@ class HasManyAssociationsTest < Test::Unit::TestCase
406
436
  end
407
437
 
408
438
  def test_build
409
- new_client = @signals37.clients_of_firm.build("name" => "Another Client")
439
+ new_client = companies(:first_firm).clients_of_firm.build("name" => "Another Client")
410
440
  assert_equal "Another Client", new_client.name
411
441
  assert new_client.new_record?
412
- assert_equal new_client, @signals37.clients_of_firm.last
413
- assert @signals37.save
442
+ assert_equal new_client, companies(:first_firm).clients_of_firm.last
443
+ assert companies(:first_firm).save
414
444
  assert !new_client.new_record?
415
- assert_equal 2, @signals37.clients_of_firm(true).size
445
+ assert_equal 2, companies(:first_firm).clients_of_firm(true).size
416
446
  end
417
447
 
418
448
  def test_build_many
419
- new_clients = @signals37.clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}])
449
+ new_clients = companies(:first_firm).clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}])
420
450
  assert_equal 2, new_clients.size
421
451
 
422
- assert @signals37.save
423
- assert_equal 3, @signals37.clients_of_firm(true).size
452
+ assert companies(:first_firm).save
453
+ assert_equal 3, companies(:first_firm).clients_of_firm(true).size
424
454
  end
425
455
 
426
456
  def test_invalid_build
427
- new_client = @signals37.clients_of_firm.build
457
+ new_client = companies(:first_firm).clients_of_firm.build
428
458
  assert new_client.new_record?
429
459
  assert !new_client.valid?
430
- assert_equal new_client, @signals37.clients_of_firm.last
431
- assert !@signals37.save
460
+ assert_equal new_client, companies(:first_firm).clients_of_firm.last
461
+ assert !companies(:first_firm).save
432
462
  assert new_client.new_record?
433
- assert_equal 1, @signals37.clients_of_firm(true).size
463
+ assert_equal 1, companies(:first_firm).clients_of_firm(true).size
434
464
  end
435
465
 
436
466
  def test_create
437
467
  force_signal37_to_load_all_clients_of_firm
438
- new_client = @signals37.clients_of_firm.create("name" => "Another Client")
468
+ new_client = companies(:first_firm).clients_of_firm.create("name" => "Another Client")
439
469
  assert !new_client.new_record?
440
- assert_equal new_client, @signals37.clients_of_firm.last
441
- assert_equal new_client, @signals37.clients_of_firm(true).last
470
+ assert_equal new_client, companies(:first_firm).clients_of_firm.last
471
+ assert_equal new_client, companies(:first_firm).clients_of_firm(true).last
442
472
  end
443
473
 
444
474
  def test_create_many
445
- @signals37.clients_of_firm.create([{"name" => "Another Client"}, {"name" => "Another Client II"}])
446
- assert_equal 3, @signals37.clients_of_firm(true).size
475
+ companies(:first_firm).clients_of_firm.create([{"name" => "Another Client"}, {"name" => "Another Client II"}])
476
+ assert_equal 3, companies(:first_firm).clients_of_firm(true).size
447
477
  end
448
478
 
449
479
  def test_deleting
450
480
  force_signal37_to_load_all_clients_of_firm
451
- @signals37.clients_of_firm.delete(@signals37.clients_of_firm.first)
452
- assert_equal 0, @signals37.clients_of_firm.size
453
- assert_equal 0, @signals37.clients_of_firm(true).size
481
+ companies(:first_firm).clients_of_firm.delete(companies(:first_firm).clients_of_firm.first)
482
+ assert_equal 0, companies(:first_firm).clients_of_firm.size
483
+ assert_equal 0, companies(:first_firm).clients_of_firm(true).size
454
484
  end
455
485
 
456
486
  def test_deleting_before_save
@@ -463,29 +493,29 @@ class HasManyAssociationsTest < Test::Unit::TestCase
463
493
 
464
494
  def test_deleting_a_collection
465
495
  force_signal37_to_load_all_clients_of_firm
466
- @signals37.clients_of_firm.create("name" => "Another Client")
467
- assert_equal 2, @signals37.clients_of_firm.size
468
- #@signals37.clients_of_firm.clear
469
- @signals37.clients_of_firm.delete([@signals37.clients_of_firm[0], @signals37.clients_of_firm[1]])
470
- assert_equal 0, @signals37.clients_of_firm.size
471
- assert_equal 0, @signals37.clients_of_firm(true).size
496
+ companies(:first_firm).clients_of_firm.create("name" => "Another Client")
497
+ assert_equal 2, companies(:first_firm).clients_of_firm.size
498
+ #companies(:first_firm).clients_of_firm.clear
499
+ companies(:first_firm).clients_of_firm.delete([companies(:first_firm).clients_of_firm[0], companies(:first_firm).clients_of_firm[1]])
500
+ assert_equal 0, companies(:first_firm).clients_of_firm.size
501
+ assert_equal 0, companies(:first_firm).clients_of_firm(true).size
472
502
  end
473
503
 
474
504
  def test_deleting_a_association_collection
475
505
  force_signal37_to_load_all_clients_of_firm
476
- @signals37.clients_of_firm.create("name" => "Another Client")
477
- assert_equal 2, @signals37.clients_of_firm.size
478
- @signals37.clients_of_firm.clear
479
- assert_equal 0, @signals37.clients_of_firm.size
480
- assert_equal 0, @signals37.clients_of_firm(true).size
506
+ companies(:first_firm).clients_of_firm.create("name" => "Another Client")
507
+ assert_equal 2, companies(:first_firm).clients_of_firm.size
508
+ companies(:first_firm).clients_of_firm.clear
509
+ assert_equal 0, companies(:first_firm).clients_of_firm.size
510
+ assert_equal 0, companies(:first_firm).clients_of_firm(true).size
481
511
  end
482
512
 
483
513
  def test_deleting_a_item_which_is_not_in_the_collection
484
514
  force_signal37_to_load_all_clients_of_firm
485
515
  summit = Client.find_first("name = 'Summit'")
486
- @signals37.clients_of_firm.delete(summit)
487
- assert_equal 1, @signals37.clients_of_firm.size
488
- assert_equal 1, @signals37.clients_of_firm(true).size
516
+ companies(:first_firm).clients_of_firm.delete(summit)
517
+ assert_equal 1, companies(:first_firm).clients_of_firm.size
518
+ assert_equal 1, companies(:first_firm).clients_of_firm(true).size
489
519
  assert_equal 2, summit.client_of
490
520
  end
491
521
 
@@ -503,20 +533,21 @@ class HasManyAssociationsTest < Test::Unit::TestCase
503
533
 
504
534
  def test_destroy_all
505
535
  force_signal37_to_load_all_clients_of_firm
506
- assert !@signals37.clients_of_firm.empty?, "37signals has clients after load"
507
- @signals37.clients_of_firm.destroy_all
508
- assert @signals37.clients_of_firm.empty?, "37signals has no clients after destroy all"
509
- assert @signals37.clients_of_firm(true).empty?, "37signals has no clients after destroy all and refresh"
536
+ assert !companies(:first_firm).clients_of_firm.empty?, "37signals has clients after load"
537
+ companies(:first_firm).clients_of_firm.destroy_all
538
+ assert companies(:first_firm).clients_of_firm.empty?, "37signals has no clients after destroy all"
539
+ assert companies(:first_firm).clients_of_firm(true).empty?, "37signals has no clients after destroy all and refresh"
510
540
  end
511
541
 
512
542
  def test_dependence
513
- assert_equal 2, Client.find_all.size
514
- Firm.find_first.destroy
515
- assert Client.find_all.empty?
543
+ firm = companies(:first_firm)
544
+ assert_equal 2, firm.clients.size
545
+ firm.destroy
546
+ assert Client.find(:all, :conditions => "firm_id=#{firm.id}").empty?
516
547
  end
517
548
 
518
549
  def test_destroy_dependent_when_deleted_from_association
519
- firm = Firm.find_first
550
+ firm = Firm.find(:first)
520
551
  assert_equal 2, firm.clients.size
521
552
 
522
553
  client = firm.clients.first
@@ -535,43 +566,81 @@ class HasManyAssociationsTest < Test::Unit::TestCase
535
566
  assert_nothing_raised { topic.destroy }
536
567
  end
537
568
 
569
+ uses_transaction :test_dependence_with_transaction_support_on_failure
538
570
  def test_dependence_with_transaction_support_on_failure
539
- assert_equal 2, Client.find_all.length
540
- firm = Firm.find_first
571
+ firm = companies(:first_firm)
541
572
  clients = firm.clients
573
+ assert_equal 2, clients.length
542
574
  clients.last.instance_eval { def before_destroy() raise "Trigger rollback" end }
543
575
 
544
576
  firm.destroy rescue "do nothing"
545
577
 
546
- assert_equal 2, Client.find_all.length
578
+ assert_equal 2, Client.find(:all, :conditions => "firm_id=#{firm.id}").size
547
579
  end
548
580
 
549
581
  def test_dependence_on_account
550
- assert_equal 2, Account.find_all.length
551
- @signals37.destroy
552
- assert_equal 1, Account.find_all.length
582
+ assert_equal 2, Account.count
583
+ companies(:first_firm).destroy
584
+ assert_equal 1, Account.count
553
585
  end
554
586
 
555
587
  def test_included_in_collection
556
- assert @signals37.clients.include?(Client.find(2))
588
+ assert companies(:first_firm).clients.include?(Client.find(2))
557
589
  end
558
590
 
559
591
  def test_adding_array_and_collection
560
- assert_nothing_raised { Firm.find_first.clients + Firm.find_all.last.clients }
592
+ assert_nothing_raised { Firm.find(:first).clients + Firm.find(:all).last.clients }
561
593
  end
562
- end
563
594
 
564
- class BelongsToAssociationsTest < Test::Unit::TestCase
565
- fixtures :accounts, :companies, :developers, :projects, :topics
595
+ def test_find_all_without_conditions
596
+ firm = companies(:first_firm)
597
+ assert_equal 2, firm.clients.find(:all).length
598
+ end
599
+
600
+ def test_replace_with_less
601
+ firm = Firm.find(:first)
602
+ firm.clients = [companies(:first_client)]
603
+ assert firm.save, "Could not save firm"
604
+ firm.reload
605
+ assert_equal 1, firm.clients.length
606
+ end
607
+
608
+ def test_replace_with_new
609
+ firm = Firm.find(:first)
610
+ new_client = Client.new("name" => "New Client")
611
+ firm.clients = [companies(:second_client),new_client]
612
+ firm.save
613
+ firm.reload
614
+ assert_equal 2, firm.clients.length
615
+ assert !firm.clients.include?(:first_client)
616
+ end
566
617
 
567
- def setup
568
- create_fixtures "developers_projects"
569
- @signals37 = Firm.find(1)
618
+ def test_replace_on_new_object
619
+ firm = Firm.new("name" => "New Firm")
620
+ firm.clients = [companies(:second_client), Client.new("name" => "New Client")]
621
+ assert firm.save
622
+ firm.reload
623
+ assert_equal 2, firm.clients.length
624
+ assert firm.clients.include?(Client.find_by_name("New Client"))
570
625
  end
626
+
627
+ def test_assign_ids
628
+ firm = Firm.new("name" => "Apple")
629
+ firm.client_ids = [companies(:first_client).id, companies(:second_client).id]
630
+ firm.save
631
+ firm.reload
632
+ assert_equal 2, firm.clients.length
633
+ assert firm.clients.include?(companies(:second_client))
634
+ end
635
+ end
571
636
 
637
+ class BelongsToAssociationsTest < Test::Unit::TestCase
638
+ fixtures :accounts, :companies, :developers, :projects, :topics,
639
+ :developers_projects
640
+
572
641
  def test_belongs_to
573
642
  Client.find(3).firm.name
574
- assert_equal @signals37.name, Client.find(3).firm.name
643
+ assert_equal companies(:first_firm).name, Client.find(3).firm.name
575
644
  assert !Client.find(3).firm.nil?, "Microsoft should have a firm"
576
645
  end
577
646
 
@@ -630,7 +699,7 @@ class BelongsToAssociationsTest < Test::Unit::TestCase
630
699
  end
631
700
 
632
701
  def test_assignment_before_parent_saved
633
- client = Client.find_first
702
+ client = Client.find(:first)
634
703
  apple = Firm.new("name" => "Apple")
635
704
  client.firm = apple
636
705
  assert_equal apple, client.firm
@@ -669,7 +738,7 @@ class BelongsToAssociationsTest < Test::Unit::TestCase
669
738
 
670
739
  def test_new_record_with_foreign_key_but_no_object
671
740
  c = Client.new("firm_id" => 1)
672
- assert_equal Firm.find_first, c.firm_with_basic_id
741
+ assert_equal Firm.find(:first), c.firm_with_basic_id
673
742
  end
674
743
 
675
744
  def test_forgetting_the_load_when_foreign_key_enters_late
@@ -677,7 +746,7 @@ class BelongsToAssociationsTest < Test::Unit::TestCase
677
746
  assert_nil c.firm_with_basic_id
678
747
 
679
748
  c.firm_id = 1
680
- assert_equal Firm.find_first, c.firm_with_basic_id
749
+ assert_equal Firm.find(:first), c.firm_with_basic_id
681
750
  end
682
751
 
683
752
  def test_field_name_same_as_foreign_key
@@ -695,12 +764,39 @@ class BelongsToAssociationsTest < Test::Unit::TestCase
695
764
  apple.companies_count = 2
696
765
  apple.save
697
766
 
698
- apple = Firm.find_first("name = 'Apple'")
767
+ apple = Firm.find(:first, :conditions => "name = 'Apple'")
699
768
  assert_equal 2, apple.clients.size, "Should use the new cached number"
700
769
 
701
770
  apple.clients.to_s
702
771
  assert_equal 1, apple.clients.size, "Should not use the cached number, but go to the database"
703
772
  end
773
+
774
+ end
775
+
776
+
777
+ class ProjectWithAfterCreateHook < ActiveRecord::Base
778
+ set_table_name 'projects'
779
+ has_and_belongs_to_many :developers,
780
+ :class_name => "DeveloperForProjectWithAfterCreateHook",
781
+ :join_table => "developers_projects",
782
+ :foreign_key => "project_id",
783
+ :association_foreign_key => "developer_id"
784
+
785
+ after_create :add_david
786
+
787
+ def add_david
788
+ david = DeveloperForProjectWithAfterCreateHook.find_by_name('David')
789
+ david.projects << self
790
+ end
791
+ end
792
+
793
+ class DeveloperForProjectWithAfterCreateHook < ActiveRecord::Base
794
+ set_table_name 'developers'
795
+ has_and_belongs_to_many :projects,
796
+ :class_name => "ProjectWithAfterCreateHook",
797
+ :join_table => "developers_projects",
798
+ :association_foreign_key => "project_id",
799
+ :foreign_key => "developer_id"
704
800
  end
705
801
 
706
802
 
@@ -716,9 +812,9 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
716
812
  active_record = Project.find(1)
717
813
  assert !active_record.developers.empty?
718
814
  assert_equal 2, active_record.developers.size
719
- assert_equal david.name, active_record.developers.first.name
815
+ assert active_record.developers.include?(david)
720
816
  end
721
-
817
+
722
818
  def test_adding_single
723
819
  jamis = Developer.find(2)
724
820
  jamis.projects.reload # causing the collection to load
@@ -753,8 +849,24 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
753
849
  assert_equal 2, action_controller.developers(true).size
754
850
  end
755
851
 
852
+ def test_adding_from_the_project_fixed_timestamp
853
+ jamis = Developer.find(2)
854
+ action_controller = Project.find(2)
855
+ action_controller.developers.reload
856
+ assert_equal 1, jamis.projects.size
857
+ assert_equal 1, action_controller.developers.size
858
+ updated_at = jamis.updated_at
859
+
860
+ action_controller.developers << jamis
861
+
862
+ assert_equal updated_at, jamis.updated_at
863
+ assert_equal 2, jamis.projects(true).size
864
+ assert_equal 2, action_controller.developers.size
865
+ assert_equal 2, action_controller.developers(true).size
866
+ end
867
+
756
868
  def test_adding_multiple
757
- aredridel = Developer.new("name" => "Aridridel")
869
+ aredridel = Developer.new("name" => "Aredridel")
758
870
  aredridel.save
759
871
  aredridel.projects.reload
760
872
  aredridel.projects.push(Project.find(1), Project.find(2))
@@ -763,7 +875,7 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
763
875
  end
764
876
 
765
877
  def test_adding_a_collection
766
- aredridel = Developer.new("name" => "Aridridel")
878
+ aredridel = Developer.new("name" => "Aredridel")
767
879
  aredridel.save
768
880
  aredridel.projects.reload
769
881
  aredridel.projects.concat([Project.find(1), Project.find(2)])
@@ -774,7 +886,7 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
774
886
  def test_habtm_adding_before_save
775
887
  no_of_devels = Developer.count
776
888
  no_of_projects = Project.count
777
- aredridel = Developer.new("name" => "Aridridel")
889
+ aredridel = Developer.new("name" => "Aredridel")
778
890
  aredridel.projects.concat([Project.find(1), p = Project.new("name" => "Projekt")])
779
891
  assert aredridel.new_record?
780
892
  assert p.new_record?
@@ -790,6 +902,7 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
790
902
  no_of_devels = Developer.count
791
903
  no_of_projects = Project.count
792
904
  now = Date.today
905
+ sqlnow = Time.now.strftime("%Y/%m/%d 00:00:00")
793
906
  ken = Developer.new("name" => "Ken")
794
907
  ken.projects.push_with_attributes( Project.find(1), :joined_on => now )
795
908
  p = Project.new("name" => "Foomatic")
@@ -804,7 +917,13 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
804
917
  assert_equal 2, ken.projects(true).size
805
918
 
806
919
  kenReloaded = Developer.find_by_name 'Ken'
807
- kenReloaded.projects.each { |prj| assert_equal(now.to_s, prj.joined_on.to_s) }
920
+ # SQL Server doesn't have a separate column type just for dates,
921
+ # so the time is in the string and incorrectly formatted
922
+ if ActiveRecord::ConnectionAdapters.const_defined? :SQLServerAdapter and ActiveRecord::Base.connection.instance_of?(ActiveRecord::ConnectionAdapters::SQLServerAdapter)
923
+ kenReloaded.projects.each { |prj| assert_equal(sqlnow, prj.joined_on.to_s) }
924
+ else
925
+ kenReloaded.projects.each { |prj| assert_equal(now.to_s, prj.joined_on.to_s) }
926
+ end
808
927
  end
809
928
 
810
929
  def test_build
@@ -825,16 +944,16 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
825
944
  end
826
945
 
827
946
  def test_uniq_after_the_fact
828
- @developers["jamis"].find.projects << @projects["active_record"].find
829
- @developers["jamis"].find.projects << @projects["active_record"].find
830
- assert_equal 3, @developers["jamis"].find.projects.size
831
- assert_equal 1, @developers["jamis"].find.projects.uniq.size
947
+ developers(:jamis).projects << projects(:active_record)
948
+ developers(:jamis).projects << projects(:active_record)
949
+ assert_equal 3, developers(:jamis).projects.size
950
+ assert_equal 1, developers(:jamis).projects.uniq.size
832
951
  end
833
952
 
834
953
  def test_uniq_before_the_fact
835
- @projects["active_record"].find.developers << @developers["jamis"].find
836
- @projects["active_record"].find.developers << @developers["david"].find
837
- assert_equal 2, @projects["active_record"].find.developers.size
954
+ projects(:active_record).developers << developers(:jamis)
955
+ projects(:active_record).developers << developers(:david)
956
+ assert_equal 2, projects(:active_record, :reload).developers.size
838
957
  end
839
958
 
840
959
  def test_deleting
@@ -854,11 +973,30 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
854
973
  def test_deleting_array
855
974
  david = Developer.find(1)
856
975
  david.projects.reload
857
- david.projects.delete(Project.find_all)
976
+ david.projects.delete(Project.find(:all))
858
977
  assert_equal 0, david.projects.size
859
978
  assert_equal 0, david.projects(true).size
860
979
  end
861
980
 
981
+ def test_deleting_with_sql
982
+ david = Developer.find(1)
983
+ active_record = Project.find(1)
984
+ active_record.developers.reload
985
+ assert_equal 2, active_record.developers_by_sql.size
986
+
987
+ active_record.developers_by_sql.delete(david)
988
+ assert_equal 1, active_record.developers_by_sql(true).size
989
+ end
990
+
991
+ def test_deleting_array_with_sql
992
+ active_record = Project.find(1)
993
+ active_record.developers.reload
994
+ assert_equal 2, active_record.developers_by_sql.size
995
+
996
+ active_record.developers_by_sql.delete(Developer.find(:all))
997
+ assert_equal 0, active_record.developers_by_sql(true).size
998
+ end
999
+
862
1000
  def test_deleting_all
863
1001
  david = Developer.find(1)
864
1002
  david.projects.reload
@@ -873,7 +1011,13 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
873
1011
  end
874
1012
 
875
1013
  def test_additional_columns_from_join_table
876
- assert_equal Date.new(2004, 10, 10).to_s, Developer.find(1).projects.first.joined_on.to_s
1014
+ # SQL Server doesn't have a separate column type just for dates,
1015
+ # so the time is in the string and incorrectly formatted
1016
+ if ActiveRecord::ConnectionAdapters.const_defined? :SQLServerAdapter and ActiveRecord::Base.connection.instance_of?(ActiveRecord::ConnectionAdapters::SQLServerAdapter)
1017
+ assert_equal Time.mktime(2004, 10, 10).strftime("%Y/%m/%d 00:00:00"), Developer.find(1).projects.first.joined_on.to_s
1018
+ else
1019
+ assert_equal Date.new(2004, 10, 10).to_s, Developer.find(1).projects.first.joined_on.to_s
1020
+ end
877
1021
  end
878
1022
 
879
1023
  def test_destroy_all
@@ -886,35 +1030,93 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
886
1030
  end
887
1031
 
888
1032
  def test_rich_association
889
- @jamis = @developers["jamis"].find
890
- @jamis.projects.push_with_attributes(@projects["action_controller"].find, :joined_on => Date.today)
891
- assert_equal Date.today.to_s, @jamis.projects.select { |p| p.name == @projects["action_controller"]["name"] }.first.joined_on.to_s
892
- assert_equal Date.today.to_s, @developers["jamis"].find.projects.select { |p| p.name == @projects["action_controller"]["name"] }.first.joined_on.to_s
1033
+ jamis = developers(:jamis)
1034
+ jamis.projects.push_with_attributes(projects(:action_controller), :joined_on => Date.today)
1035
+ # SQL Server doesn't have a separate column type just for dates,
1036
+ # so the time is in the string and incorrectly formatted
1037
+ if ActiveRecord::ConnectionAdapters.const_defined? :SQLServerAdapter and ActiveRecord::Base.connection.instance_of?(ActiveRecord::ConnectionAdapters::SQLServerAdapter)
1038
+ assert_equal Time.now.strftime("%Y/%m/%d 00:00:00"), jamis.projects.select { |p| p.name == projects(:action_controller).name }.first.joined_on.to_s
1039
+ assert_equal Time.now.strftime("%Y/%m/%d 00:00:00"), developers(:jamis).projects.select { |p| p.name == projects(:action_controller).name }.first.joined_on.to_s
1040
+ else
1041
+ assert_equal Date.today.to_s, jamis.projects.select { |p| p.name == projects(:action_controller).name }.first.joined_on.to_s
1042
+ assert_equal Date.today.to_s, developers(:jamis).projects.select { |p| p.name == projects(:action_controller).name }.first.joined_on.to_s
1043
+ end
893
1044
  end
894
1045
 
895
1046
  def test_associations_with_conditions
896
- assert_equal 2, @projects["active_record"].find.developers.size
897
- assert_equal 1, @projects["active_record"].find.developers_named_david.size
898
-
899
- @projects["active_record"].find.developers_named_david.clear
900
- assert_equal 1, @projects["active_record"].find.developers.size
1047
+ assert_equal 2, projects(:active_record).developers.size
1048
+ assert_equal 1, projects(:active_record).developers_named_david.size
1049
+
1050
+ assert_equal developers(:david), projects(:active_record).developers_named_david.find(developers(:david).id)
1051
+ assert_equal developers(:david), projects(:active_record).salaried_developers.find(developers(:david).id)
1052
+
1053
+ projects(:active_record).developers_named_david.clear
1054
+ assert_equal 1, projects(:active_record, :reload).developers.size
901
1055
  end
902
1056
 
903
1057
  def test_find_in_association
904
1058
  # Using sql
905
- assert_equal @developers["david"].find, @projects["active_record"].find.developers.find(@developers["david"]["id"]), "SQL find"
1059
+ assert_equal developers(:david), projects(:active_record).developers.find(developers(:david).id), "SQL find"
906
1060
 
907
1061
  # Using ruby
908
- @active_record = @projects["active_record"].find
909
- @active_record.developers.reload
910
- assert_equal @developers["david"].find, @active_record.developers.find(@developers["david"]["id"]), "Ruby find"
1062
+ active_record = projects(:active_record)
1063
+ active_record.developers.reload
1064
+ assert_equal developers(:david), active_record.developers.find(developers(:david).id), "Ruby find"
1065
+ end
1066
+
1067
+ def test_new_with_values_in_collection
1068
+ jamis = DeveloperForProjectWithAfterCreateHook.find_by_name('Jamis')
1069
+ david = DeveloperForProjectWithAfterCreateHook.find_by_name('David')
1070
+ project = ProjectWithAfterCreateHook.new(:name => "Cooking with Bertie")
1071
+ project.developers << jamis
1072
+ project.save!
1073
+ project.reload
1074
+
1075
+ assert project.developers.include?(jamis)
1076
+ assert project.developers.include?(david)
911
1077
  end
912
1078
 
913
1079
  def xtest_find_in_association_with_options
914
- developers = @active_record.developers.find(:all)
1080
+ developers = projects(:active_record).developers.find(:all)
915
1081
  assert_equal 2, developers.size
916
1082
 
917
- assert_equal @david, @active_record.developers.find(:first, :conditions => "salary < 10000")
918
- assert_equal @jamis, @active_record.developers.find(:first, :order => "salary DESC")
1083
+ assert_equal developers(:david), projects(:active_record).developers.find(:first, :conditions => "salary < 10000")
1084
+ assert_equal developers(:jamis), projects(:active_record).developers.find(:first, :order => "salary DESC")
919
1085
  end
920
- end
1086
+
1087
+ def test_replace_with_less
1088
+ david = developers(:david)
1089
+ david.projects = [projects(:action_controller)]
1090
+ assert david.save
1091
+ assert_equal 1, david.projects.length
1092
+ end
1093
+
1094
+ def test_replace_with_new
1095
+ david = developers(:david)
1096
+ david.projects = [projects(:action_controller), Project.new("name" => "ActionWebSearch")]
1097
+ david.save
1098
+ assert_equal 2, david.projects.length
1099
+ assert !david.projects.include?(projects(:active_record))
1100
+ end
1101
+
1102
+ def test_replace_on_new_object
1103
+ new_developer = Developer.new("name" => "Matz")
1104
+ new_developer.projects = [projects(:action_controller), Project.new("name" => "ActionWebSearch")]
1105
+ new_developer.save
1106
+ assert_equal 2, new_developer.projects.length
1107
+ end
1108
+
1109
+ def test_consider_type
1110
+ developer = Developer.find(:first)
1111
+ special_project = SpecialProject.create("name" => "Special Project")
1112
+
1113
+ other_project = developer.projects.first
1114
+ developer.special_projects << special_project
1115
+ developer.reload
1116
+
1117
+ assert developer.projects.include?(special_project)
1118
+ assert developer.special_projects.include?(special_project)
1119
+ assert !developer.special_projects.include?(other_project)
1120
+ end
1121
+
1122
+ end