activerecord 2.0.5 → 2.1.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 (289) hide show
  1. data/CHANGELOG +168 -6
  2. data/README +27 -22
  3. data/RUNNING_UNIT_TESTS +7 -4
  4. data/Rakefile +22 -25
  5. data/lib/active_record.rb +8 -2
  6. data/lib/active_record/aggregations.rb +21 -12
  7. data/lib/active_record/association_preload.rb +277 -0
  8. data/lib/active_record/associations.rb +481 -295
  9. data/lib/active_record/associations/association_collection.rb +162 -37
  10. data/lib/active_record/associations/association_proxy.rb +71 -7
  11. data/lib/active_record/associations/belongs_to_association.rb +5 -3
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +5 -6
  13. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +12 -64
  14. data/lib/active_record/associations/has_many_association.rb +8 -73
  15. data/lib/active_record/associations/has_many_through_association.rb +68 -117
  16. data/lib/active_record/associations/has_one_association.rb +7 -5
  17. data/lib/active_record/associations/has_one_through_association.rb +28 -0
  18. data/lib/active_record/attribute_methods.rb +69 -19
  19. data/lib/active_record/base.rb +496 -275
  20. data/lib/active_record/calculations.rb +28 -21
  21. data/lib/active_record/callbacks.rb +9 -38
  22. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +3 -2
  23. data/lib/active_record/connection_adapters/abstract/database_statements.rb +2 -2
  24. data/lib/active_record/connection_adapters/abstract/query_cache.rb +6 -0
  25. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +232 -45
  26. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +141 -27
  27. data/lib/active_record/connection_adapters/abstract_adapter.rb +9 -13
  28. data/lib/active_record/connection_adapters/mysql_adapter.rb +57 -24
  29. data/lib/active_record/connection_adapters/postgresql_adapter.rb +143 -42
  30. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -1
  31. data/lib/active_record/connection_adapters/sqlite_adapter.rb +18 -10
  32. data/lib/active_record/dirty.rb +158 -0
  33. data/lib/active_record/fixtures.rb +121 -156
  34. data/lib/active_record/locking/optimistic.rb +14 -11
  35. data/lib/active_record/locking/pessimistic.rb +2 -2
  36. data/lib/active_record/migration.rb +157 -77
  37. data/lib/active_record/named_scope.rb +163 -0
  38. data/lib/active_record/observer.rb +19 -5
  39. data/lib/active_record/reflection.rb +34 -14
  40. data/lib/active_record/schema.rb +7 -14
  41. data/lib/active_record/schema_dumper.rb +4 -4
  42. data/lib/active_record/serialization.rb +5 -5
  43. data/lib/active_record/serializers/json_serializer.rb +37 -28
  44. data/lib/active_record/serializers/xml_serializer.rb +52 -29
  45. data/lib/active_record/test_case.rb +36 -0
  46. data/lib/active_record/timestamp.rb +4 -4
  47. data/lib/active_record/transactions.rb +3 -3
  48. data/lib/active_record/validations.rb +182 -248
  49. data/lib/active_record/version.rb +2 -2
  50. data/test/{fixtures → assets}/example.log +0 -0
  51. data/test/{fixtures → assets}/flowers.jpg +0 -0
  52. data/test/cases/aaa_create_tables_test.rb +24 -0
  53. data/test/cases/active_schema_test_mysql.rb +95 -0
  54. data/test/cases/active_schema_test_postgresql.rb +24 -0
  55. data/test/{adapter_test.rb → cases/adapter_test.rb} +15 -14
  56. data/test/{adapter_test_sqlserver.rb → cases/adapter_test_sqlserver.rb} +95 -95
  57. data/test/{aggregations_test.rb → cases/aggregations_test.rb} +20 -20
  58. data/test/{ar_schema_test.rb → cases/ar_schema_test.rb} +6 -6
  59. data/test/cases/associations/belongs_to_associations_test.rb +412 -0
  60. data/test/{associations → cases/associations}/callbacks_test.rb +24 -10
  61. data/test/{associations → cases/associations}/cascaded_eager_loading_test.rb +18 -17
  62. data/test/cases/associations/eager_load_nested_include_test.rb +83 -0
  63. data/test/{associations → cases/associations}/eager_singularization_test.rb +5 -5
  64. data/test/{associations → cases/associations}/eager_test.rb +216 -51
  65. data/test/{associations → cases/associations}/extension_test.rb +8 -8
  66. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +684 -0
  67. data/test/cases/associations/has_many_associations_test.rb +932 -0
  68. data/test/cases/associations/has_many_through_associations_test.rb +190 -0
  69. data/test/cases/associations/has_one_associations_test.rb +323 -0
  70. data/test/cases/associations/has_one_through_associations_test.rb +74 -0
  71. data/test/{associations → cases/associations}/inner_join_association_test.rb +20 -20
  72. data/test/{associations → cases/associations}/join_model_test.rb +175 -35
  73. data/test/cases/associations_test.rb +262 -0
  74. data/test/{attribute_methods_test.rb → cases/attribute_methods_test.rb} +103 -11
  75. data/test/{base_test.rb → cases/base_test.rb} +338 -191
  76. data/test/{binary_test.rb → cases/binary_test.rb} +6 -4
  77. data/test/{calculations_test.rb → cases/calculations_test.rb} +35 -23
  78. data/test/{callbacks_test.rb → cases/callbacks_test.rb} +7 -7
  79. data/test/{class_inheritable_attributes_test.rb → cases/class_inheritable_attributes_test.rb} +3 -3
  80. data/test/{column_alias_test.rb → cases/column_alias_test.rb} +3 -3
  81. data/test/{connection_test_firebird.rb → cases/connection_test_firebird.rb} +2 -2
  82. data/test/{connection_test_mysql.rb → cases/connection_test_mysql.rb} +2 -2
  83. data/test/{copy_table_test_sqlite.rb → cases/copy_table_test_sqlite.rb} +13 -13
  84. data/test/{datatype_test_postgresql.rb → cases/datatype_test_postgresql.rb} +8 -8
  85. data/test/{date_time_test.rb → cases/date_time_test.rb} +5 -5
  86. data/test/{default_test_firebird.rb → cases/default_test_firebird.rb} +3 -3
  87. data/test/{defaults_test.rb → cases/defaults_test.rb} +8 -6
  88. data/test/{deprecated_finder_test.rb → cases/deprecated_finder_test.rb} +3 -3
  89. data/test/cases/dirty_test.rb +163 -0
  90. data/test/cases/finder_respond_to_test.rb +76 -0
  91. data/test/{finder_test.rb → cases/finder_test.rb} +266 -33
  92. data/test/{fixtures_test.rb → cases/fixtures_test.rb} +88 -72
  93. data/test/cases/helper.rb +47 -0
  94. data/test/{inheritance_test.rb → cases/inheritance_test.rb} +61 -17
  95. data/test/cases/invalid_date_test.rb +24 -0
  96. data/test/{json_serialization_test.rb → cases/json_serialization_test.rb} +36 -11
  97. data/test/{lifecycle_test.rb → cases/lifecycle_test.rb} +16 -13
  98. data/test/{locking_test.rb → cases/locking_test.rb} +17 -10
  99. data/test/{method_scoping_test.rb → cases/method_scoping_test.rb} +75 -39
  100. data/test/{migration_test.rb → cases/migration_test.rb} +420 -80
  101. data/test/{migration_test_firebird.rb → cases/migration_test_firebird.rb} +3 -3
  102. data/test/{mixin_test.rb → cases/mixin_test.rb} +7 -6
  103. data/test/{modules_test.rb → cases/modules_test.rb} +11 -6
  104. data/test/{multiple_db_test.rb → cases/multiple_db_test.rb} +5 -5
  105. data/test/cases/named_scope_test.rb +157 -0
  106. data/test/{pk_test.rb → cases/pk_test.rb} +10 -10
  107. data/test/{query_cache_test.rb → cases/query_cache_test.rb} +12 -10
  108. data/test/{readonly_test.rb → cases/readonly_test.rb} +11 -11
  109. data/test/{reflection_test.rb → cases/reflection_test.rb} +15 -14
  110. data/test/{reserved_word_test_mysql.rb → cases/reserved_word_test_mysql.rb} +4 -5
  111. data/test/{schema_authorization_test_postgresql.rb → cases/schema_authorization_test_postgresql.rb} +5 -5
  112. data/test/cases/schema_dumper_test.rb +138 -0
  113. data/test/cases/schema_test_postgresql.rb +102 -0
  114. data/test/{serialization_test.rb → cases/serialization_test.rb} +7 -7
  115. data/test/{synonym_test_oracle.rb → cases/synonym_test_oracle.rb} +5 -5
  116. data/test/{table_name_test_sqlserver.rb → cases/table_name_test_sqlserver.rb} +3 -3
  117. data/test/{threaded_connections_test.rb → cases/threaded_connections_test.rb} +7 -7
  118. data/test/{transactions_test.rb → cases/transactions_test.rb} +31 -5
  119. data/test/{unconnected_test.rb → cases/unconnected_test.rb} +2 -2
  120. data/test/{validations_test.rb → cases/validations_test.rb} +141 -39
  121. data/test/{xml_serialization_test.rb → cases/xml_serialization_test.rb} +12 -12
  122. data/test/config.rb +5 -0
  123. data/test/connections/native_db2/connection.rb +1 -1
  124. data/test/connections/native_firebird/connection.rb +1 -1
  125. data/test/connections/native_frontbase/connection.rb +1 -1
  126. data/test/connections/native_mysql/connection.rb +1 -1
  127. data/test/connections/native_openbase/connection.rb +1 -1
  128. data/test/connections/native_oracle/connection.rb +1 -1
  129. data/test/connections/native_postgresql/connection.rb +1 -3
  130. data/test/connections/native_sqlite/connection.rb +2 -2
  131. data/test/connections/native_sqlite3/connection.rb +2 -2
  132. data/test/connections/native_sqlite3/in_memory_connection.rb +3 -3
  133. data/test/connections/native_sybase/connection.rb +1 -1
  134. data/test/fixtures/author_addresses.yml +5 -0
  135. data/test/fixtures/authors.yml +2 -0
  136. data/test/fixtures/clubs.yml +6 -0
  137. data/test/fixtures/jobs.yml +7 -0
  138. data/test/fixtures/members.yml +4 -0
  139. data/test/fixtures/memberships.yml +20 -0
  140. data/test/fixtures/owners.yml +7 -0
  141. data/test/fixtures/people.yml +4 -1
  142. data/test/fixtures/pets.yml +14 -0
  143. data/test/fixtures/posts.yml +1 -0
  144. data/test/fixtures/price_estimates.yml +7 -0
  145. data/test/fixtures/readers.yml +5 -0
  146. data/test/fixtures/references.yml +17 -0
  147. data/test/fixtures/sponsors.yml +9 -0
  148. data/test/fixtures/subscribers.yml +7 -0
  149. data/test/fixtures/subscriptions.yml +12 -0
  150. data/test/fixtures/taggings.yml +4 -1
  151. data/test/fixtures/topics.yml +22 -2
  152. data/test/fixtures/warehouse-things.yml +3 -0
  153. data/test/{fixtures/migrations_with_decimal → migrations/decimal}/1_give_me_big_numbers.rb +0 -0
  154. data/test/{fixtures/migrations_with_duplicate → migrations/duplicate}/1_people_have_last_names.rb +1 -1
  155. data/test/{fixtures/migrations_with_duplicate → migrations/duplicate}/2_we_need_reminders.rb +1 -1
  156. data/test/{fixtures/migrations_with_duplicate → migrations/duplicate}/3_foo.rb +0 -0
  157. data/test/{fixtures/migrations → migrations/duplicate}/3_innocent_jointable.rb +0 -0
  158. data/test/migrations/duplicate_names/20080507052938_chunky.rb +7 -0
  159. data/test/migrations/duplicate_names/20080507053028_chunky.rb +7 -0
  160. data/test/{fixtures/migrations_with_duplicate → migrations/interleaved/pass_1}/3_innocent_jointable.rb +0 -0
  161. data/test/{fixtures/migrations → migrations/interleaved/pass_2}/1_people_have_last_names.rb +1 -1
  162. data/test/{fixtures/migrations_with_missing_versions/4_innocent_jointable.rb → migrations/interleaved/pass_2/3_innocent_jointable.rb} +0 -0
  163. data/test/{fixtures/migrations_with_missing_versions → migrations/interleaved/pass_3}/1_people_have_last_names.rb +1 -1
  164. data/test/migrations/interleaved/pass_3/2_i_raise_on_down.rb +8 -0
  165. data/test/migrations/interleaved/pass_3/3_innocent_jointable.rb +12 -0
  166. data/test/{fixtures/migrations_with_missing_versions → migrations/missing}/1000_people_have_middle_names.rb +1 -1
  167. data/test/migrations/missing/1_people_have_last_names.rb +9 -0
  168. data/test/{fixtures/migrations_with_missing_versions → migrations/missing}/3_we_need_reminders.rb +1 -1
  169. data/test/migrations/missing/4_innocent_jointable.rb +12 -0
  170. data/test/migrations/valid/1_people_have_last_names.rb +9 -0
  171. data/test/{fixtures/migrations → migrations/valid}/2_we_need_reminders.rb +1 -1
  172. data/test/migrations/valid/3_innocent_jointable.rb +12 -0
  173. data/test/{fixtures → models}/author.rb +28 -4
  174. data/test/{fixtures → models}/auto_id.rb +0 -0
  175. data/test/{fixtures → models}/binary.rb +0 -0
  176. data/test/{fixtures → models}/book.rb +0 -0
  177. data/test/{fixtures → models}/categorization.rb +0 -0
  178. data/test/{fixtures → models}/category.rb +8 -5
  179. data/test/{fixtures → models}/citation.rb +0 -0
  180. data/test/models/club.rb +7 -0
  181. data/test/{fixtures → models}/column_name.rb +0 -0
  182. data/test/{fixtures → models}/comment.rb +5 -3
  183. data/test/{fixtures → models}/company.rb +15 -6
  184. data/test/{fixtures → models}/company_in_module.rb +5 -3
  185. data/test/{fixtures → models}/computer.rb +0 -1
  186. data/test/{fixtures → models}/contact.rb +1 -1
  187. data/test/{fixtures → models}/course.rb +0 -0
  188. data/test/{fixtures → models}/customer.rb +8 -8
  189. data/test/{fixtures → models}/default.rb +0 -0
  190. data/test/{fixtures → models}/developer.rb +14 -10
  191. data/test/{fixtures → models}/edge.rb +0 -0
  192. data/test/{fixtures → models}/entrant.rb +0 -0
  193. data/test/models/guid.rb +2 -0
  194. data/test/{fixtures → models}/item.rb +0 -0
  195. data/test/models/job.rb +5 -0
  196. data/test/{fixtures → models}/joke.rb +0 -0
  197. data/test/{fixtures → models}/keyboard.rb +0 -0
  198. data/test/{fixtures → models}/legacy_thing.rb +0 -0
  199. data/test/{fixtures → models}/matey.rb +0 -0
  200. data/test/models/member.rb +9 -0
  201. data/test/models/membership.rb +9 -0
  202. data/test/{fixtures → models}/minimalistic.rb +0 -0
  203. data/test/{fixtures → models}/mixed_case_monkey.rb +0 -0
  204. data/test/{fixtures → models}/movie.rb +0 -0
  205. data/test/{fixtures → models}/order.rb +2 -2
  206. data/test/models/owner.rb +4 -0
  207. data/test/{fixtures → models}/parrot.rb +0 -0
  208. data/test/models/person.rb +10 -0
  209. data/test/models/pet.rb +4 -0
  210. data/test/models/pirate.rb +9 -0
  211. data/test/{fixtures → models}/post.rb +23 -2
  212. data/test/models/price_estimate.rb +3 -0
  213. data/test/{fixtures → models}/project.rb +1 -0
  214. data/test/{fixtures → models}/reader.rb +0 -0
  215. data/test/models/reference.rb +4 -0
  216. data/test/{fixtures → models}/reply.rb +7 -5
  217. data/test/{fixtures → models}/ship.rb +0 -0
  218. data/test/models/sponsor.rb +4 -0
  219. data/test/{fixtures → models}/subject.rb +0 -0
  220. data/test/{fixtures → models}/subscriber.rb +2 -0
  221. data/test/models/subscription.rb +4 -0
  222. data/test/{fixtures → models}/tag.rb +0 -0
  223. data/test/{fixtures → models}/tagging.rb +0 -0
  224. data/test/{fixtures → models}/task.rb +0 -0
  225. data/test/{fixtures → models}/topic.rb +32 -4
  226. data/test/{fixtures → models}/treasure.rb +2 -0
  227. data/test/{fixtures → models}/vertex.rb +0 -0
  228. data/test/models/warehouse_thing.rb +5 -0
  229. data/test/schema/mysql_specific_schema.rb +12 -0
  230. data/test/schema/postgresql_specific_schema.rb +103 -0
  231. data/test/schema/schema.rb +421 -0
  232. data/test/schema/schema2.rb +6 -0
  233. data/test/schema/sqlite_specific_schema.rb +25 -0
  234. data/test/schema/sqlserver_specific_schema.rb +5 -0
  235. metadata +192 -176
  236. data/test/aaa_create_tables_test.rb +0 -72
  237. data/test/abstract_unit.rb +0 -84
  238. data/test/active_schema_test_mysql.rb +0 -46
  239. data/test/all.sh +0 -8
  240. data/test/association_inheritance_reload.rb +0 -14
  241. data/test/associations_test.rb +0 -2177
  242. data/test/fixtures/bad_fixtures/attr_with_numeric_first_char +0 -1
  243. data/test/fixtures/bad_fixtures/attr_with_spaces +0 -1
  244. data/test/fixtures/bad_fixtures/blank_line +0 -3
  245. data/test/fixtures/bad_fixtures/duplicate_attributes +0 -3
  246. data/test/fixtures/bad_fixtures/missing_value +0 -1
  247. data/test/fixtures/db_definitions/db2.drop.sql +0 -33
  248. data/test/fixtures/db_definitions/db2.sql +0 -235
  249. data/test/fixtures/db_definitions/db22.drop.sql +0 -2
  250. data/test/fixtures/db_definitions/db22.sql +0 -5
  251. data/test/fixtures/db_definitions/firebird.drop.sql +0 -65
  252. data/test/fixtures/db_definitions/firebird.sql +0 -310
  253. data/test/fixtures/db_definitions/firebird2.drop.sql +0 -2
  254. data/test/fixtures/db_definitions/firebird2.sql +0 -6
  255. data/test/fixtures/db_definitions/frontbase.drop.sql +0 -33
  256. data/test/fixtures/db_definitions/frontbase.sql +0 -273
  257. data/test/fixtures/db_definitions/frontbase2.drop.sql +0 -1
  258. data/test/fixtures/db_definitions/frontbase2.sql +0 -4
  259. data/test/fixtures/db_definitions/openbase.drop.sql +0 -2
  260. data/test/fixtures/db_definitions/openbase.sql +0 -318
  261. data/test/fixtures/db_definitions/openbase2.drop.sql +0 -2
  262. data/test/fixtures/db_definitions/openbase2.sql +0 -7
  263. data/test/fixtures/db_definitions/oracle.drop.sql +0 -67
  264. data/test/fixtures/db_definitions/oracle.sql +0 -330
  265. data/test/fixtures/db_definitions/oracle2.drop.sql +0 -2
  266. data/test/fixtures/db_definitions/oracle2.sql +0 -6
  267. data/test/fixtures/db_definitions/postgresql.drop.sql +0 -44
  268. data/test/fixtures/db_definitions/postgresql.sql +0 -292
  269. data/test/fixtures/db_definitions/postgresql2.drop.sql +0 -2
  270. data/test/fixtures/db_definitions/postgresql2.sql +0 -4
  271. data/test/fixtures/db_definitions/schema.rb +0 -354
  272. data/test/fixtures/db_definitions/schema2.rb +0 -11
  273. data/test/fixtures/db_definitions/sqlite.drop.sql +0 -33
  274. data/test/fixtures/db_definitions/sqlite.sql +0 -219
  275. data/test/fixtures/db_definitions/sqlite2.drop.sql +0 -2
  276. data/test/fixtures/db_definitions/sqlite2.sql +0 -5
  277. data/test/fixtures/db_definitions/sybase.drop.sql +0 -35
  278. data/test/fixtures/db_definitions/sybase.sql +0 -222
  279. data/test/fixtures/db_definitions/sybase2.drop.sql +0 -4
  280. data/test/fixtures/db_definitions/sybase2.sql +0 -5
  281. data/test/fixtures/developers_projects/david_action_controller +0 -3
  282. data/test/fixtures/developers_projects/david_active_record +0 -3
  283. data/test/fixtures/developers_projects/jamis_active_record +0 -2
  284. data/test/fixtures/person.rb +0 -4
  285. data/test/fixtures/pirate.rb +0 -5
  286. data/test/fixtures/subscribers/first +0 -2
  287. data/test/fixtures/subscribers/second +0 -2
  288. data/test/schema_dumper_test.rb +0 -131
  289. data/test/schema_test_postgresql.rb +0 -64
@@ -0,0 +1,932 @@
1
+ require "cases/helper"
2
+ require 'models/developer'
3
+ require 'models/project'
4
+ require 'models/company'
5
+ require 'models/topic'
6
+ require 'models/reply'
7
+ require 'models/category'
8
+ require 'models/post'
9
+ require 'models/author'
10
+ require 'models/comment'
11
+ require 'models/person'
12
+ require 'models/reader'
13
+
14
+ class HasManyAssociationsTest < ActiveRecord::TestCase
15
+ fixtures :accounts, :categories, :companies, :developers, :projects,
16
+ :developers_projects, :topics, :authors, :comments, :author_addresses,
17
+ :people, :posts
18
+
19
+ def setup
20
+ Client.destroyed_client_ids.clear
21
+ end
22
+
23
+ def force_signal37_to_load_all_clients_of_firm
24
+ companies(:first_firm).clients_of_firm.each {|f| }
25
+ end
26
+
27
+ def test_counting_with_counter_sql
28
+ assert_equal 2, Firm.find(:first).clients.count
29
+ end
30
+
31
+ def test_counting
32
+ assert_equal 2, Firm.find(:first).plain_clients.count
33
+ end
34
+
35
+ def test_counting_with_empty_hash_conditions
36
+ assert_equal 2, Firm.find(:first).plain_clients.count(:conditions => {})
37
+ end
38
+
39
+ def test_counting_with_single_conditions
40
+ assert_equal 2, Firm.find(:first).plain_clients.count(:conditions => '1=1')
41
+ end
42
+
43
+ def test_counting_with_single_hash
44
+ assert_equal 2, Firm.find(:first).plain_clients.count(:conditions => '1=1')
45
+ end
46
+
47
+ def test_counting_with_column_name_and_hash
48
+ assert_equal 2, Firm.find(:first).plain_clients.count(:all, :conditions => '1=1')
49
+ end
50
+
51
+ def test_finding
52
+ assert_equal 2, Firm.find(:first).clients.length
53
+ end
54
+
55
+ def test_find_with_blank_conditions
56
+ [[], {}, nil, ""].each do |blank|
57
+ assert_equal 2, Firm.find(:first).clients.find(:all, :conditions => blank).size
58
+ end
59
+ end
60
+
61
+ def test_find_many_with_merged_options
62
+ assert_equal 1, companies(:first_firm).limited_clients.size
63
+ assert_equal 1, companies(:first_firm).limited_clients.find(:all).size
64
+ assert_equal 2, companies(:first_firm).limited_clients.find(:all, :limit => nil).size
65
+ end
66
+
67
+ def test_dynamic_find_should_respect_association_order
68
+ assert_equal companies(:second_client), companies(:first_firm).clients_sorted_desc.find(:first, :conditions => "type = 'Client'")
69
+ assert_equal companies(:second_client), companies(:first_firm).clients_sorted_desc.find_by_type('Client')
70
+ end
71
+
72
+ def test_dynamic_find_order_should_override_association_order
73
+ assert_equal companies(:first_client), companies(:first_firm).clients_sorted_desc.find(:first, :conditions => "type = 'Client'", :order => 'id')
74
+ assert_equal companies(:first_client), companies(:first_firm).clients_sorted_desc.find_by_type('Client', :order => 'id')
75
+ end
76
+
77
+ def test_dynamic_find_all_should_respect_association_order
78
+ assert_equal [companies(:second_client), companies(:first_client)], companies(:first_firm).clients_sorted_desc.find(:all, :conditions => "type = 'Client'")
79
+ assert_equal [companies(:second_client), companies(:first_client)], companies(:first_firm).clients_sorted_desc.find_all_by_type('Client')
80
+ end
81
+
82
+ def test_dynamic_find_all_order_should_override_association_order
83
+ assert_equal [companies(:first_client), companies(:second_client)], companies(:first_firm).clients_sorted_desc.find(:all, :conditions => "type = 'Client'", :order => 'id')
84
+ assert_equal [companies(:first_client), companies(:second_client)], companies(:first_firm).clients_sorted_desc.find_all_by_type('Client', :order => 'id')
85
+ end
86
+
87
+ def test_dynamic_find_all_should_respect_association_limit
88
+ assert_equal 1, companies(:first_firm).limited_clients.find(:all, :conditions => "type = 'Client'").length
89
+ assert_equal 1, companies(:first_firm).limited_clients.find_all_by_type('Client').length
90
+ end
91
+
92
+ def test_dynamic_find_all_limit_should_override_association_limit
93
+ assert_equal 2, companies(:first_firm).limited_clients.find(:all, :conditions => "type = 'Client'", :limit => 9_000).length
94
+ assert_equal 2, companies(:first_firm).limited_clients.find_all_by_type('Client', :limit => 9_000).length
95
+ end
96
+
97
+ def test_dynamic_find_all_should_respect_readonly_access
98
+ companies(:first_firm).readonly_clients.find(:all).each { |c| assert_raise(ActiveRecord::ReadOnlyRecord) { c.save! } }
99
+ companies(:first_firm).readonly_clients.find(:all).each { |c| assert c.readonly? }
100
+ end
101
+
102
+ def test_cant_save_has_many_readonly_association
103
+ authors(:david).readonly_comments.each { |c| assert_raise(ActiveRecord::ReadOnlyRecord) { c.save! } }
104
+ authors(:david).readonly_comments.each { |c| assert c.readonly? }
105
+ end
106
+
107
+ def test_triple_equality
108
+ assert !(Array === Firm.find(:first).clients)
109
+ assert Firm.find(:first).clients === Array
110
+ end
111
+
112
+ def test_finding_default_orders
113
+ assert_equal "Summit", Firm.find(:first).clients.first.name
114
+ end
115
+
116
+ def test_finding_with_different_class_name_and_order
117
+ assert_equal "Microsoft", Firm.find(:first).clients_sorted_desc.first.name
118
+ end
119
+
120
+ def test_finding_with_foreign_key
121
+ assert_equal "Microsoft", Firm.find(:first).clients_of_firm.first.name
122
+ end
123
+
124
+ def test_finding_with_condition
125
+ assert_equal "Microsoft", Firm.find(:first).clients_like_ms.first.name
126
+ end
127
+
128
+ def test_finding_with_condition_hash
129
+ assert_equal "Microsoft", Firm.find(:first).clients_like_ms_with_hash_conditions.first.name
130
+ end
131
+
132
+ def test_finding_using_sql
133
+ firm = Firm.find(:first)
134
+ first_client = firm.clients_using_sql.first
135
+ assert_not_nil first_client
136
+ assert_equal "Microsoft", first_client.name
137
+ assert_equal 1, firm.clients_using_sql.size
138
+ assert_equal 1, Firm.find(:first).clients_using_sql.size
139
+ end
140
+
141
+ def test_counting_using_sql
142
+ assert_equal 1, Firm.find(:first).clients_using_counter_sql.size
143
+ assert Firm.find(:first).clients_using_counter_sql.any?
144
+ assert_equal 0, Firm.find(:first).clients_using_zero_counter_sql.size
145
+ assert !Firm.find(:first).clients_using_zero_counter_sql.any?
146
+ end
147
+
148
+ def test_counting_non_existant_items_using_sql
149
+ assert_equal 0, Firm.find(:first).no_clients_using_counter_sql.size
150
+ end
151
+
152
+ def test_belongs_to_sanity
153
+ c = Client.new
154
+ assert_nil c.firm
155
+
156
+ if c.firm
157
+ assert false, "belongs_to failed if check"
158
+ end
159
+
160
+ unless c.firm
161
+ else
162
+ assert false, "belongs_to failed unless check"
163
+ end
164
+ end
165
+
166
+ def test_find_ids
167
+ firm = Firm.find(:first)
168
+
169
+ assert_raises(ActiveRecord::RecordNotFound) { firm.clients.find }
170
+
171
+ client = firm.clients.find(2)
172
+ assert_kind_of Client, client
173
+
174
+ client_ary = firm.clients.find([2])
175
+ assert_kind_of Array, client_ary
176
+ assert_equal client, client_ary.first
177
+
178
+ client_ary = firm.clients.find(2, 3)
179
+ assert_kind_of Array, client_ary
180
+ assert_equal 2, client_ary.size
181
+ assert_equal client, client_ary.first
182
+
183
+ assert_raises(ActiveRecord::RecordNotFound) { firm.clients.find(2, 99) }
184
+ end
185
+
186
+ def test_find_string_ids_when_using_finder_sql
187
+ firm = Firm.find(:first)
188
+
189
+ client = firm.clients_using_finder_sql.find("2")
190
+ assert_kind_of Client, client
191
+
192
+ client_ary = firm.clients_using_finder_sql.find(["2"])
193
+ assert_kind_of Array, client_ary
194
+ assert_equal client, client_ary.first
195
+
196
+ client_ary = firm.clients_using_finder_sql.find("2", "3")
197
+ assert_kind_of Array, client_ary
198
+ assert_equal 2, client_ary.size
199
+ assert client_ary.include?(client)
200
+ end
201
+
202
+ def test_find_all
203
+ firm = Firm.find(:first)
204
+ assert_equal 2, firm.clients.find(:all, :conditions => "#{QUOTED_TYPE} = 'Client'").length
205
+ assert_equal 1, firm.clients.find(:all, :conditions => "name = 'Summit'").length
206
+ end
207
+
208
+ def test_find_all_sanitized
209
+ firm = Firm.find(:first)
210
+ summit = firm.clients.find(:all, :conditions => "name = 'Summit'")
211
+ assert_equal summit, firm.clients.find(:all, :conditions => ["name = ?", "Summit"])
212
+ assert_equal summit, firm.clients.find(:all, :conditions => ["name = :name", { :name => "Summit" }])
213
+ end
214
+
215
+ def test_find_first
216
+ firm = Firm.find(:first)
217
+ client2 = Client.find(2)
218
+ assert_equal firm.clients.first, firm.clients.find(:first)
219
+ assert_equal client2, firm.clients.find(:first, :conditions => "#{QUOTED_TYPE} = 'Client'")
220
+ end
221
+
222
+ def test_find_first_sanitized
223
+ firm = Firm.find(:first)
224
+ client2 = Client.find(2)
225
+ assert_equal client2, firm.clients.find(:first, :conditions => ["#{QUOTED_TYPE} = ?", 'Client'])
226
+ assert_equal client2, firm.clients.find(:first, :conditions => ["#{QUOTED_TYPE} = :type", { :type => 'Client' }])
227
+ end
228
+
229
+ def test_find_in_collection
230
+ assert_equal Client.find(2).name, companies(:first_firm).clients.find(2).name
231
+ assert_raises(ActiveRecord::RecordNotFound) { companies(:first_firm).clients.find(6) }
232
+ end
233
+
234
+ def test_find_grouped
235
+ all_clients_of_firm1 = Client.find(:all, :conditions => "firm_id = 1")
236
+ grouped_clients_of_firm1 = Client.find(:all, :conditions => "firm_id = 1", :group => "firm_id", :select => 'firm_id, count(id) as clients_count')
237
+ assert_equal 2, all_clients_of_firm1.size
238
+ assert_equal 1, grouped_clients_of_firm1.size
239
+ end
240
+
241
+ def test_adding
242
+ force_signal37_to_load_all_clients_of_firm
243
+ natural = Client.new("name" => "Natural Company")
244
+ companies(:first_firm).clients_of_firm << natural
245
+ assert_equal 2, companies(:first_firm).clients_of_firm.size # checking via the collection
246
+ assert_equal 2, companies(:first_firm).clients_of_firm(true).size # checking using the db
247
+ assert_equal natural, companies(:first_firm).clients_of_firm.last
248
+ end
249
+
250
+ def test_adding_using_create
251
+ first_firm = companies(:first_firm)
252
+ assert_equal 2, first_firm.plain_clients.size
253
+ natural = first_firm.plain_clients.create(:name => "Natural Company")
254
+ assert_equal 3, first_firm.plain_clients.length
255
+ assert_equal 3, first_firm.plain_clients.size
256
+ end
257
+
258
+ def test_create_with_bang_on_has_many_when_parent_is_new_raises
259
+ assert_raises(ActiveRecord::RecordNotSaved) do
260
+ firm = Firm.new
261
+ firm.plain_clients.create! :name=>"Whoever"
262
+ end
263
+ end
264
+
265
+ def test_regular_create_on_has_many_when_parent_is_new_raises
266
+ assert_raises(ActiveRecord::RecordNotSaved) do
267
+ firm = Firm.new
268
+ firm.plain_clients.create :name=>"Whoever"
269
+ end
270
+ end
271
+
272
+ def test_create_with_bang_on_has_many_raises_when_record_not_saved
273
+ assert_raises(ActiveRecord::RecordInvalid) do
274
+ firm = Firm.find(:first)
275
+ firm.plain_clients.create!
276
+ end
277
+ end
278
+
279
+ def test_create_with_bang_on_habtm_when_parent_is_new_raises
280
+ assert_raises(ActiveRecord::RecordNotSaved) do
281
+ Developer.new("name" => "Aredridel").projects.create!
282
+ end
283
+ end
284
+
285
+ def test_adding_a_mismatch_class
286
+ assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << nil }
287
+ assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << 1 }
288
+ assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << Topic.find(1) }
289
+ end
290
+
291
+ def test_adding_a_collection
292
+ force_signal37_to_load_all_clients_of_firm
293
+ companies(:first_firm).clients_of_firm.concat([Client.new("name" => "Natural Company"), Client.new("name" => "Apple")])
294
+ assert_equal 3, companies(:first_firm).clients_of_firm.size
295
+ assert_equal 3, companies(:first_firm).clients_of_firm(true).size
296
+ end
297
+
298
+ def test_adding_before_save
299
+ no_of_firms = Firm.count
300
+ no_of_clients = Client.count
301
+
302
+ new_firm = Firm.new("name" => "A New Firm, Inc")
303
+ c = Client.new("name" => "Apple")
304
+
305
+ new_firm.clients_of_firm.push Client.new("name" => "Natural Company")
306
+ assert_equal 1, new_firm.clients_of_firm.size
307
+ new_firm.clients_of_firm << c
308
+ assert_equal 2, new_firm.clients_of_firm.size
309
+
310
+ assert_equal no_of_firms, Firm.count # Firm was not saved to database.
311
+ assert_equal no_of_clients, Client.count # Clients were not saved to database.
312
+ assert new_firm.save
313
+ assert !new_firm.new_record?
314
+ assert !c.new_record?
315
+ assert_equal new_firm, c.firm
316
+ assert_equal no_of_firms+1, Firm.count # Firm was saved to database.
317
+ assert_equal no_of_clients+2, Client.count # Clients were saved to database.
318
+
319
+ assert_equal 2, new_firm.clients_of_firm.size
320
+ assert_equal 2, new_firm.clients_of_firm(true).size
321
+ end
322
+
323
+ def test_invalid_adding
324
+ firm = Firm.find(1)
325
+ assert !(firm.clients_of_firm << c = Client.new)
326
+ assert c.new_record?
327
+ assert !firm.valid?
328
+ assert !firm.save
329
+ assert c.new_record?
330
+ end
331
+
332
+ def test_invalid_adding_before_save
333
+ no_of_firms = Firm.count
334
+ no_of_clients = Client.count
335
+ new_firm = Firm.new("name" => "A New Firm, Inc")
336
+ new_firm.clients_of_firm.concat([c = Client.new, Client.new("name" => "Apple")])
337
+ assert c.new_record?
338
+ assert !c.valid?
339
+ assert !new_firm.valid?
340
+ assert !new_firm.save
341
+ assert c.new_record?
342
+ assert new_firm.new_record?
343
+ end
344
+
345
+ def test_build
346
+ company = companies(:first_firm)
347
+ new_client = assert_no_queries { company.clients_of_firm.build("name" => "Another Client") }
348
+ assert !company.clients_of_firm.loaded?
349
+
350
+ assert_equal "Another Client", new_client.name
351
+ assert new_client.new_record?
352
+ assert_equal new_client, company.clients_of_firm.last
353
+ company.name += '-changed'
354
+ assert_queries(2) { assert company.save }
355
+ assert !new_client.new_record?
356
+ assert_equal 2, company.clients_of_firm(true).size
357
+ end
358
+
359
+ def test_build_many
360
+ company = companies(:first_firm)
361
+ new_clients = assert_no_queries { company.clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}]) }
362
+
363
+ assert_equal 2, new_clients.size
364
+ company.name += '-changed'
365
+ assert_queries(3) { assert company.save }
366
+ assert_equal 3, company.clients_of_firm(true).size
367
+ end
368
+
369
+ def test_build_followed_by_save_does_not_load_target
370
+ new_client = companies(:first_firm).clients_of_firm.build("name" => "Another Client")
371
+ assert companies(:first_firm).save
372
+ assert !companies(:first_firm).clients_of_firm.loaded?
373
+ end
374
+
375
+ def test_build_without_loading_association
376
+ first_topic = topics(:first)
377
+ Reply.column_names
378
+
379
+ assert_equal 1, first_topic.replies.length
380
+
381
+ assert_no_queries do
382
+ first_topic.replies.build(:title => "Not saved", :content => "Superstars")
383
+ assert_equal 2, first_topic.replies.size
384
+ end
385
+
386
+ assert_equal 2, first_topic.replies.to_ary.size
387
+ end
388
+
389
+ def test_create_without_loading_association
390
+ first_firm = companies(:first_firm)
391
+ Firm.column_names
392
+ Client.column_names
393
+
394
+ assert_equal 1, first_firm.clients_of_firm.size
395
+ first_firm.clients_of_firm.reset
396
+
397
+ assert_queries(1) do
398
+ first_firm.clients_of_firm.create(:name => "Superstars")
399
+ end
400
+
401
+ assert_equal 2, first_firm.clients_of_firm.size
402
+ end
403
+
404
+ def test_invalid_build
405
+ new_client = companies(:first_firm).clients_of_firm.build
406
+ assert new_client.new_record?
407
+ assert !new_client.valid?
408
+ assert_equal new_client, companies(:first_firm).clients_of_firm.last
409
+ assert !companies(:first_firm).save
410
+ assert new_client.new_record?
411
+ assert_equal 1, companies(:first_firm).clients_of_firm(true).size
412
+ end
413
+
414
+ def test_create
415
+ force_signal37_to_load_all_clients_of_firm
416
+ new_client = companies(:first_firm).clients_of_firm.create("name" => "Another Client")
417
+ assert !new_client.new_record?
418
+ assert_equal new_client, companies(:first_firm).clients_of_firm.last
419
+ assert_equal new_client, companies(:first_firm).clients_of_firm(true).last
420
+ end
421
+
422
+ def test_create_many
423
+ companies(:first_firm).clients_of_firm.create([{"name" => "Another Client"}, {"name" => "Another Client II"}])
424
+ assert_equal 3, companies(:first_firm).clients_of_firm(true).size
425
+ end
426
+
427
+ def test_create_followed_by_save_does_not_load_target
428
+ new_client = companies(:first_firm).clients_of_firm.create("name" => "Another Client")
429
+ assert companies(:first_firm).save
430
+ assert !companies(:first_firm).clients_of_firm.loaded?
431
+ end
432
+
433
+ def test_find_or_initialize
434
+ the_client = companies(:first_firm).clients.find_or_initialize_by_name("Yet another client")
435
+ assert_equal companies(:first_firm).id, the_client.firm_id
436
+ assert_equal "Yet another client", the_client.name
437
+ assert the_client.new_record?
438
+ end
439
+
440
+ def test_find_or_create
441
+ number_of_clients = companies(:first_firm).clients.size
442
+ the_client = companies(:first_firm).clients.find_or_create_by_name("Yet another client")
443
+ assert_equal number_of_clients + 1, companies(:first_firm, :reload).clients.size
444
+ assert_equal the_client, companies(:first_firm).clients.find_or_create_by_name("Yet another client")
445
+ assert_equal number_of_clients + 1, companies(:first_firm, :reload).clients.size
446
+ end
447
+
448
+ def test_deleting
449
+ force_signal37_to_load_all_clients_of_firm
450
+ companies(:first_firm).clients_of_firm.delete(companies(:first_firm).clients_of_firm.first)
451
+ assert_equal 0, companies(:first_firm).clients_of_firm.size
452
+ assert_equal 0, companies(:first_firm).clients_of_firm(true).size
453
+ end
454
+
455
+ def test_deleting_before_save
456
+ new_firm = Firm.new("name" => "A New Firm, Inc.")
457
+ new_client = new_firm.clients_of_firm.build("name" => "Another Client")
458
+ assert_equal 1, new_firm.clients_of_firm.size
459
+ new_firm.clients_of_firm.delete(new_client)
460
+ assert_equal 0, new_firm.clients_of_firm.size
461
+ end
462
+
463
+ def test_deleting_a_collection
464
+ force_signal37_to_load_all_clients_of_firm
465
+ companies(:first_firm).clients_of_firm.create("name" => "Another Client")
466
+ assert_equal 2, companies(:first_firm).clients_of_firm.size
467
+ companies(:first_firm).clients_of_firm.delete([companies(:first_firm).clients_of_firm[0], companies(:first_firm).clients_of_firm[1]])
468
+ assert_equal 0, companies(:first_firm).clients_of_firm.size
469
+ assert_equal 0, companies(:first_firm).clients_of_firm(true).size
470
+ end
471
+
472
+ def test_delete_all
473
+ force_signal37_to_load_all_clients_of_firm
474
+ companies(:first_firm).clients_of_firm.create("name" => "Another Client")
475
+ assert_equal 2, companies(:first_firm).clients_of_firm.size
476
+ companies(:first_firm).clients_of_firm.delete_all
477
+ assert_equal 0, companies(:first_firm).clients_of_firm.size
478
+ assert_equal 0, companies(:first_firm).clients_of_firm(true).size
479
+ end
480
+
481
+ def test_delete_all_with_not_yet_loaded_association_collection
482
+ force_signal37_to_load_all_clients_of_firm
483
+ companies(:first_firm).clients_of_firm.create("name" => "Another Client")
484
+ assert_equal 2, companies(:first_firm).clients_of_firm.size
485
+ companies(:first_firm).clients_of_firm.reset
486
+ companies(:first_firm).clients_of_firm.delete_all
487
+ assert_equal 0, companies(:first_firm).clients_of_firm.size
488
+ assert_equal 0, companies(:first_firm).clients_of_firm(true).size
489
+ end
490
+
491
+ def test_clearing_an_association_collection
492
+ firm = companies(:first_firm)
493
+ client_id = firm.clients_of_firm.first.id
494
+ assert_equal 1, firm.clients_of_firm.size
495
+
496
+ firm.clients_of_firm.clear
497
+
498
+ assert_equal 0, firm.clients_of_firm.size
499
+ assert_equal 0, firm.clients_of_firm(true).size
500
+ assert_equal [], Client.destroyed_client_ids[firm.id]
501
+
502
+ # Should not be destroyed since the association is not dependent.
503
+ assert_nothing_raised do
504
+ assert Client.find(client_id).firm.nil?
505
+ end
506
+ end
507
+
508
+ def test_clearing_a_dependent_association_collection
509
+ firm = companies(:first_firm)
510
+ client_id = firm.dependent_clients_of_firm.first.id
511
+ assert_equal 1, firm.dependent_clients_of_firm.size
512
+
513
+ # :dependent means destroy is called on each client
514
+ firm.dependent_clients_of_firm.clear
515
+
516
+ assert_equal 0, firm.dependent_clients_of_firm.size
517
+ assert_equal 0, firm.dependent_clients_of_firm(true).size
518
+ assert_equal [client_id], Client.destroyed_client_ids[firm.id]
519
+
520
+ # Should be destroyed since the association is dependent.
521
+ assert Client.find_by_id(client_id).nil?
522
+ end
523
+
524
+ def test_clearing_an_exclusively_dependent_association_collection
525
+ firm = companies(:first_firm)
526
+ client_id = firm.exclusively_dependent_clients_of_firm.first.id
527
+ assert_equal 1, firm.exclusively_dependent_clients_of_firm.size
528
+
529
+ assert_equal [], Client.destroyed_client_ids[firm.id]
530
+
531
+ # :exclusively_dependent means each client is deleted directly from
532
+ # the database without looping through them calling destroy.
533
+ firm.exclusively_dependent_clients_of_firm.clear
534
+
535
+ assert_equal 0, firm.exclusively_dependent_clients_of_firm.size
536
+ assert_equal 0, firm.exclusively_dependent_clients_of_firm(true).size
537
+ # no destroy-filters should have been called
538
+ assert_equal [], Client.destroyed_client_ids[firm.id]
539
+
540
+ # Should be destroyed since the association is exclusively dependent.
541
+ assert Client.find_by_id(client_id).nil?
542
+ end
543
+
544
+ def test_dependent_association_respects_optional_conditions_on_delete
545
+ firm = companies(:odegy)
546
+ Client.create(:client_of => firm.id, :name => "BigShot Inc.")
547
+ Client.create(:client_of => firm.id, :name => "SmallTime Inc.")
548
+ # only one of two clients is included in the association due to the :conditions key
549
+ assert_equal 2, Client.find_all_by_client_of(firm.id).size
550
+ assert_equal 1, firm.dependent_conditional_clients_of_firm.size
551
+ firm.destroy
552
+ # only the correctly associated client should have been deleted
553
+ assert_equal 1, Client.find_all_by_client_of(firm.id).size
554
+ end
555
+
556
+ def test_dependent_association_respects_optional_sanitized_conditions_on_delete
557
+ firm = companies(:odegy)
558
+ Client.create(:client_of => firm.id, :name => "BigShot Inc.")
559
+ Client.create(:client_of => firm.id, :name => "SmallTime Inc.")
560
+ # only one of two clients is included in the association due to the :conditions key
561
+ assert_equal 2, Client.find_all_by_client_of(firm.id).size
562
+ assert_equal 1, firm.dependent_sanitized_conditional_clients_of_firm.size
563
+ firm.destroy
564
+ # only the correctly associated client should have been deleted
565
+ assert_equal 1, Client.find_all_by_client_of(firm.id).size
566
+ end
567
+
568
+ def test_creation_respects_hash_condition
569
+ ms_client = companies(:first_firm).clients_like_ms_with_hash_conditions.build
570
+
571
+ assert ms_client.save
572
+ assert_equal 'Microsoft', ms_client.name
573
+
574
+ another_ms_client = companies(:first_firm).clients_like_ms_with_hash_conditions.create
575
+
576
+ assert !another_ms_client.new_record?
577
+ assert_equal 'Microsoft', another_ms_client.name
578
+ end
579
+
580
+ def test_dependent_delete_and_destroy_with_belongs_to
581
+ author_address = author_addresses(:david_address)
582
+ assert_equal [], AuthorAddress.destroyed_author_address_ids[authors(:david).id]
583
+
584
+ assert_difference "AuthorAddress.count", -2 do
585
+ authors(:david).destroy
586
+ end
587
+
588
+ assert_equal [author_address.id], AuthorAddress.destroyed_author_address_ids[authors(:david).id]
589
+ end
590
+
591
+ def test_invalid_belongs_to_dependent_option_raises_exception
592
+ assert_raises ArgumentError do
593
+ Author.belongs_to :special_author_address, :dependent => :nullify
594
+ end
595
+ end
596
+
597
+ def test_clearing_without_initial_access
598
+ firm = companies(:first_firm)
599
+
600
+ firm.clients_of_firm.clear
601
+
602
+ assert_equal 0, firm.clients_of_firm.size
603
+ assert_equal 0, firm.clients_of_firm(true).size
604
+ end
605
+
606
+ def test_deleting_a_item_which_is_not_in_the_collection
607
+ force_signal37_to_load_all_clients_of_firm
608
+ summit = Client.find_by_name('Summit')
609
+ companies(:first_firm).clients_of_firm.delete(summit)
610
+ assert_equal 1, companies(:first_firm).clients_of_firm.size
611
+ assert_equal 1, companies(:first_firm).clients_of_firm(true).size
612
+ assert_equal 2, summit.client_of
613
+ end
614
+
615
+ def test_deleting_type_mismatch
616
+ david = Developer.find(1)
617
+ david.projects.reload
618
+ assert_raises(ActiveRecord::AssociationTypeMismatch) { david.projects.delete(1) }
619
+ end
620
+
621
+ def test_deleting_self_type_mismatch
622
+ david = Developer.find(1)
623
+ david.projects.reload
624
+ assert_raises(ActiveRecord::AssociationTypeMismatch) { david.projects.delete(Project.find(1).developers) }
625
+ end
626
+
627
+ def test_destroy_all
628
+ force_signal37_to_load_all_clients_of_firm
629
+ assert !companies(:first_firm).clients_of_firm.empty?, "37signals has clients after load"
630
+ companies(:first_firm).clients_of_firm.destroy_all
631
+ assert companies(:first_firm).clients_of_firm.empty?, "37signals has no clients after destroy all"
632
+ assert companies(:first_firm).clients_of_firm(true).empty?, "37signals has no clients after destroy all and refresh"
633
+ end
634
+
635
+ def test_dependence
636
+ firm = companies(:first_firm)
637
+ assert_equal 2, firm.clients.size
638
+ firm.destroy
639
+ assert Client.find(:all, :conditions => "firm_id=#{firm.id}").empty?
640
+ end
641
+
642
+ def test_destroy_dependent_when_deleted_from_association
643
+ firm = Firm.find(:first)
644
+ assert_equal 2, firm.clients.size
645
+
646
+ client = firm.clients.first
647
+ firm.clients.delete(client)
648
+
649
+ assert_raise(ActiveRecord::RecordNotFound) { Client.find(client.id) }
650
+ assert_raise(ActiveRecord::RecordNotFound) { firm.clients.find(client.id) }
651
+ assert_equal 1, firm.clients.size
652
+ end
653
+
654
+ def test_three_levels_of_dependence
655
+ topic = Topic.create "title" => "neat and simple"
656
+ reply = topic.replies.create "title" => "neat and simple", "content" => "still digging it"
657
+ silly_reply = reply.replies.create "title" => "neat and simple", "content" => "ain't complaining"
658
+
659
+ assert_nothing_raised { topic.destroy }
660
+ end
661
+
662
+ uses_transaction :test_dependence_with_transaction_support_on_failure
663
+ def test_dependence_with_transaction_support_on_failure
664
+ firm = companies(:first_firm)
665
+ clients = firm.clients
666
+ assert_equal 2, clients.length
667
+ clients.last.instance_eval { def before_destroy() raise "Trigger rollback" end }
668
+
669
+ firm.destroy rescue "do nothing"
670
+
671
+ assert_equal 2, Client.find(:all, :conditions => "firm_id=#{firm.id}").size
672
+ end
673
+
674
+ def test_dependence_on_account
675
+ num_accounts = Account.count
676
+ companies(:first_firm).destroy
677
+ assert_equal num_accounts - 1, Account.count
678
+ end
679
+
680
+ def test_depends_and_nullify
681
+ num_accounts = Account.count
682
+ num_companies = Company.count
683
+
684
+ core = companies(:rails_core)
685
+ assert_equal accounts(:rails_core_account), core.account
686
+ assert_equal companies(:leetsoft, :jadedpixel), core.companies
687
+ core.destroy
688
+ assert_nil accounts(:rails_core_account).reload.firm_id
689
+ assert_nil companies(:leetsoft).reload.client_of
690
+ assert_nil companies(:jadedpixel).reload.client_of
691
+
692
+
693
+ assert_equal num_accounts, Account.count
694
+ end
695
+
696
+ def test_included_in_collection
697
+ assert companies(:first_firm).clients.include?(Client.find(2))
698
+ end
699
+
700
+ def test_adding_array_and_collection
701
+ assert_nothing_raised { Firm.find(:first).clients + Firm.find(:all).last.clients }
702
+ end
703
+
704
+ def test_find_all_without_conditions
705
+ firm = companies(:first_firm)
706
+ assert_equal 2, firm.clients.find(:all).length
707
+ end
708
+
709
+ def test_replace_with_less
710
+ firm = Firm.find(:first)
711
+ firm.clients = [companies(:first_client)]
712
+ assert firm.save, "Could not save firm"
713
+ firm.reload
714
+ assert_equal 1, firm.clients.length
715
+ end
716
+
717
+ def test_replace_with_less_and_dependent_nullify
718
+ num_companies = Company.count
719
+ companies(:rails_core).companies = []
720
+ assert_equal num_companies, Company.count
721
+ end
722
+
723
+ def test_replace_with_new
724
+ firm = Firm.find(:first)
725
+ firm.clients = [companies(:second_client), Client.new("name" => "New Client")]
726
+ firm.save
727
+ firm.reload
728
+ assert_equal 2, firm.clients.length
729
+ assert !firm.clients.include?(:first_client)
730
+ end
731
+
732
+ def test_replace_on_new_object
733
+ firm = Firm.new("name" => "New Firm")
734
+ firm.clients = [companies(:second_client), Client.new("name" => "New Client")]
735
+ assert firm.save
736
+ firm.reload
737
+ assert_equal 2, firm.clients.length
738
+ assert firm.clients.include?(Client.find_by_name("New Client"))
739
+ end
740
+
741
+ def test_get_ids
742
+ assert_equal [companies(:first_client).id, companies(:second_client).id], companies(:first_firm).client_ids
743
+ end
744
+
745
+ def test_assign_ids
746
+ firm = Firm.new("name" => "Apple")
747
+ firm.client_ids = [companies(:first_client).id, companies(:second_client).id]
748
+ firm.save
749
+ firm.reload
750
+ assert_equal 2, firm.clients.length
751
+ assert firm.clients.include?(companies(:second_client))
752
+ end
753
+
754
+ def test_assign_ids_ignoring_blanks
755
+ firm = Firm.create!(:name => 'Apple')
756
+ firm.client_ids = [companies(:first_client).id, nil, companies(:second_client).id, '']
757
+ firm.save!
758
+
759
+ assert_equal 2, firm.clients(true).size
760
+ assert firm.clients.include?(companies(:second_client))
761
+ end
762
+
763
+ def test_get_ids_for_through
764
+ assert_equal [comments(:eager_other_comment1).id], authors(:mary).comment_ids
765
+ end
766
+
767
+ def test_modifying_a_through_a_has_many_should_raise
768
+ [
769
+ lambda { authors(:mary).comment_ids = [comments(:greetings).id, comments(:more_greetings).id] },
770
+ lambda { authors(:mary).comments = [comments(:greetings), comments(:more_greetings)] },
771
+ lambda { authors(:mary).comments << Comment.create!(:body => "Yay", :post_id => 424242) },
772
+ lambda { authors(:mary).comments.delete(authors(:mary).comments.first) },
773
+ ].each {|block| assert_raise(ActiveRecord::HasManyThroughCantAssociateThroughHasManyReflection, &block) }
774
+ end
775
+
776
+
777
+ def test_assign_ids_for_through_a_belongs_to
778
+ post = Post.new(:title => "Assigning IDs works!", :body => "You heared it here first, folks!")
779
+ post.person_ids = [people(:david).id, people(:michael).id]
780
+ post.save
781
+ post.reload
782
+ assert_equal 2, post.people.length
783
+ assert post.people.include?(people(:david))
784
+ end
785
+
786
+ def test_dynamic_find_should_respect_association_order_for_through
787
+ assert_equal Comment.find(10), authors(:david).comments_desc.find(:first, :conditions => "comments.type = 'SpecialComment'")
788
+ assert_equal Comment.find(10), authors(:david).comments_desc.find_by_type('SpecialComment')
789
+ end
790
+
791
+ def test_dynamic_find_order_should_override_association_order_for_through
792
+ assert_equal Comment.find(3), authors(:david).comments_desc.find(:first, :conditions => "comments.type = 'SpecialComment'", :order => 'comments.id')
793
+ assert_equal Comment.find(3), authors(:david).comments_desc.find_by_type('SpecialComment', :order => 'comments.id')
794
+ end
795
+
796
+ def test_dynamic_find_all_should_respect_association_order_for_through
797
+ assert_equal [Comment.find(10), Comment.find(7), Comment.find(6), Comment.find(3)], authors(:david).comments_desc.find(:all, :conditions => "comments.type = 'SpecialComment'")
798
+ assert_equal [Comment.find(10), Comment.find(7), Comment.find(6), Comment.find(3)], authors(:david).comments_desc.find_all_by_type('SpecialComment')
799
+ end
800
+
801
+ def test_dynamic_find_all_order_should_override_association_order_for_through
802
+ 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')
803
+ 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')
804
+ end
805
+
806
+ def test_dynamic_find_all_should_respect_association_limit_for_through
807
+ assert_equal 1, authors(:david).limited_comments.find(:all, :conditions => "comments.type = 'SpecialComment'").length
808
+ assert_equal 1, authors(:david).limited_comments.find_all_by_type('SpecialComment').length
809
+ end
810
+
811
+ def test_dynamic_find_all_order_should_override_association_limit_for_through
812
+ assert_equal 4, authors(:david).limited_comments.find(:all, :conditions => "comments.type = 'SpecialComment'", :limit => 9_000).length
813
+ assert_equal 4, authors(:david).limited_comments.find_all_by_type('SpecialComment', :limit => 9_000).length
814
+ end
815
+
816
+ def test_find_all_include_over_the_same_table_for_through
817
+ assert_equal 2, people(:michael).posts.find(:all, :include => :people).length
818
+ end
819
+
820
+ def test_has_many_through_respects_hash_conditions
821
+ assert_equal authors(:david).hello_posts, authors(:david).hello_posts_with_hash_conditions
822
+ assert_equal authors(:david).hello_post_comments, authors(:david).hello_post_comments_with_hash_conditions
823
+ end
824
+
825
+ def test_include_uses_array_include_after_loaded
826
+ firm = companies(:first_firm)
827
+ firm.clients.class # force load target
828
+
829
+ client = firm.clients.first
830
+
831
+ assert_no_queries do
832
+ assert firm.clients.loaded?
833
+ assert firm.clients.include?(client)
834
+ end
835
+ end
836
+
837
+ def test_include_checks_if_record_exists_if_target_not_loaded
838
+ firm = companies(:first_firm)
839
+ client = firm.clients.first
840
+
841
+ firm.reload
842
+ assert ! firm.clients.loaded?
843
+ assert_queries(1) do
844
+ assert firm.clients.include?(client)
845
+ end
846
+ assert ! firm.clients.loaded?
847
+ end
848
+
849
+ def test_include_loads_collection_if_target_uses_finder_sql
850
+ firm = companies(:first_firm)
851
+ client = firm.clients_using_sql.first
852
+
853
+ firm.reload
854
+ assert ! firm.clients_using_sql.loaded?
855
+ assert firm.clients_using_sql.include?(client)
856
+ assert firm.clients_using_sql.loaded?
857
+ end
858
+
859
+
860
+ def test_include_returns_false_for_non_matching_record_to_verify_scoping
861
+ firm = companies(:first_firm)
862
+ client = Client.create!(:name => 'Not Associated')
863
+
864
+ assert ! firm.clients.loaded?
865
+ assert ! firm.clients.include?(client)
866
+ end
867
+
868
+ def test_calling_first_or_last_on_association_should_not_load_association
869
+ firm = companies(:first_firm)
870
+ firm.clients.first
871
+ firm.clients.last
872
+ assert !firm.clients.loaded?
873
+ end
874
+
875
+ def test_calling_first_or_last_on_loaded_association_should_not_fetch_with_query
876
+ firm = companies(:first_firm)
877
+ firm.clients.class # force load target
878
+ assert firm.clients.loaded?
879
+
880
+ assert_no_queries do
881
+ firm.clients.first
882
+ assert_equal 2, firm.clients.first(2).size
883
+ firm.clients.last
884
+ assert_equal 2, firm.clients.last(2).size
885
+ end
886
+ end
887
+
888
+ def test_calling_first_or_last_on_existing_record_with_build_should_load_association
889
+ firm = companies(:first_firm)
890
+ firm.clients.build(:name => 'Foo')
891
+ assert !firm.clients.loaded?
892
+
893
+ assert_queries 1 do
894
+ firm.clients.first
895
+ firm.clients.last
896
+ end
897
+
898
+ assert firm.clients.loaded?
899
+ end
900
+
901
+ def test_calling_first_or_last_on_new_record_should_not_run_queries
902
+ firm = Firm.new
903
+
904
+ assert_no_queries do
905
+ firm.clients.first
906
+ firm.clients.last
907
+ end
908
+ end
909
+
910
+ def test_calling_first_or_last_with_find_options_on_loaded_association_should_fetch_with_query
911
+ firm = companies(:first_firm)
912
+ firm.clients.class # force load target
913
+
914
+ assert_queries 2 do
915
+ assert firm.clients.loaded?
916
+ firm.clients.first(:order => 'name')
917
+ firm.clients.last(:order => 'name')
918
+ end
919
+ end
920
+
921
+ def test_calling_first_or_last_with_integer_on_association_should_load_association
922
+ firm = companies(:first_firm)
923
+
924
+ assert_queries 1 do
925
+ firm.clients.first(2)
926
+ firm.clients.last(2)
927
+ end
928
+
929
+ assert firm.clients.loaded?
930
+ end
931
+
932
+ end