activerecord 1.15.6 → 2.0.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 (185) hide show
  1. data/CHANGELOG +2454 -34
  2. data/README +1 -1
  3. data/RUNNING_UNIT_TESTS +3 -34
  4. data/Rakefile +98 -77
  5. data/install.rb +1 -1
  6. data/lib/active_record.rb +13 -22
  7. data/lib/active_record/aggregations.rb +38 -49
  8. data/lib/active_record/associations.rb +452 -333
  9. data/lib/active_record/associations/association_collection.rb +66 -20
  10. data/lib/active_record/associations/association_proxy.rb +9 -8
  11. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +46 -51
  12. data/lib/active_record/associations/has_many_association.rb +21 -57
  13. data/lib/active_record/associations/has_many_through_association.rb +38 -18
  14. data/lib/active_record/associations/has_one_association.rb +30 -14
  15. data/lib/active_record/attribute_methods.rb +253 -0
  16. data/lib/active_record/base.rb +719 -494
  17. data/lib/active_record/calculations.rb +62 -63
  18. data/lib/active_record/callbacks.rb +57 -83
  19. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +38 -9
  20. data/lib/active_record/connection_adapters/abstract/database_statements.rb +56 -15
  21. data/lib/active_record/connection_adapters/abstract/query_cache.rb +87 -0
  22. data/lib/active_record/connection_adapters/abstract/quoting.rb +23 -12
  23. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +191 -62
  24. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +37 -34
  25. data/lib/active_record/connection_adapters/abstract_adapter.rb +28 -17
  26. data/lib/active_record/connection_adapters/mysql_adapter.rb +119 -37
  27. data/lib/active_record/connection_adapters/postgresql_adapter.rb +473 -210
  28. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +34 -0
  29. data/lib/active_record/connection_adapters/sqlite_adapter.rb +91 -107
  30. data/lib/active_record/fixtures.rb +503 -113
  31. data/lib/active_record/locking/optimistic.rb +72 -34
  32. data/lib/active_record/migration.rb +80 -57
  33. data/lib/active_record/observer.rb +13 -10
  34. data/lib/active_record/query_cache.rb +16 -57
  35. data/lib/active_record/reflection.rb +35 -38
  36. data/lib/active_record/schema.rb +5 -5
  37. data/lib/active_record/schema_dumper.rb +35 -13
  38. data/lib/active_record/serialization.rb +98 -0
  39. data/lib/active_record/serializers/json_serializer.rb +71 -0
  40. data/lib/active_record/{xml_serialization.rb → serializers/xml_serializer.rb} +90 -83
  41. data/lib/active_record/timestamp.rb +20 -21
  42. data/lib/active_record/transactions.rb +39 -43
  43. data/lib/active_record/validations.rb +256 -107
  44. data/lib/active_record/version.rb +3 -3
  45. data/lib/activerecord.rb +1 -0
  46. data/test/aaa_create_tables_test.rb +15 -2
  47. data/test/abstract_unit.rb +24 -17
  48. data/test/active_schema_test_mysql.rb +20 -8
  49. data/test/adapter_test.rb +23 -5
  50. data/test/adapter_test_sqlserver.rb +15 -1
  51. data/test/aggregations_test.rb +16 -1
  52. data/test/all.sh +2 -2
  53. data/test/associations/ar_joins_test.rb +0 -0
  54. data/test/associations/callbacks_test.rb +51 -30
  55. data/test/associations/cascaded_eager_loading_test.rb +1 -29
  56. data/test/associations/eager_singularization_test.rb +145 -0
  57. data/test/associations/eager_test.rb +42 -6
  58. data/test/associations/extension_test.rb +6 -1
  59. data/test/associations/inner_join_association_test.rb +88 -0
  60. data/test/associations/join_model_test.rb +47 -16
  61. data/test/associations_test.rb +449 -226
  62. data/test/attribute_methods_test.rb +97 -0
  63. data/test/base_test.rb +251 -105
  64. data/test/binary_test.rb +22 -27
  65. data/test/calculations_test.rb +37 -5
  66. data/test/callbacks_test.rb +23 -0
  67. data/test/connection_test_firebird.rb +2 -2
  68. data/test/connection_test_mysql.rb +30 -0
  69. data/test/connections/native_mysql/connection.rb +3 -0
  70. data/test/connections/native_sqlite/connection.rb +5 -14
  71. data/test/connections/native_sqlite3/connection.rb +5 -14
  72. data/test/connections/native_sqlite3/in_memory_connection.rb +1 -1
  73. data/test/{copy_table_sqlite.rb → copy_table_test_sqlite.rb} +8 -3
  74. data/test/datatype_test_postgresql.rb +178 -27
  75. data/test/{empty_date_time_test.rb → date_time_test.rb} +13 -1
  76. data/test/defaults_test.rb +8 -1
  77. data/test/deprecated_finder_test.rb +7 -128
  78. data/test/finder_test.rb +192 -54
  79. data/test/fixtures/all/developers.yml +0 -0
  80. data/test/fixtures/all/people.csv +0 -0
  81. data/test/fixtures/all/tasks.yml +0 -0
  82. data/test/fixtures/author.rb +12 -5
  83. data/test/fixtures/binaries.yml +130 -435
  84. data/test/fixtures/category.rb +6 -0
  85. data/test/fixtures/company.rb +8 -1
  86. data/test/fixtures/computer.rb +1 -0
  87. data/test/fixtures/contact.rb +16 -0
  88. data/test/fixtures/customer.rb +2 -2
  89. data/test/fixtures/db_definitions/db2.drop.sql +1 -0
  90. data/test/fixtures/db_definitions/db2.sql +4 -0
  91. data/test/fixtures/db_definitions/firebird.drop.sql +3 -1
  92. data/test/fixtures/db_definitions/firebird.sql +6 -0
  93. data/test/fixtures/db_definitions/frontbase.drop.sql +1 -0
  94. data/test/fixtures/db_definitions/frontbase.sql +5 -0
  95. data/test/fixtures/db_definitions/openbase.sql +41 -25
  96. data/test/fixtures/db_definitions/oracle.drop.sql +2 -0
  97. data/test/fixtures/db_definitions/oracle.sql +5 -0
  98. data/test/fixtures/db_definitions/postgresql.drop.sql +7 -0
  99. data/test/fixtures/db_definitions/postgresql.sql +87 -58
  100. data/test/fixtures/db_definitions/postgresql2.sql +1 -2
  101. data/test/fixtures/db_definitions/schema.rb +280 -0
  102. data/test/fixtures/db_definitions/schema2.rb +11 -0
  103. data/test/fixtures/db_definitions/sqlite.drop.sql +1 -0
  104. data/test/fixtures/db_definitions/sqlite.sql +4 -0
  105. data/test/fixtures/db_definitions/sybase.drop.sql +1 -0
  106. data/test/fixtures/db_definitions/sybase.sql +4 -0
  107. data/test/fixtures/developer.rb +10 -0
  108. data/test/fixtures/example.log +1 -0
  109. data/test/fixtures/flowers.jpg +0 -0
  110. data/test/fixtures/item.rb +7 -0
  111. data/test/fixtures/items.yml +4 -0
  112. data/test/fixtures/joke.rb +0 -3
  113. data/test/fixtures/matey.rb +4 -0
  114. data/test/fixtures/mateys.yml +4 -0
  115. data/test/fixtures/minimalistic.rb +2 -0
  116. data/test/fixtures/minimalistics.yml +2 -0
  117. data/test/fixtures/mixins.yml +2 -100
  118. data/test/fixtures/parrot.rb +13 -0
  119. data/test/fixtures/parrots.yml +27 -0
  120. data/test/fixtures/parrots_pirates.yml +7 -0
  121. data/test/fixtures/pirate.rb +5 -0
  122. data/test/fixtures/pirates.yml +9 -0
  123. data/test/fixtures/post.rb +1 -0
  124. data/test/fixtures/project.rb +3 -2
  125. data/test/fixtures/reserved_words/distinct.yml +5 -0
  126. data/test/fixtures/reserved_words/distincts_selects.yml +11 -0
  127. data/test/fixtures/reserved_words/group.yml +14 -0
  128. data/test/fixtures/reserved_words/select.yml +8 -0
  129. data/test/fixtures/reserved_words/values.yml +7 -0
  130. data/test/fixtures/ship.rb +3 -0
  131. data/test/fixtures/ships.yml +5 -0
  132. data/test/fixtures/tagging.rb +4 -0
  133. data/test/fixtures/taggings.yml +8 -1
  134. data/test/fixtures/topic.rb +13 -1
  135. data/test/fixtures/treasure.rb +4 -0
  136. data/test/fixtures/treasures.yml +10 -0
  137. data/test/fixtures_test.rb +205 -24
  138. data/test/inheritance_test.rb +7 -1
  139. data/test/json_serialization_test.rb +180 -0
  140. data/test/lifecycle_test.rb +1 -1
  141. data/test/locking_test.rb +85 -2
  142. data/test/migration_test.rb +206 -40
  143. data/test/mixin_test.rb +13 -515
  144. data/test/pk_test.rb +3 -6
  145. data/test/query_cache_test.rb +104 -0
  146. data/test/reflection_test.rb +16 -0
  147. data/test/reserved_word_test_mysql.rb +177 -0
  148. data/test/schema_dumper_test.rb +38 -3
  149. data/test/serialization_test.rb +47 -0
  150. data/test/transactions_test.rb +74 -23
  151. data/test/unconnected_test.rb +1 -1
  152. data/test/validations_test.rb +322 -32
  153. data/test/xml_serialization_test.rb +121 -44
  154. metadata +48 -41
  155. data/examples/associations.rb +0 -87
  156. data/examples/shared_setup.rb +0 -15
  157. data/examples/validation.rb +0 -85
  158. data/lib/active_record/acts/list.rb +0 -256
  159. data/lib/active_record/acts/nested_set.rb +0 -211
  160. data/lib/active_record/acts/tree.rb +0 -96
  161. data/lib/active_record/connection_adapters/db2_adapter.rb +0 -228
  162. data/lib/active_record/connection_adapters/firebird_adapter.rb +0 -728
  163. data/lib/active_record/connection_adapters/frontbase_adapter.rb +0 -861
  164. data/lib/active_record/connection_adapters/openbase_adapter.rb +0 -350
  165. data/lib/active_record/connection_adapters/oracle_adapter.rb +0 -690
  166. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +0 -591
  167. data/lib/active_record/connection_adapters/sybase_adapter.rb +0 -662
  168. data/lib/active_record/deprecated_associations.rb +0 -104
  169. data/lib/active_record/deprecated_finders.rb +0 -44
  170. data/lib/active_record/vendor/simple.rb +0 -693
  171. data/lib/active_record/wrappers/yaml_wrapper.rb +0 -15
  172. data/lib/active_record/wrappings.rb +0 -58
  173. data/test/connections/native_sqlserver/connection.rb +0 -23
  174. data/test/connections/native_sqlserver_odbc/connection.rb +0 -25
  175. data/test/deprecated_associations_test.rb +0 -396
  176. data/test/fixtures/db_definitions/mysql.drop.sql +0 -32
  177. data/test/fixtures/db_definitions/mysql.sql +0 -234
  178. data/test/fixtures/db_definitions/mysql2.drop.sql +0 -2
  179. data/test/fixtures/db_definitions/mysql2.sql +0 -5
  180. data/test/fixtures/db_definitions/sqlserver.drop.sql +0 -34
  181. data/test/fixtures/db_definitions/sqlserver.sql +0 -243
  182. data/test/fixtures/db_definitions/sqlserver2.drop.sql +0 -2
  183. data/test/fixtures/db_definitions/sqlserver2.sql +0 -5
  184. data/test/fixtures/mixin.rb +0 -63
  185. data/test/mixin_nested_set_test.rb +0 -196
@@ -7,13 +7,16 @@ require 'fixtures/reply'
7
7
  require 'fixtures/computer'
8
8
  require 'fixtures/customer'
9
9
  require 'fixtures/order'
10
+ require 'fixtures/categorization'
10
11
  require 'fixtures/category'
11
12
  require 'fixtures/post'
12
13
  require 'fixtures/author'
14
+ require 'fixtures/comment'
15
+ require 'fixtures/tag'
16
+ require 'fixtures/tagging'
13
17
  require 'fixtures/person'
14
18
  require 'fixtures/reader'
15
19
 
16
-
17
20
  class AssociationsTest < Test::Unit::TestCase
18
21
  fixtures :accounts, :companies, :developers, :projects, :developers_projects,
19
22
  :computers
@@ -37,18 +40,12 @@ class AssociationsTest < Test::Unit::TestCase
37
40
  firm.save
38
41
  firm.clients.each {|c|} # forcing to load all clients
39
42
  assert firm.clients.empty?, "New firm shouldn't have client objects"
40
- assert_deprecated do
41
- assert !firm.has_clients?, "New firm shouldn't have clients"
42
- end
43
43
  assert_equal 0, firm.clients.size, "New firm should have 0 clients"
44
44
 
45
45
  client = Client.new("name" => "TheClient.com", "firm_id" => firm.id)
46
46
  client.save
47
47
 
48
48
  assert firm.clients.empty?, "New firm should have cached no client objects"
49
- assert_deprecated do
50
- assert !firm.has_clients?, "New firm should have cached a no-clients response"
51
- end
52
49
  assert_equal 0, firm.clients.size, "New firm should have cached 0 clients count"
53
50
 
54
51
  assert !firm.clients(true).empty?, "New firm should have reloaded client objects"
@@ -77,7 +74,7 @@ class AssociationsTest < Test::Unit::TestCase
77
74
  end
78
75
 
79
76
  class AssociationProxyTest < Test::Unit::TestCase
80
- fixtures :authors, :posts, :developers, :projects, :developers_projects
77
+ fixtures :authors, :posts, :categorizations, :categories, :developers, :projects, :developers_projects
81
78
 
82
79
  def test_proxy_accessors
83
80
  welcome = posts(:welcome)
@@ -91,13 +88,28 @@ class AssociationProxyTest < Test::Unit::TestCase
91
88
  assert_equal david.class.reflect_on_association(:posts), david.posts.proxy_reflection
92
89
  david.posts.first # force load target
93
90
  assert_equal david.posts, david.posts.proxy_target
94
-
91
+
95
92
  assert_equal david, david.posts_with_extension.testing_proxy_owner
96
93
  assert_equal david.class.reflect_on_association(:posts_with_extension), david.posts_with_extension.testing_proxy_reflection
97
94
  david.posts_with_extension.first # force load target
98
95
  assert_equal david.posts_with_extension, david.posts_with_extension.testing_proxy_target
99
96
  end
100
97
 
98
+ def test_push_does_not_load_target
99
+ david = authors(:david)
100
+
101
+ david.categories << categories(:technology)
102
+ assert !david.categories.loaded?
103
+ assert david.categories.include?(categories(:technology))
104
+ end
105
+
106
+ def test_push_does_not_lose_additions_to_new_record
107
+ josh = Author.new(:name => "Josh")
108
+ josh.posts << Post.new(:title => "New on Edge", :body => "More cool stuff!")
109
+ assert josh.posts.loaded?
110
+ assert_equal 1, josh.posts.size
111
+ end
112
+
101
113
  def test_save_on_parent_does_not_load_target
102
114
  david = developers(:david)
103
115
 
@@ -110,15 +122,32 @@ class AssociationProxyTest < Test::Unit::TestCase
110
122
  developer = Developer.create :name => "Bryan", :salary => 50_000
111
123
  assert_equal 1, developer.reload.audit_logs.size
112
124
  end
125
+
126
+ def test_failed_reload_returns_nil
127
+ p = setup_dangling_association
128
+ assert_nil p.author.reload
129
+ end
130
+
131
+ def test_failed_reset_returns_nil
132
+ p = setup_dangling_association
133
+ assert_nil p.author.reset
134
+ end
135
+
136
+ def setup_dangling_association
137
+ josh = Author.create(:name => "Josh")
138
+ p = Post.create(:title => "New on Edge", :body => "More cool stuff!", :author => josh)
139
+ josh.destroy
140
+ p
141
+ end
113
142
  end
114
143
 
115
144
  class HasOneAssociationsTest < Test::Unit::TestCase
116
145
  fixtures :accounts, :companies, :developers, :projects, :developers_projects
117
-
146
+
118
147
  def setup
119
148
  Account.destroyed_account_ids.clear
120
149
  end
121
-
150
+
122
151
  def test_has_one
123
152
  assert_equal companies(:first_firm).account, Account.find(1)
124
153
  assert_equal Account.find(1).credit_limit, companies(:first_firm).account.credit_limit
@@ -166,22 +195,22 @@ class HasOneAssociationsTest < Test::Unit::TestCase
166
195
  apple.account = citibank
167
196
  assert_equal apple.id, citibank.firm_id
168
197
  end
169
-
198
+
170
199
  def test_natural_assignment_to_nil
171
200
  old_account_id = companies(:first_firm).account.id
172
201
  companies(:first_firm).account = nil
173
202
  companies(:first_firm).save
174
203
  assert_nil companies(:first_firm).account
175
204
  # account is dependent, therefore is destroyed when reference to owner is lost
176
- assert_raises(ActiveRecord::RecordNotFound) { Account.find(old_account_id) }
205
+ assert_raises(ActiveRecord::RecordNotFound) { Account.find(old_account_id) }
177
206
  end
178
-
207
+
179
208
  def test_assignment_without_replacement
180
209
  apple = Firm.create("name" => "Apple")
181
210
  citibank = Account.create("credit_limit" => 10)
182
211
  apple.account = citibank
183
212
  assert_equal apple.id, citibank.firm_id
184
-
213
+
185
214
  hsbc = apple.build_account({ :credit_limit => 20}, false)
186
215
  assert_equal apple.id, hsbc.firm_id
187
216
  hsbc.save
@@ -198,7 +227,7 @@ class HasOneAssociationsTest < Test::Unit::TestCase
198
227
  citibank = Account.create("credit_limit" => 10)
199
228
  apple.account = citibank
200
229
  assert_equal apple.id, citibank.firm_id
201
-
230
+
202
231
  hsbc = apple.create_account({:credit_limit => 10}, false)
203
232
  assert_equal apple.id, hsbc.firm_id
204
233
  hsbc.save
@@ -218,12 +247,6 @@ class HasOneAssociationsTest < Test::Unit::TestCase
218
247
  assert_equal [account_id], Account.destroyed_account_ids[firm.id]
219
248
  end
220
249
 
221
- def test_deprecated_exclusive_dependence
222
- assert_deprecated(/:exclusively_dependent.*:dependent => :delete_all/) do
223
- Firm.has_many :deprecated_exclusively_dependent_clients, :class_name => 'Client', :exclusively_dependent => true
224
- end
225
- end
226
-
227
250
  def test_exclusive_dependence
228
251
  num_accounts = Account.count
229
252
 
@@ -271,9 +294,9 @@ class HasOneAssociationsTest < Test::Unit::TestCase
271
294
  end
272
295
 
273
296
  def test_create_association
274
- firm = Firm.new("name" => "GlobalMegaCorp")
275
- firm.save
276
- assert_equal firm.create_account("credit_limit" => 1000), firm.account
297
+ firm = Firm.create(:name => "GlobalMegaCorp")
298
+ account = firm.create_account(:credit_limit => 1000)
299
+ assert_equal account, firm.reload.account
277
300
  end
278
301
 
279
302
  def test_build
@@ -311,7 +334,7 @@ class HasOneAssociationsTest < Test::Unit::TestCase
311
334
  def test_failing_build_association
312
335
  firm = Firm.new("name" => "GlobalMegaCorp")
313
336
  firm.save
314
-
337
+
315
338
  firm.account = account = Account.new
316
339
  assert_equal account, firm.account
317
340
  assert !account.save
@@ -339,6 +362,13 @@ class HasOneAssociationsTest < Test::Unit::TestCase
339
362
  firm.destroy
340
363
  end
341
364
 
365
+ def test_dependence_with_missing_association_and_nullify
366
+ Account.destroy_all
367
+ firm = DependentFirm.find(:first)
368
+ assert firm.account.nil?
369
+ firm.destroy
370
+ end
371
+
342
372
  def test_assignment_before_parent_saved
343
373
  firm = Firm.new("name" => "GlobalMegaCorp")
344
374
  firm.account = a = Account.find(1)
@@ -395,21 +425,14 @@ class HasOneAssociationsTest < Test::Unit::TestCase
395
425
  firm.account = Account.find(:first).clone
396
426
  assert_queries(2) { firm.save! }
397
427
  end
398
-
428
+
399
429
  def test_save_still_works_after_accessing_nil_has_one
400
430
  jp = Company.new :name => 'Jaded Pixel'
401
431
  jp.dummy_account.nil?
402
-
432
+
403
433
  assert_nothing_raised do
404
434
  jp.save!
405
- end
406
- end
407
-
408
- def test_deprecated_inferred_foreign_key
409
- assert_not_deprecated { Company.belongs_to :firm }
410
- assert_not_deprecated { Company.belongs_to :client, :foreign_key => "firm_id" }
411
- assert_not_deprecated { Company.belongs_to :firm, :class_name => "Firm", :foreign_key => "client_of" }
412
- assert_deprecated("inferred foreign_key name") { Company.belongs_to :client, :class_name => "Firm" }
435
+ end
413
436
  end
414
437
 
415
438
  end
@@ -417,7 +440,7 @@ end
417
440
 
418
441
  class HasManyAssociationsTest < Test::Unit::TestCase
419
442
  fixtures :accounts, :companies, :developers, :projects,
420
- :developers_projects, :topics
443
+ :developers_projects, :topics, :authors, :comments
421
444
 
422
445
  def setup
423
446
  Client.destroyed_client_ids.clear
@@ -436,9 +459,7 @@ class HasManyAssociationsTest < Test::Unit::TestCase
436
459
  end
437
460
 
438
461
  def test_counting_with_single_conditions
439
- assert_deprecated 'count' do
440
- assert_equal 2, Firm.find(:first).plain_clients.count('1=1')
441
- end
462
+ assert_equal 2, Firm.find(:first).plain_clients.count(:conditions => '1=1')
442
463
  end
443
464
 
444
465
  def test_counting_with_single_hash
@@ -459,6 +480,36 @@ class HasManyAssociationsTest < Test::Unit::TestCase
459
480
  assert_equal 2, companies(:first_firm).limited_clients.find(:all, :limit => nil).size
460
481
  end
461
482
 
483
+ def test_dynamic_find_should_respect_association_order
484
+ assert_equal companies(:second_client), companies(:first_firm).clients_sorted_desc.find(:first, :conditions => "type = 'Client'")
485
+ assert_equal companies(:second_client), companies(:first_firm).clients_sorted_desc.find_by_type('Client')
486
+ end
487
+
488
+ def test_dynamic_find_order_should_override_association_order
489
+ assert_equal companies(:first_client), companies(:first_firm).clients_sorted_desc.find(:first, :conditions => "type = 'Client'", :order => 'id')
490
+ assert_equal companies(:first_client), companies(:first_firm).clients_sorted_desc.find_by_type('Client', :order => 'id')
491
+ end
492
+
493
+ def test_dynamic_find_all_should_respect_association_order
494
+ assert_equal [companies(:second_client), companies(:first_client)], companies(:first_firm).clients_sorted_desc.find(:all, :conditions => "type = 'Client'")
495
+ assert_equal [companies(:second_client), companies(:first_client)], companies(:first_firm).clients_sorted_desc.find_all_by_type('Client')
496
+ end
497
+
498
+ def test_dynamic_find_all_order_should_override_association_order
499
+ assert_equal [companies(:first_client), companies(:second_client)], companies(:first_firm).clients_sorted_desc.find(:all, :conditions => "type = 'Client'", :order => 'id')
500
+ assert_equal [companies(:first_client), companies(:second_client)], companies(:first_firm).clients_sorted_desc.find_all_by_type('Client', :order => 'id')
501
+ end
502
+
503
+ def test_dynamic_find_all_should_respect_association_limit
504
+ assert_equal 1, companies(:first_firm).limited_clients.find(:all, :conditions => "type = 'Client'").length
505
+ assert_equal 1, companies(:first_firm).limited_clients.find_all_by_type('Client').length
506
+ end
507
+
508
+ def test_dynamic_find_all_limit_should_override_association_limit
509
+ assert_equal 2, companies(:first_firm).limited_clients.find(:all, :conditions => "type = 'Client'", :limit => 9_000).length
510
+ assert_equal 2, companies(:first_firm).limited_clients.find_all_by_type('Client', :limit => 9_000).length
511
+ end
512
+
462
513
  def test_triple_equality
463
514
  assert !(Array === Firm.find(:first).clients)
464
515
  assert Firm.find(:first).clients === Array
@@ -495,13 +546,15 @@ class HasManyAssociationsTest < Test::Unit::TestCase
495
546
 
496
547
  def test_counting_using_sql
497
548
  assert_equal 1, Firm.find(:first).clients_using_counter_sql.size
549
+ assert Firm.find(:first).clients_using_counter_sql.any?
498
550
  assert_equal 0, Firm.find(:first).clients_using_zero_counter_sql.size
551
+ assert !Firm.find(:first).clients_using_zero_counter_sql.any?
499
552
  end
500
553
 
501
554
  def test_counting_non_existant_items_using_sql
502
555
  assert_equal 0, Firm.find(:first).no_clients_using_counter_sql.size
503
556
  end
504
-
557
+
505
558
  def test_belongs_to_sanity
506
559
  c = Client.new
507
560
  assert_nil c.firm
@@ -536,45 +589,47 @@ class HasManyAssociationsTest < Test::Unit::TestCase
536
589
  assert_raises(ActiveRecord::RecordNotFound) { firm.clients.find(2, 99) }
537
590
  end
538
591
 
592
+ def test_find_string_ids_when_using_finder_sql
593
+ firm = Firm.find(:first)
594
+
595
+ client = firm.clients_using_finder_sql.find("2")
596
+ assert_kind_of Client, client
597
+
598
+ client_ary = firm.clients_using_finder_sql.find(["2"])
599
+ assert_kind_of Array, client_ary
600
+ assert_equal client, client_ary.first
601
+
602
+ client_ary = firm.clients_using_finder_sql.find("2", "3")
603
+ assert_kind_of Array, client_ary
604
+ assert_equal 2, client_ary.size
605
+ assert client_ary.include?(client)
606
+ end
607
+
539
608
  def test_find_all
540
- assert_deprecated 'find_all' do
541
- firm = Firm.find_first
542
- assert_equal firm.clients, firm.clients.find_all
543
- assert_equal 2, firm.clients.find(:all, :conditions => "#{QUOTED_TYPE} = 'Client'").length
544
- assert_equal 1, firm.clients.find(:all, :conditions => "name = 'Summit'").length
545
- end
609
+ firm = Firm.find(:first)
610
+ assert_equal 2, firm.clients.find(:all, :conditions => "#{QUOTED_TYPE} = 'Client'").length
611
+ assert_equal 1, firm.clients.find(:all, :conditions => "name = 'Summit'").length
546
612
  end
547
613
 
548
614
  def test_find_all_sanitized
549
- assert_deprecated 'find_all' do
550
- firm = Firm.find_first
551
- assert_equal firm.clients.find_all("name = 'Summit'"), firm.clients.find_all(["name = '%s'", "Summit"])
552
- summit = firm.clients.find(:all, :conditions => "name = 'Summit'")
553
- assert_equal summit, firm.clients.find(:all, :conditions => ["name = ?", "Summit"])
554
- assert_equal summit, firm.clients.find(:all, :conditions => ["name = :name", { :name => "Summit" }])
555
- end
615
+ firm = Firm.find(:first)
616
+ summit = firm.clients.find(:all, :conditions => "name = 'Summit'")
617
+ assert_equal summit, firm.clients.find(:all, :conditions => ["name = ?", "Summit"])
618
+ assert_equal summit, firm.clients.find(:all, :conditions => ["name = :name", { :name => "Summit" }])
556
619
  end
557
620
 
558
621
  def test_find_first
559
- assert_deprecated 'find_first' do
560
- firm = Firm.find_first
561
- client2 = Client.find(2)
562
- assert_equal firm.clients.first, firm.clients.find_first
563
- assert_equal client2, firm.clients.find_first("#{QUOTED_TYPE} = 'Client'")
564
- assert_equal client2, firm.clients.find(:first, :conditions => "#{QUOTED_TYPE} = 'Client'")
565
- end
622
+ firm = Firm.find(:first)
623
+ client2 = Client.find(2)
624
+ assert_equal firm.clients.first, firm.clients.find(:first)
625
+ assert_equal client2, firm.clients.find(:first, :conditions => "#{QUOTED_TYPE} = 'Client'")
566
626
  end
567
627
 
568
628
  def test_find_first_sanitized
569
- assert_deprecated 'find_first' do
570
- firm = Firm.find_first
571
- client2 = Client.find(2)
572
- assert_deprecated(/find_first/) do
573
- assert_equal client2, firm.clients.find_first(["#{QUOTED_TYPE} = ?", "Client"])
574
- end
575
- assert_equal client2, firm.clients.find(:first, :conditions => ["#{QUOTED_TYPE} = ?", 'Client'])
576
- assert_equal client2, firm.clients.find(:first, :conditions => ["#{QUOTED_TYPE} = :type", { :type => 'Client' }])
577
- end
629
+ firm = Firm.find(:first)
630
+ client2 = Client.find(2)
631
+ assert_equal client2, firm.clients.find(:first, :conditions => ["#{QUOTED_TYPE} = ?", 'Client'])
632
+ assert_equal client2, firm.clients.find(:first, :conditions => ["#{QUOTED_TYPE} = :type", { :type => 'Client' }])
578
633
  end
579
634
 
580
635
  def test_find_in_collection
@@ -606,19 +661,39 @@ class HasManyAssociationsTest < Test::Unit::TestCase
606
661
  assert_equal 3, first_firm.plain_clients.size
607
662
  end
608
663
 
664
+ def test_create_with_bang_on_has_many_when_parent_is_new_raises
665
+ assert_raises(ActiveRecord::RecordNotSaved) do
666
+ firm = Firm.new
667
+ firm.plain_clients.create! :name=>"Whoever"
668
+ end
669
+ end
670
+
609
671
  def test_regular_create_on_has_many_when_parent_is_new_raises
610
- assert_deprecated(/.build instead/) do
672
+ assert_raises(ActiveRecord::RecordNotSaved) do
611
673
  firm = Firm.new
612
674
  firm.plain_clients.create :name=>"Whoever"
613
675
  end
614
676
  end
677
+
678
+ def test_create_with_bang_on_has_many_raises_when_record_not_saved
679
+ assert_raises(ActiveRecord::RecordInvalid) do
680
+ firm = Firm.find(:first)
681
+ firm.plain_clients.create!
682
+ end
683
+ end
684
+
685
+ def test_create_with_bang_on_habtm_when_parent_is_new_raises
686
+ assert_raises(ActiveRecord::RecordNotSaved) do
687
+ Developer.new("name" => "Aredridel").projects.create!
688
+ end
689
+ end
615
690
 
616
691
  def test_adding_a_mismatch_class
617
692
  assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << nil }
618
693
  assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << 1 }
619
694
  assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << Topic.find(1) }
620
695
  end
621
-
696
+
622
697
  def test_adding_a_collection
623
698
  force_signal37_to_load_all_clients_of_firm
624
699
  companies(:first_firm).clients_of_firm.concat([Client.new("name" => "Natural Company"), Client.new("name" => "Apple")])
@@ -629,12 +704,15 @@ class HasManyAssociationsTest < Test::Unit::TestCase
629
704
  def test_adding_before_save
630
705
  no_of_firms = Firm.count
631
706
  no_of_clients = Client.count
707
+
632
708
  new_firm = Firm.new("name" => "A New Firm, Inc")
709
+ c = Client.new("name" => "Apple")
710
+
633
711
  new_firm.clients_of_firm.push Client.new("name" => "Natural Company")
634
- new_firm.clients_of_firm << (c = Client.new("name" => "Apple"))
635
- assert new_firm.new_record?
636
- assert c.new_record?
712
+ assert_equal 1, new_firm.clients_of_firm.size
713
+ new_firm.clients_of_firm << c
637
714
  assert_equal 2, new_firm.clients_of_firm.size
715
+
638
716
  assert_equal no_of_firms, Firm.count # Firm was not saved to database.
639
717
  assert_equal no_of_clients, Client.count # Clients were not saved to database.
640
718
  assert new_firm.save
@@ -643,6 +721,7 @@ class HasManyAssociationsTest < Test::Unit::TestCase
643
721
  assert_equal new_firm, c.firm
644
722
  assert_equal no_of_firms+1, Firm.count # Firm was saved to database.
645
723
  assert_equal no_of_clients+2, Client.count # Clients were saved to database.
724
+
646
725
  assert_equal 2, new_firm.clients_of_firm.size
647
726
  assert_equal 2, new_firm.clients_of_firm(true).size
648
727
  end
@@ -692,7 +771,7 @@ class HasManyAssociationsTest < Test::Unit::TestCase
692
771
  Reply.column_names
693
772
 
694
773
  assert_equal 1, first_topic.replies.length
695
-
774
+
696
775
  assert_no_queries do
697
776
  first_topic.replies.build(:title => "Not saved", :content => "Superstars")
698
777
  assert_equal 2, first_topic.replies.size
@@ -708,11 +787,11 @@ class HasManyAssociationsTest < Test::Unit::TestCase
708
787
 
709
788
  assert_equal 1, first_firm.clients_of_firm.size
710
789
  first_firm.clients_of_firm.reset
711
-
790
+
712
791
  assert_queries(1) do
713
792
  first_firm.clients_of_firm.create(:name => "Superstars")
714
793
  end
715
-
794
+
716
795
  assert_equal 2, first_firm.clients_of_firm.size
717
796
  end
718
797
 
@@ -725,7 +804,7 @@ class HasManyAssociationsTest < Test::Unit::TestCase
725
804
  assert new_client.new_record?
726
805
  assert_equal 1, companies(:first_firm).clients_of_firm(true).size
727
806
  end
728
-
807
+
729
808
  def test_create
730
809
  force_signal37_to_load_all_clients_of_firm
731
810
  new_client = companies(:first_firm).clients_of_firm.create("name" => "Another Client")
@@ -733,18 +812,25 @@ class HasManyAssociationsTest < Test::Unit::TestCase
733
812
  assert_equal new_client, companies(:first_firm).clients_of_firm.last
734
813
  assert_equal new_client, companies(:first_firm).clients_of_firm(true).last
735
814
  end
736
-
815
+
737
816
  def test_create_many
738
817
  companies(:first_firm).clients_of_firm.create([{"name" => "Another Client"}, {"name" => "Another Client II"}])
739
818
  assert_equal 3, companies(:first_firm).clients_of_firm(true).size
740
819
  end
741
820
 
821
+ def test_find_or_initialize
822
+ the_client = companies(:first_firm).clients.find_or_initialize_by_name("Yet another client")
823
+ assert_equal companies(:first_firm).id, the_client.firm_id
824
+ assert_equal "Yet another client", the_client.name
825
+ assert the_client.new_record?
826
+ end
827
+
742
828
  def test_find_or_create
743
829
  number_of_clients = companies(:first_firm).clients.size
744
830
  the_client = companies(:first_firm).clients.find_or_create_by_name("Yet another client")
745
- assert_equal number_of_clients + 1, companies(:first_firm, :refresh).clients.size
831
+ assert_equal number_of_clients + 1, companies(:first_firm, :reload).clients.size
746
832
  assert_equal the_client, companies(:first_firm).clients.find_or_create_by_name("Yet another client")
747
- assert_equal number_of_clients + 1, companies(:first_firm, :refresh).clients.size
833
+ assert_equal number_of_clients + 1, companies(:first_firm, :reload).clients.size
748
834
  end
749
835
 
750
836
  def test_deleting
@@ -770,7 +856,7 @@ class HasManyAssociationsTest < Test::Unit::TestCase
770
856
  assert_equal 0, companies(:first_firm).clients_of_firm.size
771
857
  assert_equal 0, companies(:first_firm).clients_of_firm(true).size
772
858
  end
773
-
859
+
774
860
  def test_delete_all
775
861
  force_signal37_to_load_all_clients_of_firm
776
862
  companies(:first_firm).clients_of_firm.create("name" => "Another Client")
@@ -836,11 +922,36 @@ class HasManyAssociationsTest < Test::Unit::TestCase
836
922
 
837
923
  assert_equal 0, firm.exclusively_dependent_clients_of_firm.size
838
924
  assert_equal 0, firm.exclusively_dependent_clients_of_firm(true).size
839
- assert_equal [3], Client.destroyed_client_ids[firm.id]
925
+ # no destroy-filters should have been called
926
+ assert_equal [], Client.destroyed_client_ids[firm.id]
840
927
 
841
928
  # Should be destroyed since the association is exclusively dependent.
842
929
  assert Client.find_by_id(client_id).nil?
843
- end
930
+ end
931
+
932
+ def test_dependent_association_respects_optional_conditions_on_delete
933
+ firm = companies(:odegy)
934
+ Client.create(:client_of => firm.id, :name => "BigShot Inc.")
935
+ Client.create(:client_of => firm.id, :name => "SmallTime Inc.")
936
+ # only one of two clients is included in the association due to the :conditions key
937
+ assert_equal 2, Client.find_all_by_client_of(firm.id).size
938
+ assert_equal 1, firm.dependent_conditional_clients_of_firm.size
939
+ firm.destroy
940
+ # only the correctly associated client should have been deleted
941
+ assert_equal 1, Client.find_all_by_client_of(firm.id).size
942
+ end
943
+
944
+ def test_dependent_association_respects_optional_sanitized_conditions_on_delete
945
+ firm = companies(:odegy)
946
+ Client.create(:client_of => firm.id, :name => "BigShot Inc.")
947
+ Client.create(:client_of => firm.id, :name => "SmallTime Inc.")
948
+ # only one of two clients is included in the association due to the :conditions key
949
+ assert_equal 2, Client.find_all_by_client_of(firm.id).size
950
+ assert_equal 1, firm.dependent_sanitized_conditional_clients_of_firm.size
951
+ firm.destroy
952
+ # only the correctly associated client should have been deleted
953
+ assert_equal 1, Client.find_all_by_client_of(firm.id).size
954
+ end
844
955
 
845
956
  def test_clearing_without_initial_access
846
957
  firm = companies(:first_firm)
@@ -903,7 +1014,7 @@ class HasManyAssociationsTest < Test::Unit::TestCase
903
1014
  topic = Topic.create "title" => "neat and simple"
904
1015
  reply = topic.replies.create "title" => "neat and simple", "content" => "still digging it"
905
1016
  silly_reply = reply.replies.create "title" => "neat and simple", "content" => "ain't complaining"
906
-
1017
+
907
1018
  assert_nothing_raised { topic.destroy }
908
1019
  end
909
1020
 
@@ -928,16 +1039,16 @@ class HasManyAssociationsTest < Test::Unit::TestCase
928
1039
  def test_depends_and_nullify
929
1040
  num_accounts = Account.count
930
1041
  num_companies = Company.count
931
-
1042
+
932
1043
  core = companies(:rails_core)
933
1044
  assert_equal accounts(:rails_core_account), core.account
934
- assert_equal [companies(:leetsoft), companies(:jadedpixel)], core.companies
935
- core.destroy
1045
+ assert_equal companies(:leetsoft, :jadedpixel), core.companies
1046
+ core.destroy
936
1047
  assert_nil accounts(:rails_core_account).reload.firm_id
937
1048
  assert_nil companies(:leetsoft).reload.client_of
938
1049
  assert_nil companies(:jadedpixel).reload.client_of
939
-
940
-
1050
+
1051
+
941
1052
  assert_equal num_accounts, Account.count
942
1053
  end
943
1054
 
@@ -960,19 +1071,23 @@ class HasManyAssociationsTest < Test::Unit::TestCase
960
1071
  assert firm.save, "Could not save firm"
961
1072
  firm.reload
962
1073
  assert_equal 1, firm.clients.length
963
- end
964
-
965
-
1074
+ end
1075
+
1076
+ def test_replace_with_less_and_dependent_nullify
1077
+ num_companies = Company.count
1078
+ companies(:rails_core).companies = []
1079
+ assert_equal num_companies, Company.count
1080
+ end
1081
+
966
1082
  def test_replace_with_new
967
1083
  firm = Firm.find(:first)
968
- new_client = Client.new("name" => "New Client")
969
- firm.clients = [companies(:second_client),new_client]
1084
+ firm.clients = [companies(:second_client), Client.new("name" => "New Client")]
970
1085
  firm.save
971
1086
  firm.reload
972
1087
  assert_equal 2, firm.clients.length
973
1088
  assert !firm.clients.include?(:first_client)
974
1089
  end
975
-
1090
+
976
1091
  def test_replace_on_new_object
977
1092
  firm = Firm.new("name" => "New Firm")
978
1093
  firm.clients = [companies(:second_client), Client.new("name" => "New Client")]
@@ -981,11 +1096,11 @@ class HasManyAssociationsTest < Test::Unit::TestCase
981
1096
  assert_equal 2, firm.clients.length
982
1097
  assert firm.clients.include?(Client.find_by_name("New Client"))
983
1098
  end
984
-
1099
+
985
1100
  def test_get_ids
986
1101
  assert_equal [companies(:first_client).id, companies(:second_client).id], companies(:first_firm).client_ids
987
1102
  end
988
-
1103
+
989
1104
  def test_assign_ids
990
1105
  firm = Firm.new("name" => "Apple")
991
1106
  firm.client_ids = [companies(:first_client).id, companies(:second_client).id]
@@ -996,24 +1111,62 @@ class HasManyAssociationsTest < Test::Unit::TestCase
996
1111
  end
997
1112
 
998
1113
  def test_assign_ids_ignoring_blanks
999
- firm = Firm.new("name" => "Apple")
1114
+ firm = Firm.create!(:name => 'Apple')
1000
1115
  firm.client_ids = [companies(:first_client).id, nil, companies(:second_client).id, '']
1001
- firm.save
1002
- firm.reload
1003
- assert_equal 2, firm.clients.length
1116
+ firm.save!
1117
+
1118
+ assert_equal 2, firm.clients(true).size
1004
1119
  assert firm.clients.include?(companies(:second_client))
1005
1120
  end
1006
1121
 
1122
+ def test_get_ids_for_through
1123
+ assert_equal [comments(:eager_other_comment1).id], authors(:mary).comment_ids
1124
+ end
1125
+
1126
+ def test_assign_ids_for_through
1127
+ assert_raise(NoMethodError) { authors(:mary).comment_ids = [123] }
1128
+ end
1129
+
1130
+ def test_dynamic_find_should_respect_association_order_for_through
1131
+ assert_equal Comment.find(10), authors(:david).comments_desc.find(:first, :conditions => "comments.type = 'SpecialComment'")
1132
+ assert_equal Comment.find(10), authors(:david).comments_desc.find_by_type('SpecialComment')
1133
+ end
1134
+
1135
+ def test_dynamic_find_order_should_override_association_order_for_through
1136
+ assert_equal Comment.find(3), authors(:david).comments_desc.find(:first, :conditions => "comments.type = 'SpecialComment'", :order => 'comments.id')
1137
+ assert_equal Comment.find(3), authors(:david).comments_desc.find_by_type('SpecialComment', :order => 'comments.id')
1138
+ end
1139
+
1140
+ def test_dynamic_find_all_should_respect_association_order_for_through
1141
+ assert_equal [Comment.find(10), Comment.find(7), Comment.find(6), Comment.find(3)], authors(:david).comments_desc.find(:all, :conditions => "comments.type = 'SpecialComment'")
1142
+ assert_equal [Comment.find(10), Comment.find(7), Comment.find(6), Comment.find(3)], authors(:david).comments_desc.find_all_by_type('SpecialComment')
1143
+ end
1144
+
1145
+ def test_dynamic_find_all_order_should_override_association_order_for_through
1146
+ assert_equal [Comment.find(3), Comment.find(6), Comment.find(7), Comment.find(10)], authors(:david).comments_desc.find(:all, :conditions => "comments.type = 'SpecialComment'", :order => 'comments.id')
1147
+ assert_equal [Comment.find(3), Comment.find(6), Comment.find(7), Comment.find(10)], authors(:david).comments_desc.find_all_by_type('SpecialComment', :order => 'comments.id')
1148
+ end
1149
+
1150
+ def test_dynamic_find_all_should_respect_association_limit_for_through
1151
+ assert_equal 1, authors(:david).limited_comments.find(:all, :conditions => "comments.type = 'SpecialComment'").length
1152
+ assert_equal 1, authors(:david).limited_comments.find_all_by_type('SpecialComment').length
1153
+ end
1154
+
1155
+ def test_dynamic_find_all_order_should_override_association_limit_for_through
1156
+ assert_equal 4, authors(:david).limited_comments.find(:all, :conditions => "comments.type = 'SpecialComment'", :limit => 9_000).length
1157
+ assert_equal 4, authors(:david).limited_comments.find_all_by_type('SpecialComment', :limit => 9_000).length
1158
+ end
1159
+
1007
1160
  end
1008
1161
 
1009
1162
  class BelongsToAssociationsTest < Test::Unit::TestCase
1010
1163
  fixtures :accounts, :companies, :developers, :projects, :topics,
1011
- :developers_projects, :computers, :authors, :posts
1012
-
1164
+ :developers_projects, :computers, :authors, :posts, :tags, :taggings
1165
+
1013
1166
  def test_belongs_to
1014
1167
  Client.find(3).firm.name
1015
1168
  assert_equal companies(:first_firm).name, Client.find(3).firm.name
1016
- assert !Client.find(3).firm.nil?, "Microsoft should have a firm"
1169
+ assert !Client.find(3).firm.nil?, "Microsoft should have a firm"
1017
1170
  end
1018
1171
 
1019
1172
  def test_proxy_assignment
@@ -1066,7 +1219,7 @@ class BelongsToAssociationsTest < Test::Unit::TestCase
1066
1219
  citibank.save
1067
1220
  assert_equal apple.id, citibank.firm_id
1068
1221
  end
1069
-
1222
+
1070
1223
  def test_natural_assignment_to_nil
1071
1224
  client = Client.find(3)
1072
1225
  client.firm = nil
@@ -1074,7 +1227,7 @@ class BelongsToAssociationsTest < Test::Unit::TestCase
1074
1227
  assert_nil client.firm(true)
1075
1228
  assert_nil client.client_of
1076
1229
  end
1077
-
1230
+
1078
1231
  def test_with_different_class_name
1079
1232
  assert_equal Company.find(1).name, Company.find(3).firm_with_other_name.name
1080
1233
  assert_not_nil Company.find(3).firm_with_other_name, "Microsoft should have a firm"
@@ -1084,7 +1237,7 @@ class BelongsToAssociationsTest < Test::Unit::TestCase
1084
1237
  assert_equal Company.find(1).name, Company.find(3).firm_with_condition.name
1085
1238
  assert_not_nil Company.find(3).firm_with_condition, "Microsoft should have a firm"
1086
1239
  end
1087
-
1240
+
1088
1241
  def test_belongs_to_counter
1089
1242
  debate = Topic.create("title" => "debate")
1090
1243
  assert_equal 0, debate.send(:read_attribute, "replies_count"), "No replies yet"
@@ -1128,6 +1281,42 @@ class BelongsToAssociationsTest < Test::Unit::TestCase
1128
1281
  assert_equal 0, Topic.find(t2.id).replies.size
1129
1282
  end
1130
1283
 
1284
+ def test_belongs_to_counter_after_save
1285
+ topic = Topic.create!(:title => "monday night")
1286
+ topic.replies.create!(:title => "re: monday night", :content => "football")
1287
+ assert_equal 1, Topic.find(topic.id)[:replies_count]
1288
+
1289
+ topic.save!
1290
+ assert_equal 1, Topic.find(topic.id)[:replies_count]
1291
+ end
1292
+
1293
+ def test_belongs_to_counter_after_update_attributes
1294
+ topic = Topic.create!(:title => "37s")
1295
+ topic.replies.create!(:title => "re: 37s", :content => "rails")
1296
+ assert_equal 1, Topic.find(topic.id)[:replies_count]
1297
+
1298
+ topic.update_attributes(:title => "37signals")
1299
+ assert_equal 1, Topic.find(topic.id)[:replies_count]
1300
+ end
1301
+
1302
+ def test_belongs_to_counter_after_save
1303
+ topic = Topic.create("title" => "monday night")
1304
+ topic.replies.create("title" => "re: monday night", "content" => "football")
1305
+ assert_equal 1, Topic.find(topic.id).send(:read_attribute, "replies_count")
1306
+
1307
+ topic.save
1308
+ assert_equal 1, Topic.find(topic.id).send(:read_attribute, "replies_count")
1309
+ end
1310
+
1311
+ def test_belongs_to_counter_after_update_attributes
1312
+ topic = Topic.create("title" => "37s")
1313
+ topic.replies.create("title" => "re: 37s", "content" => "rails")
1314
+ assert_equal 1, Topic.find(topic.id).send(:read_attribute, "replies_count")
1315
+
1316
+ topic.update_attributes("title" => "37signals")
1317
+ assert_equal 1, Topic.find(topic.id).send(:read_attribute, "replies_count")
1318
+ end
1319
+
1131
1320
  def test_assignment_before_parent_saved
1132
1321
  client = Client.find(:first)
1133
1322
  apple = Firm.new("name" => "Apple")
@@ -1187,7 +1376,7 @@ class BelongsToAssociationsTest < Test::Unit::TestCase
1187
1376
  def test_counter_cache
1188
1377
  topic = Topic.create :title => "Zoom-zoom-zoom"
1189
1378
  assert_equal 0, topic[:replies_count]
1190
-
1379
+
1191
1380
  reply = Reply.create(:title => "re: zoom", :content => "speedy quick!")
1192
1381
  reply.topic = topic
1193
1382
 
@@ -1215,10 +1404,10 @@ class BelongsToAssociationsTest < Test::Unit::TestCase
1215
1404
  def test_store_two_association_with_one_save
1216
1405
  num_orders = Order.count
1217
1406
  num_customers = Customer.count
1218
- order = Order.new
1407
+ order = Order.new
1219
1408
 
1220
1409
  customer1 = order.billing = Customer.new
1221
- customer2 = order.shipping = Customer.new
1410
+ customer2 = order.shipping = Customer.new
1222
1411
  assert order.save
1223
1412
  assert_equal customer1, order.billing
1224
1413
  assert_equal customer2, order.shipping
@@ -1226,28 +1415,28 @@ class BelongsToAssociationsTest < Test::Unit::TestCase
1226
1415
  order.reload
1227
1416
 
1228
1417
  assert_equal customer1, order.billing
1229
- assert_equal customer2, order.shipping
1418
+ assert_equal customer2, order.shipping
1230
1419
 
1231
1420
  assert_equal num_orders +1, Order.count
1232
1421
  assert_equal num_customers +2, Customer.count
1233
1422
  end
1234
1423
 
1235
-
1424
+
1236
1425
  def test_store_association_in_two_relations_with_one_save
1237
1426
  num_orders = Order.count
1238
1427
  num_customers = Customer.count
1239
- order = Order.new
1240
-
1241
- customer = order.billing = order.shipping = Customer.new
1428
+ order = Order.new
1429
+
1430
+ customer = order.billing = order.shipping = Customer.new
1242
1431
  assert order.save
1243
1432
  assert_equal customer, order.billing
1244
1433
  assert_equal customer, order.shipping
1245
-
1434
+
1246
1435
  order.reload
1247
-
1436
+
1248
1437
  assert_equal customer, order.billing
1249
- assert_equal customer, order.shipping
1250
-
1438
+ assert_equal customer, order.shipping
1439
+
1251
1440
  assert_equal num_orders +1, Order.count
1252
1441
  assert_equal num_customers +1, Customer.count
1253
1442
  end
@@ -1256,46 +1445,46 @@ class BelongsToAssociationsTest < Test::Unit::TestCase
1256
1445
  num_orders = Order.count
1257
1446
  num_customers = Customer.count
1258
1447
  order = Order.create
1259
-
1260
- customer = order.billing = order.shipping = Customer.new
1448
+
1449
+ customer = order.billing = order.shipping = Customer.new
1261
1450
  assert order.save
1262
1451
  assert_equal customer, order.billing
1263
1452
  assert_equal customer, order.shipping
1264
-
1453
+
1265
1454
  order.reload
1266
-
1455
+
1267
1456
  assert_equal customer, order.billing
1268
- assert_equal customer, order.shipping
1269
-
1457
+ assert_equal customer, order.shipping
1458
+
1270
1459
  assert_equal num_orders +1, Order.count
1271
1460
  assert_equal num_customers +1, Customer.count
1272
1461
  end
1273
-
1462
+
1274
1463
  def test_store_association_in_two_relations_with_one_save_in_existing_object_with_values
1275
1464
  num_orders = Order.count
1276
1465
  num_customers = Customer.count
1277
1466
  order = Order.create
1278
-
1279
- customer = order.billing = order.shipping = Customer.new
1467
+
1468
+ customer = order.billing = order.shipping = Customer.new
1280
1469
  assert order.save
1281
1470
  assert_equal customer, order.billing
1282
1471
  assert_equal customer, order.shipping
1283
-
1472
+
1284
1473
  order.reload
1285
-
1286
- customer = order.billing = order.shipping = Customer.new
1287
-
1474
+
1475
+ customer = order.billing = order.shipping = Customer.new
1476
+
1288
1477
  assert order.save
1289
- order.reload
1290
-
1478
+ order.reload
1479
+
1291
1480
  assert_equal customer, order.billing
1292
- assert_equal customer, order.shipping
1293
-
1481
+ assert_equal customer, order.shipping
1482
+
1294
1483
  assert_equal num_orders +1, Order.count
1295
1484
  assert_equal num_customers +2, Customer.count
1296
1485
  end
1297
-
1298
-
1486
+
1487
+
1299
1488
  def test_association_assignment_sticks
1300
1489
  post = Post.find(:first)
1301
1490
 
@@ -1316,7 +1505,7 @@ class BelongsToAssociationsTest < Test::Unit::TestCase
1316
1505
  # the author id of the post should be the id we set
1317
1506
  assert_equal post.author_id, author2.id
1318
1507
  end
1319
-
1508
+
1320
1509
  end
1321
1510
 
1322
1511
 
@@ -1348,7 +1537,7 @@ end
1348
1537
 
1349
1538
  class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1350
1539
  fixtures :accounts, :companies, :categories, :posts, :categories_posts, :developers, :projects, :developers_projects
1351
-
1540
+
1352
1541
  def test_has_and_belongs_to_many
1353
1542
  david = Developer.find(1)
1354
1543
 
@@ -1368,11 +1557,11 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1368
1557
 
1369
1558
  def test_adding_single
1370
1559
  jamis = Developer.find(2)
1371
- jamis.projects.reload # causing the collection to load
1560
+ jamis.projects.reload # causing the collection to load
1372
1561
  action_controller = Project.find(2)
1373
1562
  assert_equal 1, jamis.projects.size
1374
- assert_equal 1, action_controller.developers.size
1375
-
1563
+ assert_equal 1, action_controller.developers.size
1564
+
1376
1565
  jamis.projects << action_controller
1377
1566
 
1378
1567
  assert_equal 2, jamis.projects.size
@@ -1393,8 +1582,8 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1393
1582
  assert_equal 1, jamis.projects.size
1394
1583
  assert_equal 1, action_controller.developers.size
1395
1584
 
1396
- action_controller.developers << jamis
1397
-
1585
+ action_controller.developers << jamis
1586
+
1398
1587
  assert_equal 2, jamis.projects(true).size
1399
1588
  assert_equal 2, action_controller.developers.size
1400
1589
  assert_equal 2, action_controller.developers(true).size
@@ -1444,19 +1633,7 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1444
1633
  assert_equal 1, project.access_level.to_i
1445
1634
  end
1446
1635
 
1447
- def test_adding_uses_explicit_values_on_join_table
1448
- ac = projects(:action_controller)
1449
- assert !developers(:jamis).projects.include?(ac)
1450
- assert_deprecated do
1451
- developers(:jamis).projects.push_with_attributes(ac, :access_level => 3)
1452
- end
1453
-
1454
- assert developers(:jamis, :reload).projects.include?(ac)
1455
- project = developers(:jamis).projects.detect { |p| p == ac }
1456
- assert_equal 3, project.access_level.to_i
1457
- end
1458
-
1459
- def test_hatbm_attribute_access_and_respond_to
1636
+ def test_habtm_attribute_access_and_respond_to
1460
1637
  project = developers(:jamis).projects[0]
1461
1638
  assert project.has_attribute?("name")
1462
1639
  assert project.has_attribute?("joined_on")
@@ -1465,10 +1642,12 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1465
1642
  assert project.respond_to?("name=")
1466
1643
  assert project.respond_to?("name?")
1467
1644
  assert project.respond_to?("joined_on")
1468
- assert project.respond_to?("joined_on=")
1645
+ # given that the 'join attribute' won't be persisted, I don't
1646
+ # think we should define the mutators
1647
+ #assert project.respond_to?("joined_on=")
1469
1648
  assert project.respond_to?("joined_on?")
1470
1649
  assert project.respond_to?("access_level")
1471
- assert project.respond_to?("access_level=")
1650
+ #assert project.respond_to?("access_level=")
1472
1651
  assert project.respond_to?("access_level?")
1473
1652
  end
1474
1653
 
@@ -1487,31 +1666,6 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1487
1666
  assert_equal 2, aredridel.projects(true).size
1488
1667
  end
1489
1668
 
1490
- def test_habtm_adding_before_save_with_join_attributes
1491
- no_of_devels = Developer.count
1492
- no_of_projects = Project.count
1493
- now = Date.today
1494
- ken = Developer.new("name" => "Ken")
1495
- assert_deprecated do
1496
- ken.projects.push_with_attributes( Project.find(1), :joined_on => now )
1497
- end
1498
- p = Project.new("name" => "Foomatic")
1499
- assert_deprecated do
1500
- ken.projects.push_with_attributes( p, :joined_on => now )
1501
- end
1502
- assert ken.new_record?
1503
- assert p.new_record?
1504
- assert ken.save
1505
- assert !ken.new_record?
1506
- assert_equal no_of_devels+1, Developer.count
1507
- assert_equal no_of_projects+1, Project.count
1508
- assert_equal 2, ken.projects.size
1509
- assert_equal 2, ken.projects(true).size
1510
-
1511
- kenReloaded = Developer.find_by_name 'Ken'
1512
- kenReloaded.projects.each {|prj| assert_date_from_db(now, prj.joined_on)}
1513
- end
1514
-
1515
1669
  def test_habtm_saving_multiple_relationships
1516
1670
  new_project = Project.new("name" => "Grimetime")
1517
1671
  amount_of_developers = 4
@@ -1527,8 +1681,8 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1527
1681
  end
1528
1682
 
1529
1683
  def test_habtm_unique_order_preserved
1530
- assert_equal [developers(:poor_jamis), developers(:jamis), developers(:david)], projects(:active_record).non_unique_developers
1531
- assert_equal [developers(:poor_jamis), developers(:jamis), developers(:david)], projects(:active_record).developers
1684
+ assert_equal developers(:poor_jamis, :jamis, :david), projects(:active_record).non_unique_developers
1685
+ assert_equal developers(:poor_jamis, :jamis, :david), projects(:active_record).developers
1532
1686
  end
1533
1687
 
1534
1688
  def test_build
@@ -1541,7 +1695,7 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1541
1695
  assert_equal devel.projects.last, proj
1542
1696
  assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
1543
1697
  end
1544
-
1698
+
1545
1699
  def test_build_by_new_record
1546
1700
  devel = Developer.new(:name => "Marcel", :salary => 75000)
1547
1701
  proj1 = devel.projects.build(:name => "Make bed")
@@ -1554,7 +1708,7 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1554
1708
  assert_equal devel.projects.last, proj2
1555
1709
  assert_equal Developer.find_by_name("Marcel").projects.last, proj2 # prove join table is updated
1556
1710
  end
1557
-
1711
+
1558
1712
  def test_create
1559
1713
  devel = Developer.find(1)
1560
1714
  proj = devel.projects.create("name" => "Projekt")
@@ -1562,11 +1716,11 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1562
1716
  assert !proj.new_record?
1563
1717
  assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
1564
1718
  end
1565
-
1719
+
1566
1720
  def test_create_by_new_record
1567
1721
  devel = Developer.new(:name => "Marcel", :salary => 75000)
1568
- proj1 = devel.projects.create(:name => "Make bed")
1569
- proj2 = devel.projects.create(:name => "Lie in it")
1722
+ proj1 = devel.projects.build(:name => "Make bed")
1723
+ proj2 = devel.projects.build(:name => "Lie in it")
1570
1724
  assert_equal devel.projects.last, proj2
1571
1725
  assert proj2.new_record?
1572
1726
  devel.save
@@ -1575,7 +1729,7 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1575
1729
  assert_equal devel.projects.last, proj2
1576
1730
  assert_equal Developer.find_by_name("Marcel").projects.last, proj2 # prove join table is updated
1577
1731
  end
1578
-
1732
+
1579
1733
  def test_uniq_after_the_fact
1580
1734
  developers(:jamis).projects << projects(:active_record)
1581
1735
  developers(:jamis).projects << projects(:active_record)
@@ -1588,7 +1742,7 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1588
1742
  projects(:active_record).developers << developers(:david)
1589
1743
  assert_equal 3, projects(:active_record, :reload).developers.size
1590
1744
  end
1591
-
1745
+
1592
1746
  def test_deleting
1593
1747
  david = Developer.find(1)
1594
1748
  active_record = Project.find(1)
@@ -1597,7 +1751,7 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1597
1751
  assert_equal 3, active_record.developers.size
1598
1752
 
1599
1753
  david.projects.delete(active_record)
1600
-
1754
+
1601
1755
  assert_equal 1, david.projects.size
1602
1756
  assert_equal 1, david.projects(true).size
1603
1757
  assert_equal 2, active_record.developers(true).size
@@ -1616,7 +1770,7 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1616
1770
  active_record = Project.find(1)
1617
1771
  active_record.developers.reload
1618
1772
  assert_equal 3, active_record.developers_by_sql.size
1619
-
1773
+
1620
1774
  active_record.developers_by_sql.delete(david)
1621
1775
  assert_equal 2, active_record.developers_by_sql(true).size
1622
1776
  end
@@ -1625,7 +1779,7 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1625
1779
  active_record = Project.find(1)
1626
1780
  active_record.developers.reload
1627
1781
  assert_equal 3, active_record.developers_by_sql.size
1628
-
1782
+
1629
1783
  active_record.developers_by_sql.delete(Developer.find(:all))
1630
1784
  assert_equal 0, active_record.developers_by_sql(true).size
1631
1785
  end
@@ -1647,9 +1801,9 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1647
1801
  end
1648
1802
 
1649
1803
  def test_additional_columns_from_join_table
1650
- assert_date_from_db Date.new(2004, 10, 10), Developer.find(1).projects.first.joined_on
1804
+ assert_date_from_db Date.new(2004, 10, 10), Developer.find(1).projects.first.joined_on.to_date
1651
1805
  end
1652
-
1806
+
1653
1807
  def test_destroy_all
1654
1808
  david = Developer.find(1)
1655
1809
  david.projects.reload
@@ -1659,14 +1813,11 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1659
1813
  assert david.projects(true).empty?
1660
1814
  end
1661
1815
 
1662
- def test_rich_association
1816
+ def test_deprecated_push_with_attributes_was_removed
1663
1817
  jamis = developers(:jamis)
1664
- assert_deprecated 'push_with_attributes' do
1818
+ assert_raise(NoMethodError) do
1665
1819
  jamis.projects.push_with_attributes(projects(:action_controller), :joined_on => Date.today)
1666
1820
  end
1667
-
1668
- assert_date_from_db Date.today, jamis.projects.select { |p| p.name == projects(:action_controller).name }.first.joined_on
1669
- assert_date_from_db Date.today, developers(:jamis).projects.select { |p| p.name == projects(:action_controller).name }.first.joined_on
1670
1821
  end
1671
1822
 
1672
1823
  def test_associations_with_conditions
@@ -1681,11 +1832,11 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1681
1832
  projects(:active_record).developers_named_david.clear
1682
1833
  assert_equal 2, projects(:active_record, :reload).developers.size
1683
1834
  end
1684
-
1835
+
1685
1836
  def test_find_in_association
1686
1837
  # Using sql
1687
1838
  assert_equal developers(:david), projects(:active_record).developers.find(developers(:david).id), "SQL find"
1688
-
1839
+
1689
1840
  # Using ruby
1690
1841
  active_record = projects(:active_record)
1691
1842
  active_record.developers.reload
@@ -1694,7 +1845,7 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1694
1845
 
1695
1846
  def test_find_in_association_with_custom_finder_sql
1696
1847
  assert_equal developers(:david), projects(:active_record).developers_with_finder_sql.find(developers(:david).id), "SQL find"
1697
-
1848
+
1698
1849
  active_record = projects(:active_record)
1699
1850
  active_record.developers_with_finder_sql.reload
1700
1851
  assert_equal developers(:david), active_record.developers_with_finder_sql.find(developers(:david).id), "Ruby find"
@@ -1710,6 +1861,56 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1710
1861
  assert_equal 3, projects(:active_record).limited_developers.find(:all, :limit => nil).size
1711
1862
  end
1712
1863
 
1864
+ def test_dynamic_find_should_respect_association_order
1865
+ # Developers are ordered 'name DESC, id DESC'
1866
+ low_id_jamis = developers(:jamis)
1867
+ middle_id_jamis = developers(:poor_jamis)
1868
+ high_id_jamis = projects(:active_record).developers.create(:name => 'Jamis')
1869
+
1870
+ assert_equal high_id_jamis, projects(:active_record).developers.find(:first, :conditions => "name = 'Jamis'")
1871
+ assert_equal high_id_jamis, projects(:active_record).developers.find_by_name('Jamis')
1872
+ end
1873
+
1874
+ def test_dynamic_find_order_should_override_association_order
1875
+ # Developers are ordered 'name DESC, id DESC'
1876
+ low_id_jamis = developers(:jamis)
1877
+ middle_id_jamis = developers(:poor_jamis)
1878
+ high_id_jamis = projects(:active_record).developers.create(:name => 'Jamis')
1879
+
1880
+ assert_equal low_id_jamis, projects(:active_record).developers.find(:first, :conditions => "name = 'Jamis'", :order => 'id')
1881
+ assert_equal low_id_jamis, projects(:active_record).developers.find_by_name('Jamis', :order => 'id')
1882
+ end
1883
+
1884
+ def test_dynamic_find_all_should_respect_association_order
1885
+ # Developers are ordered 'name DESC, id DESC'
1886
+ low_id_jamis = developers(:jamis)
1887
+ middle_id_jamis = developers(:poor_jamis)
1888
+ high_id_jamis = projects(:active_record).developers.create(:name => 'Jamis')
1889
+
1890
+ assert_equal [high_id_jamis, middle_id_jamis, low_id_jamis], projects(:active_record).developers.find(:all, :conditions => "name = 'Jamis'")
1891
+ assert_equal [high_id_jamis, middle_id_jamis, low_id_jamis], projects(:active_record).developers.find_all_by_name('Jamis')
1892
+ end
1893
+
1894
+ def test_dynamic_find_all_order_should_override_association_order
1895
+ # Developers are ordered 'name DESC, id DESC'
1896
+ low_id_jamis = developers(:jamis)
1897
+ middle_id_jamis = developers(:poor_jamis)
1898
+ high_id_jamis = projects(:active_record).developers.create(:name => 'Jamis')
1899
+
1900
+ assert_equal [low_id_jamis, middle_id_jamis, high_id_jamis], projects(:active_record).developers.find(:all, :conditions => "name = 'Jamis'", :order => 'id')
1901
+ assert_equal [low_id_jamis, middle_id_jamis, high_id_jamis], projects(:active_record).developers.find_all_by_name('Jamis', :order => 'id')
1902
+ end
1903
+
1904
+ def test_dynamic_find_all_should_respect_association_limit
1905
+ assert_equal 1, projects(:active_record).limited_developers.find(:all, :conditions => "name = 'Jamis'").length
1906
+ assert_equal 1, projects(:active_record).limited_developers.find_all_by_name('Jamis').length
1907
+ end
1908
+
1909
+ def test_dynamic_find_all_order_should_override_association_limit
1910
+ assert_equal 2, projects(:active_record).limited_developers.find(:all, :conditions => "name = 'Jamis'", :limit => 9_000).length
1911
+ assert_equal 2, projects(:active_record).limited_developers.find_all_by_name('Jamis', :limit => 9_000).length
1912
+ end
1913
+
1713
1914
  def test_new_with_values_in_collection
1714
1915
  jamis = DeveloperForProjectWithAfterCreateHook.find_by_name('Jamis')
1715
1916
  david = DeveloperForProjectWithAfterCreateHook.find_by_name('David')
@@ -1725,11 +1926,11 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1725
1926
  def test_find_in_association_with_options
1726
1927
  developers = projects(:active_record).developers.find(:all)
1727
1928
  assert_equal 3, developers.size
1728
-
1929
+
1729
1930
  assert_equal developers(:poor_jamis), projects(:active_record).developers.find(:first, :conditions => "salary < 10000")
1730
1931
  assert_equal developers(:jamis), projects(:active_record).developers.find(:first, :order => "salary DESC")
1731
1932
  end
1732
-
1933
+
1733
1934
  def test_replace_with_less
1734
1935
  david = developers(:david)
1735
1936
  david.projects = [projects(:action_controller)]
@@ -1744,7 +1945,7 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1744
1945
  assert_equal 2, david.projects.length
1745
1946
  assert !david.projects.include?(projects(:active_record))
1746
1947
  end
1747
-
1948
+
1748
1949
  def test_replace_on_new_object
1749
1950
  new_developer = Developer.new("name" => "Matz")
1750
1951
  new_developer.projects = [projects(:action_controller), Project.new("name" => "ActionWebSearch")]
@@ -1755,16 +1956,16 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1755
1956
  def test_consider_type
1756
1957
  developer = Developer.find(:first)
1757
1958
  special_project = SpecialProject.create("name" => "Special Project")
1758
-
1959
+
1759
1960
  other_project = developer.projects.first
1760
1961
  developer.special_projects << special_project
1761
1962
  developer.reload
1762
-
1963
+
1763
1964
  assert developer.projects.include?(special_project)
1764
1965
  assert developer.special_projects.include?(special_project)
1765
1966
  assert !developer.special_projects.include?(other_project)
1766
1967
  end
1767
-
1968
+
1768
1969
  def test_update_attributes_after_push_without_duplicate_join_table_rows
1769
1970
  developer = Developer.new("name" => "Kano")
1770
1971
  project = SpecialProject.create("name" => "Special Project")
@@ -1777,20 +1978,33 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1777
1978
  AND developer_id = #{developer.id}
1778
1979
  end_sql
1779
1980
  end
1780
-
1981
+
1781
1982
  def test_updating_attributes_on_non_rich_associations
1782
1983
  welcome = categories(:technology).posts.first
1783
1984
  welcome.title = "Something else"
1784
1985
  assert welcome.save!
1785
1986
  end
1786
-
1987
+
1988
+ def test_habtm_respects_select
1989
+ categories(:technology).select_testing_posts(true).each do |o|
1990
+ assert_respond_to o, :correctness_marker
1991
+ end
1992
+ assert_respond_to categories(:technology).select_testing_posts.find(:first), :correctness_marker
1993
+ end
1994
+
1787
1995
  def test_updating_attributes_on_rich_associations
1788
1996
  david = projects(:action_controller).developers.first
1789
1997
  david.name = "DHH"
1790
1998
  assert_raises(ActiveRecord::ReadOnlyRecord) { david.save! }
1791
1999
  end
1792
2000
 
1793
-
2001
+ def test_updating_attributes_on_rich_associations_with_limited_find_from_reflection
2002
+ david = projects(:action_controller).selected_developers.first
2003
+ david.name = "DHH"
2004
+ assert_nothing_raised { david.save! }
2005
+ end
2006
+
2007
+
1794
2008
  def test_updating_attributes_on_rich_associations_with_limited_find
1795
2009
  david = projects(:action_controller).developers.find(:all, :select => "developers.*").first
1796
2010
  david.name = "DHH"
@@ -1800,7 +2014,7 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1800
2014
  def test_join_table_alias
1801
2015
  assert_equal 3, Developer.find(:all, :include => {:projects => :developers}, :conditions => 'developers_projects_join.joined_on IS NOT NULL').size
1802
2016
  end
1803
-
2017
+
1804
2018
  def test_join_with_group
1805
2019
  group = Developer.columns.inject([]) do |g, c|
1806
2020
  g << "developers.#{c.name}"
@@ -1812,18 +2026,18 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1812
2026
  end
1813
2027
 
1814
2028
  def test_get_ids
1815
- assert_equal [projects(:active_record).id, projects(:action_controller).id], developers(:david).project_ids
2029
+ assert_equal projects(:active_record, :action_controller).map(&:id), developers(:david).project_ids
1816
2030
  assert_equal [projects(:active_record).id], developers(:jamis).project_ids
1817
2031
  end
1818
2032
 
1819
2033
  def test_assign_ids
1820
2034
  developer = Developer.new("name" => "Joe")
1821
- developer.project_ids = [projects(:active_record).id, projects(:action_controller).id]
2035
+ developer.project_ids = projects(:active_record, :action_controller).map(&:id)
1822
2036
  developer.save
1823
2037
  developer.reload
1824
2038
  assert_equal 2, developer.projects.length
1825
- assert_equal projects(:active_record), developer.projects[0]
1826
- assert_equal projects(:action_controller), developer.projects[1]
2039
+ assert_equal projects(:active_record), developer.projects[0]
2040
+ assert_equal projects(:action_controller), developer.projects[1]
1827
2041
  end
1828
2042
 
1829
2043
  def test_assign_ids_ignoring_blanks
@@ -1832,8 +2046,8 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1832
2046
  developer.save
1833
2047
  developer.reload
1834
2048
  assert_equal 2, developer.projects.length
1835
- assert_equal projects(:active_record), developer.projects[0]
1836
- assert_equal projects(:action_controller), developer.projects[1]
2049
+ assert_equal projects(:active_record), developer.projects[0]
2050
+ assert_equal projects(:action_controller), developer.projects[1]
1837
2051
  end
1838
2052
 
1839
2053
  def test_select_limited_ids_list
@@ -1847,8 +2061,17 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1847
2061
  join_base = ActiveRecord::Associations::ClassMethods::JoinDependency::JoinBase.new(Project)
1848
2062
  join_dep = ActiveRecord::Associations::ClassMethods::JoinDependency.new(join_base, :developers, nil)
1849
2063
  projects = Project.send(:select_limited_ids_list, {:order => 'developers.created_at'}, join_dep)
2064
+ assert !projects.include?("'"), projects
1850
2065
  assert_equal %w(1 2), projects.scan(/\d/).sort
1851
2066
  end
2067
+
2068
+ def test_scoped_find_on_through_association_doesnt_return_read_only_records
2069
+ tag = Post.find(1).tags.find_by_name("General")
2070
+
2071
+ assert_nothing_raised do
2072
+ tag.save!
2073
+ end
2074
+ end
1852
2075
  end
1853
2076
 
1854
2077
 
@@ -1867,7 +2090,7 @@ class OverridingAssociationsTest < Test::Unit::TestCase
1867
2090
  # Different association with the same name, callbacks should be omitted here.
1868
2091
  has_and_belongs_to_many :has_and_belongs_to_many, :class_name => 'DifferentPerson'
1869
2092
  has_many :has_many, :class_name => 'DifferentPerson'
1870
- belongs_to :belongs_to, :class_name => 'DifferentPerson', :foreign_key => 'belongs_to_id'
2093
+ belongs_to :belongs_to, :class_name => 'DifferentPerson'
1871
2094
  has_one :has_one, :class_name => 'DifferentPerson'
1872
2095
  end
1873
2096