ibm_db 3.0.4-x86-mingw32 → 3.0.5-x86-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (463) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +4 -1
  3. data/LICENSE +1 -1
  4. data/MANIFEST +14 -14
  5. data/README +225 -225
  6. data/ext/Makefile.nt32 +181 -181
  7. data/ext/Makefile.nt32.191 +212 -212
  8. data/ext/extconf.rb +291 -291
  9. data/ext/ibm_db.c +11887 -11884
  10. data/ext/ruby_ibm_db.h +241 -241
  11. data/ext/ruby_ibm_db_cli.c +866 -866
  12. data/ext/ruby_ibm_db_cli.h +500 -500
  13. data/init.rb +41 -41
  14. data/lib/IBM_DB.rb +27 -27
  15. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +3177 -3177
  16. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +1 -1
  17. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
  18. data/lib/mswin32/ibm_db.rb +122 -122
  19. data/lib/mswin32/rb21x/i386/ibm_db.so +0 -0
  20. data/lib/mswin32/rb22x/i386/ibm_db.so +0 -0
  21. data/lib/mswin32/rb23x/i386/ibm_db.so +0 -0
  22. data/test/active_record/connection_adapters/fake_adapter.rb +46 -46
  23. data/test/assets/example.log +1 -1
  24. data/test/assets/test.txt +1 -1
  25. data/test/cases/adapter_test.rb +276 -261
  26. data/test/cases/aggregations_test.rb +158 -158
  27. data/test/cases/ar_schema_test.rb +161 -161
  28. data/test/cases/associations/association_scope_test.rb +21 -21
  29. data/test/cases/associations/belongs_to_associations_test.rb +1029 -1029
  30. data/test/cases/associations/callbacks_test.rb +192 -192
  31. data/test/cases/associations/cascaded_eager_loading_test.rb +188 -188
  32. data/test/cases/associations/deprecated_counter_cache_on_has_many_through_test.rb +26 -26
  33. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -36
  34. data/test/cases/associations/eager_load_nested_include_test.rb +128 -128
  35. data/test/cases/associations/eager_singularization_test.rb +148 -148
  36. data/test/cases/associations/eager_test.rb +1429 -1411
  37. data/test/cases/associations/extension_test.rb +82 -82
  38. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +972 -932
  39. data/test/cases/associations/has_many_associations_test.rb +2182 -2162
  40. data/test/cases/associations/has_many_through_associations_test.rb +1204 -1204
  41. data/test/cases/associations/has_one_associations_test.rb +610 -610
  42. data/test/cases/associations/has_one_through_associations_test.rb +380 -380
  43. data/test/cases/associations/inner_join_association_test.rb +139 -139
  44. data/test/cases/associations/inverse_associations_test.rb +706 -693
  45. data/test/cases/associations/join_model_test.rb +754 -754
  46. data/test/cases/associations/nested_through_associations_test.rb +579 -579
  47. data/test/cases/associations/required_test.rb +82 -82
  48. data/test/cases/associations_test.rb +380 -380
  49. data/test/cases/attribute_decorators_test.rb +125 -125
  50. data/test/cases/attribute_methods/read_test.rb +60 -60
  51. data/test/cases/attribute_methods/serialization_test.rb +29 -29
  52. data/test/cases/attribute_methods_test.rb +952 -952
  53. data/test/cases/attribute_set_test.rb +210 -200
  54. data/test/cases/attribute_test.rb +180 -180
  55. data/test/cases/attributes_test.rb +136 -136
  56. data/test/cases/autosave_association_test.rb +1595 -1595
  57. data/test/cases/base_test.rb +1664 -1638
  58. data/test/cases/batches_test.rb +212 -212
  59. data/test/cases/binary_test.rb +52 -52
  60. data/test/cases/bind_parameter_test.rb +100 -100
  61. data/test/cases/calculations_test.rb +646 -646
  62. data/test/cases/callbacks_test.rb +543 -543
  63. data/test/cases/clone_test.rb +40 -40
  64. data/test/cases/coders/yaml_column_test.rb +63 -63
  65. data/test/cases/column_alias_test.rb +17 -17
  66. data/test/cases/column_definition_test.rb +123 -123
  67. data/test/cases/connection_adapters/adapter_leasing_test.rb +54 -54
  68. data/test/cases/connection_adapters/connection_handler_test.rb +53 -53
  69. data/test/cases/connection_adapters/connection_specification_test.rb +12 -12
  70. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +293 -293
  71. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +65 -65
  72. data/test/cases/connection_adapters/quoting_test.rb +13 -13
  73. data/test/cases/connection_adapters/schema_cache_test.rb +56 -56
  74. data/test/cases/connection_adapters/type_lookup_test.rb +110 -110
  75. data/test/cases/connection_management_test.rb +122 -122
  76. data/test/cases/connection_pool_test.rb +346 -346
  77. data/test/cases/connection_specification/resolver_test.rb +116 -116
  78. data/test/cases/core_test.rb +112 -112
  79. data/test/cases/counter_cache_test.rb +209 -209
  80. data/test/cases/custom_locking_test.rb +17 -17
  81. data/test/cases/database_statements_test.rb +19 -19
  82. data/test/cases/date_time_test.rb +61 -61
  83. data/test/cases/defaults_test.rb +223 -223
  84. data/test/cases/dirty_test.rb +785 -775
  85. data/test/cases/disconnected_test.rb +28 -28
  86. data/test/cases/dup_test.rb +157 -157
  87. data/test/cases/enum_test.rb +290 -290
  88. data/test/cases/explain_subscriber_test.rb +64 -64
  89. data/test/cases/explain_test.rb +76 -76
  90. data/test/cases/finder_respond_to_test.rb +60 -60
  91. data/test/cases/finder_test.rb +1169 -1166
  92. data/test/cases/fixture_set/file_test.rb +138 -138
  93. data/test/cases/fixtures_test.rb +908 -897
  94. data/test/cases/forbidden_attributes_protection_test.rb +99 -99
  95. data/test/cases/habtm_destroy_order_test.rb +61 -61
  96. data/test/cases/helper.rb +210 -210
  97. data/test/cases/hot_compatibility_test.rb +54 -54
  98. data/test/cases/i18n_test.rb +45 -45
  99. data/test/cases/inheritance_test.rb +375 -375
  100. data/test/cases/integration_test.rb +139 -139
  101. data/test/cases/invalid_connection_test.rb +22 -22
  102. data/test/cases/invalid_date_test.rb +32 -32
  103. data/test/cases/invertible_migration_test.rb +295 -295
  104. data/test/cases/json_serialization_test.rb +302 -302
  105. data/test/cases/locking_test.rb +477 -477
  106. data/test/cases/log_subscriber_test.rb +136 -136
  107. data/test/cases/migration/change_schema_test - Copy.rb +448 -448
  108. data/test/cases/migration/change_schema_test.rb +512 -472
  109. data/test/cases/migration/change_table_test.rb +224 -224
  110. data/test/cases/migration/column_attributes_test.rb +192 -192
  111. data/test/cases/migration/column_positioning_test.rb +56 -56
  112. data/test/cases/migration/columns_test.rb +304 -304
  113. data/test/cases/migration/command_recorder_test.rb +305 -305
  114. data/test/cases/migration/create_join_table_test.rb +148 -148
  115. data/test/cases/migration/foreign_key_test - Changed.rb +325 -325
  116. data/test/cases/migration/foreign_key_test.rb +328 -360
  117. data/test/cases/migration/helper.rb +39 -39
  118. data/test/cases/migration/index_test.rb +216 -216
  119. data/test/cases/migration/logger_test.rb +36 -36
  120. data/test/cases/migration/pending_migrations_test.rb +53 -53
  121. data/test/cases/migration/references_foreign_key_test.rb +169 -214
  122. data/test/cases/migration/references_index_test.rb +101 -101
  123. data/test/cases/migration/references_statements_test.rb +116 -116
  124. data/test/cases/migration/rename_table_test.rb +93 -93
  125. data/test/cases/migration/table_and_index_test.rb +24 -24
  126. data/test/cases/migration_test.rb +959 -959
  127. data/test/cases/migrator_test.rb +388 -388
  128. data/test/cases/mixin_test.rb +70 -70
  129. data/test/cases/modules_test.rb +173 -173
  130. data/test/cases/multiparameter_attributes_test.rb +350 -350
  131. data/test/cases/multiple_db_test.rb +115 -115
  132. data/test/cases/nested_attributes_test.rb +1070 -1057
  133. data/test/cases/nested_attributes_with_callbacks_test.rb +144 -144
  134. data/test/cases/persistence_test.rb +909 -909
  135. data/test/cases/pooled_connections_test.rb +81 -81
  136. data/test/cases/primary_keys_test.rb +237 -237
  137. data/test/cases/query_cache_test.rb +326 -326
  138. data/test/cases/quoting_test.rb +156 -156
  139. data/test/cases/readonly_test.rb +118 -118
  140. data/test/cases/reaper_test.rb +85 -85
  141. data/test/cases/reflection_test.rb +463 -454
  142. data/test/cases/relation/delegation_test.rb +68 -68
  143. data/test/cases/relation/merging_test.rb +161 -161
  144. data/test/cases/relation/mutation_test.rb +165 -165
  145. data/test/cases/relation/predicate_builder_test.rb +14 -14
  146. data/test/cases/relation/where_chain_test.rb +181 -181
  147. data/test/cases/relation/where_test.rb +300 -300
  148. data/test/cases/relation/where_test2.rb +36 -36
  149. data/test/cases/relation_test.rb +319 -297
  150. data/test/cases/relations_test.rb +1815 -1815
  151. data/test/cases/reload_models_test.rb +22 -22
  152. data/test/cases/result_test.rb +80 -80
  153. data/test/cases/sanitize_test.rb +83 -83
  154. data/test/cases/schema_dumper_test.rb +463 -463
  155. data/test/cases/scoping/default_scoping_test.rb +454 -454
  156. data/test/cases/scoping/named_scoping_test.rb +524 -524
  157. data/test/cases/scoping/relation_scoping_test.rb +357 -357
  158. data/test/cases/serialization_test.rb +104 -104
  159. data/test/cases/serialized_attribute_test.rb +277 -277
  160. data/test/cases/statement_cache_test.rb +98 -98
  161. data/test/cases/store_test.rb +194 -194
  162. data/test/cases/tasks/database_tasks_test.rb +398 -396
  163. data/test/cases/tasks/mysql_rake_test.rb +324 -311
  164. data/test/cases/tasks/postgresql_rake_test.rb +250 -245
  165. data/test/cases/tasks/sqlite_rake_test.rb +193 -193
  166. data/test/cases/test_case.rb +123 -123
  167. data/test/cases/timestamp_test.rb +467 -468
  168. data/test/cases/transaction_callbacks_test.rb +452 -452
  169. data/test/cases/transaction_isolation_test.rb +106 -106
  170. data/test/cases/transactions_test.rb +817 -817
  171. data/test/cases/type/decimal_test.rb +56 -51
  172. data/test/cases/type/integer_test.rb +121 -121
  173. data/test/cases/type/string_test.rb +36 -36
  174. data/test/cases/type/type_map_test.rb +177 -177
  175. data/test/cases/type/unsigned_integer_test.rb +18 -18
  176. data/test/cases/types_test.rb +141 -141
  177. data/test/cases/unconnected_test.rb +33 -33
  178. data/test/cases/validations/association_validation_test.rb +86 -86
  179. data/test/cases/validations/i18n_generate_message_validation_test.rb +84 -84
  180. data/test/cases/validations/i18n_validation_test.rb +90 -90
  181. data/test/cases/validations/length_validation_test.rb +47 -47
  182. data/test/cases/validations/presence_validation_test.rb +68 -68
  183. data/test/cases/validations/uniqueness_validation_test.rb +457 -434
  184. data/test/cases/validations_repair_helper.rb +23 -23
  185. data/test/cases/validations_test.rb +165 -165
  186. data/test/cases/view_test.rb +119 -113
  187. data/test/cases/xml_serialization_test.rb +457 -457
  188. data/test/cases/yaml_serialization_test.rb +126 -86
  189. data/test/config.rb +5 -5
  190. data/test/config.yml +154 -154
  191. data/test/connections/native_ibm_db/connection.rb +43 -43
  192. data/test/fixtures/accounts.yml +29 -29
  193. data/test/fixtures/admin/accounts.yml +2 -2
  194. data/test/fixtures/admin/randomly_named_a9.yml +7 -7
  195. data/test/fixtures/admin/randomly_named_b0.yml +7 -7
  196. data/test/fixtures/admin/users.yml +10 -10
  197. data/test/fixtures/author_addresses.yml +17 -17
  198. data/test/fixtures/author_favorites.yml +3 -3
  199. data/test/fixtures/authors.yml +23 -23
  200. data/test/fixtures/binaries.yml +133 -133
  201. data/test/fixtures/books.yml +11 -11
  202. data/test/fixtures/bulbs.yml +5 -5
  203. data/test/fixtures/cars.yml +9 -9
  204. data/test/fixtures/categories.yml +19 -19
  205. data/test/fixtures/categories/special_categories.yml +9 -9
  206. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -4
  207. data/test/fixtures/categories_ordered.yml +7 -7
  208. data/test/fixtures/categories_posts.yml +31 -31
  209. data/test/fixtures/categorizations.yml +23 -23
  210. data/test/fixtures/clubs.yml +8 -8
  211. data/test/fixtures/collections.yml +3 -3
  212. data/test/fixtures/colleges.yml +3 -3
  213. data/test/fixtures/comments.yml +65 -65
  214. data/test/fixtures/companies.yml +67 -67
  215. data/test/fixtures/computers.yml +10 -10
  216. data/test/fixtures/courses.yml +8 -8
  217. data/test/fixtures/customers.yml +25 -25
  218. data/test/fixtures/dashboards.yml +6 -6
  219. data/test/fixtures/developers.yml +21 -21
  220. data/test/fixtures/developers_projects.yml +16 -16
  221. data/test/fixtures/dog_lovers.yml +7 -7
  222. data/test/fixtures/dogs.yml +4 -4
  223. data/test/fixtures/doubloons.yml +3 -3
  224. data/test/fixtures/edges.yml +5 -5
  225. data/test/fixtures/entrants.yml +14 -14
  226. data/test/fixtures/essays.yml +6 -6
  227. data/test/fixtures/faces.yml +11 -11
  228. data/test/fixtures/fk_test_has_fk.yml +3 -3
  229. data/test/fixtures/fk_test_has_pk.yml +1 -1
  230. data/test/fixtures/friendships.yml +4 -4
  231. data/test/fixtures/funny_jokes.yml +10 -10
  232. data/test/fixtures/interests.yml +33 -33
  233. data/test/fixtures/items.yml +3 -3
  234. data/test/fixtures/jobs.yml +7 -7
  235. data/test/fixtures/legacy_things.yml +3 -3
  236. data/test/fixtures/mateys.yml +4 -4
  237. data/test/fixtures/member_details.yml +8 -8
  238. data/test/fixtures/member_types.yml +6 -6
  239. data/test/fixtures/members.yml +11 -11
  240. data/test/fixtures/memberships.yml +34 -34
  241. data/test/fixtures/men.yml +5 -5
  242. data/test/fixtures/minimalistics.yml +2 -2
  243. data/test/fixtures/minivans.yml +5 -5
  244. data/test/fixtures/mixed_case_monkeys.yml +6 -6
  245. data/test/fixtures/mixins.yml +29 -29
  246. data/test/fixtures/movies.yml +7 -7
  247. data/test/fixtures/naked/csv/accounts.csv +1 -1
  248. data/test/fixtures/naked/yml/accounts.yml +1 -1
  249. data/test/fixtures/naked/yml/companies.yml +1 -1
  250. data/test/fixtures/naked/yml/courses.yml +1 -1
  251. data/test/fixtures/organizations.yml +5 -5
  252. data/test/fixtures/other_topics.yml +42 -42
  253. data/test/fixtures/owners.yml +9 -9
  254. data/test/fixtures/parrots.yml +27 -27
  255. data/test/fixtures/parrots_pirates.yml +7 -7
  256. data/test/fixtures/people.yml +24 -24
  257. data/test/fixtures/peoples_treasures.yml +3 -3
  258. data/test/fixtures/pets.yml +19 -19
  259. data/test/fixtures/pirates.yml +12 -12
  260. data/test/fixtures/posts.yml +80 -80
  261. data/test/fixtures/price_estimates.yml +7 -7
  262. data/test/fixtures/products.yml +4 -4
  263. data/test/fixtures/projects.yml +7 -7
  264. data/test/fixtures/randomly_named_a9.yml +7 -7
  265. data/test/fixtures/ratings.yml +14 -14
  266. data/test/fixtures/readers.yml +11 -11
  267. data/test/fixtures/references.yml +17 -17
  268. data/test/fixtures/reserved_words/distinct.yml +5 -5
  269. data/test/fixtures/reserved_words/distinct_select.yml +11 -11
  270. data/test/fixtures/reserved_words/group.yml +14 -14
  271. data/test/fixtures/reserved_words/select.yml +8 -8
  272. data/test/fixtures/reserved_words/values.yml +7 -7
  273. data/test/fixtures/ships.yml +6 -6
  274. data/test/fixtures/speedometers.yml +8 -8
  275. data/test/fixtures/sponsors.yml +12 -12
  276. data/test/fixtures/string_key_objects.yml +7 -7
  277. data/test/fixtures/subscribers.yml +10 -10
  278. data/test/fixtures/subscriptions.yml +12 -12
  279. data/test/fixtures/taggings.yml +78 -78
  280. data/test/fixtures/tags.yml +11 -11
  281. data/test/fixtures/tasks.yml +7 -7
  282. data/test/fixtures/teapots.yml +3 -3
  283. data/test/fixtures/to_be_linked/accounts.yml +2 -2
  284. data/test/fixtures/to_be_linked/users.yml +10 -10
  285. data/test/fixtures/topics.yml +49 -49
  286. data/test/fixtures/toys.yml +14 -14
  287. data/test/fixtures/traffic_lights.yml +9 -9
  288. data/test/fixtures/treasures.yml +10 -10
  289. data/test/fixtures/uuid_children.yml +3 -3
  290. data/test/fixtures/uuid_parents.yml +2 -2
  291. data/test/fixtures/variants.yml +4 -4
  292. data/test/fixtures/vegetables.yml +19 -19
  293. data/test/fixtures/vertices.yml +3 -3
  294. data/test/fixtures/warehouse_things.yml +2 -2
  295. data/test/fixtures/zines.yml +5 -5
  296. data/test/ibm_db_test.rb +24 -24
  297. data/test/migrations/10_urban/9_add_expressions.rb +11 -11
  298. data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -15
  299. data/test/migrations/magic/1_currencies_have_symbols.rb +12 -12
  300. data/test/migrations/missing/1000_people_have_middle_names.rb +8 -8
  301. data/test/migrations/missing/1_people_have_last_names.rb +8 -8
  302. data/test/migrations/missing/3_we_need_reminders.rb +11 -11
  303. data/test/migrations/missing/4_innocent_jointable.rb +11 -11
  304. data/test/migrations/rename/1_we_need_things.rb +10 -10
  305. data/test/migrations/rename/2_rename_things.rb +8 -8
  306. data/test/migrations/to_copy/1_people_have_hobbies.rb +9 -9
  307. data/test/migrations/to_copy/2_people_have_descriptions.rb +9 -9
  308. data/test/migrations/to_copy2/1_create_articles.rb +7 -7
  309. data/test/migrations/to_copy2/2_create_comments.rb +7 -7
  310. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +9 -9
  311. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +9 -9
  312. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +9 -9
  313. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +7 -7
  314. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +7 -7
  315. data/test/migrations/valid/1_valid_people_have_last_names.rb +9 -9
  316. data/test/migrations/valid/2_we_need_reminders.rb +11 -11
  317. data/test/migrations/valid/3_innocent_jointable.rb +11 -11
  318. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +9 -9
  319. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +11 -11
  320. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +11 -11
  321. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +9 -9
  322. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +12 -12
  323. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +12 -12
  324. data/test/migrations/version_check/20131219224947_migration_version_check.rb +8 -8
  325. data/test/models/admin.rb +4 -4
  326. data/test/models/admin/account.rb +2 -2
  327. data/test/models/admin/randomly_named_c1.rb +3 -3
  328. data/test/models/admin/user.rb +40 -40
  329. data/test/models/aircraft.rb +4 -4
  330. data/test/models/arunit2_model.rb +3 -3
  331. data/test/models/author.rb +212 -212
  332. data/test/models/auto_id.rb +4 -4
  333. data/test/models/autoloadable/extra_firm.rb +2 -2
  334. data/test/models/binary.rb +1 -1
  335. data/test/models/bird.rb +12 -12
  336. data/test/models/book.rb +18 -18
  337. data/test/models/boolean.rb +2 -2
  338. data/test/models/bulb.rb +51 -51
  339. data/test/models/cake_designer.rb +3 -3
  340. data/test/models/car.rb +26 -26
  341. data/test/models/carrier.rb +2 -2
  342. data/test/models/categorization.rb +19 -19
  343. data/test/models/category.rb +35 -35
  344. data/test/models/chef.rb +7 -3
  345. data/test/models/citation.rb +3 -3
  346. data/test/models/club.rb +23 -23
  347. data/test/models/college.rb +10 -10
  348. data/test/models/column.rb +3 -3
  349. data/test/models/column_name.rb +3 -3
  350. data/test/models/comment.rb +64 -64
  351. data/test/models/company.rb +228 -225
  352. data/test/models/company_in_module.rb +98 -98
  353. data/test/models/computer.rb +3 -3
  354. data/test/models/contact.rb +41 -41
  355. data/test/models/contract.rb +20 -20
  356. data/test/models/country.rb +7 -7
  357. data/test/models/course.rb +6 -6
  358. data/test/models/customer.rb +77 -77
  359. data/test/models/customer_carrier.rb +14 -14
  360. data/test/models/dashboard.rb +3 -3
  361. data/test/models/default.rb +2 -2
  362. data/test/models/department.rb +4 -4
  363. data/test/models/developer.rb +255 -252
  364. data/test/models/dog.rb +5 -5
  365. data/test/models/dog_lover.rb +5 -5
  366. data/test/models/doubloon.rb +12 -12
  367. data/test/models/drink_designer.rb +3 -3
  368. data/test/models/edge.rb +5 -5
  369. data/test/models/electron.rb +5 -5
  370. data/test/models/engine.rb +4 -4
  371. data/test/models/entrant.rb +3 -3
  372. data/test/models/essay.rb +5 -5
  373. data/test/models/event.rb +2 -2
  374. data/test/models/eye.rb +37 -37
  375. data/test/models/face.rb +9 -9
  376. data/test/models/friendship.rb +6 -6
  377. data/test/models/guid.rb +1 -1
  378. data/test/models/hotel.rb +9 -6
  379. data/test/models/image.rb +3 -3
  380. data/test/models/interest.rb +5 -5
  381. data/test/models/invoice.rb +4 -4
  382. data/test/models/item.rb +7 -7
  383. data/test/models/job.rb +7 -7
  384. data/test/models/joke.rb +7 -7
  385. data/test/models/keyboard.rb +3 -3
  386. data/test/models/legacy_thing.rb +3 -3
  387. data/test/models/lesson.rb +11 -11
  388. data/test/models/line_item.rb +3 -3
  389. data/test/models/liquid.rb +4 -4
  390. data/test/models/man.rb +11 -11
  391. data/test/models/matey.rb +4 -4
  392. data/test/models/member.rb +41 -41
  393. data/test/models/member_detail.rb +7 -7
  394. data/test/models/member_type.rb +3 -3
  395. data/test/models/membership.rb +35 -35
  396. data/test/models/minimalistic.rb +2 -2
  397. data/test/models/minivan.rb +9 -9
  398. data/test/models/mixed_case_monkey.rb +3 -3
  399. data/test/models/molecule.rb +6 -6
  400. data/test/models/movie.rb +5 -5
  401. data/test/models/order.rb +4 -4
  402. data/test/models/organization.rb +14 -14
  403. data/test/models/owner.rb +34 -34
  404. data/test/models/parrot.rb +29 -29
  405. data/test/models/person.rb +143 -143
  406. data/test/models/personal_legacy_thing.rb +4 -4
  407. data/test/models/pet.rb +15 -15
  408. data/test/models/pirate.rb +92 -92
  409. data/test/models/possession.rb +3 -3
  410. data/test/models/post.rb +264 -264
  411. data/test/models/price_estimate.rb +4 -4
  412. data/test/models/professor.rb +5 -5
  413. data/test/models/project.rb +31 -29
  414. data/test/models/publisher.rb +2 -2
  415. data/test/models/publisher/article.rb +4 -4
  416. data/test/models/publisher/magazine.rb +3 -3
  417. data/test/models/randomly_named_c1.rb +3 -3
  418. data/test/models/rating.rb +4 -4
  419. data/test/models/reader.rb +23 -23
  420. data/test/models/record.rb +2 -2
  421. data/test/models/reference.rb +22 -22
  422. data/test/models/reply.rb +61 -61
  423. data/test/models/ship.rb +33 -33
  424. data/test/models/ship_part.rb +7 -7
  425. data/test/models/shop.rb +17 -17
  426. data/test/models/shop_account.rb +6 -6
  427. data/test/models/speedometer.rb +6 -6
  428. data/test/models/sponsor.rb +7 -7
  429. data/test/models/string_key_object.rb +3 -3
  430. data/test/models/student.rb +4 -4
  431. data/test/models/subject.rb +16 -16
  432. data/test/models/subscriber.rb +8 -8
  433. data/test/models/subscription.rb +4 -4
  434. data/test/models/tag.rb +7 -7
  435. data/test/models/tagging.rb +13 -13
  436. data/test/models/task.rb +5 -5
  437. data/test/models/topic.rb +124 -124
  438. data/test/models/toy.rb +6 -6
  439. data/test/models/traffic_light.rb +4 -4
  440. data/test/models/treasure.rb +14 -14
  441. data/test/models/treaty.rb +7 -7
  442. data/test/models/tyre.rb +11 -11
  443. data/test/models/uuid_child.rb +3 -3
  444. data/test/models/uuid_parent.rb +3 -3
  445. data/test/models/vegetables.rb +24 -24
  446. data/test/models/vehicle.rb +6 -6
  447. data/test/models/vertex.rb +9 -9
  448. data/test/models/warehouse_thing.rb +5 -5
  449. data/test/models/wheel.rb +3 -3
  450. data/test/models/without_table.rb +3 -3
  451. data/test/models/zine.rb +3 -3
  452. data/test/schema/mysql2_specific_schema.rb +58 -58
  453. data/test/schema/mysql_specific_schema.rb +70 -70
  454. data/test/schema/oracle_specific_schema.rb +43 -43
  455. data/test/schema/postgresql_specific_schema.rb +202 -202
  456. data/test/schema/schema.rb +952 -938
  457. data/test/schema/sqlite_specific_schema.rb +21 -21
  458. data/test/support/config.rb +43 -43
  459. data/test/support/connection.rb +22 -22
  460. data/test/support/connection_helper.rb +14 -14
  461. data/test/support/ddl_helper.rb +8 -8
  462. data/test/support/schema_dumping_helper.rb +20 -20
  463. metadata +2 -2
@@ -1,2162 +1,2182 @@
1
- require "cases/helper"
2
- require 'models/developer'
3
- require 'models/computer'
4
- require 'models/project'
5
- require 'models/company'
6
- require 'models/contract'
7
- require 'models/topic'
8
- require 'models/reply'
9
- require 'models/category'
10
- require 'models/image'
11
- require 'models/post'
12
- require 'models/author'
13
- require 'models/essay'
14
- require 'models/comment'
15
- require 'models/person'
16
- require 'models/reader'
17
- require 'models/tagging'
18
- require 'models/tag'
19
- require 'models/invoice'
20
- require 'models/line_item'
21
- require 'models/car'
22
- require 'models/bulb'
23
- require 'models/engine'
24
- require 'models/categorization'
25
- require 'models/minivan'
26
- require 'models/speedometer'
27
- require 'models/reference'
28
- require 'models/job'
29
- require 'models/college'
30
- require 'models/student'
31
- require 'models/pirate'
32
- require 'models/ship'
33
- require 'models/treasure'
34
- require 'models/parrot'
35
- require 'models/tyre'
36
- require 'models/subscriber'
37
- require 'models/subscription'
38
- require 'models/zine'
39
- require 'models/interest'
40
-
41
- class HasManyAssociationsTestForReorderWithJoinDependency < ActiveRecord::TestCase
42
- fixtures :authors, :posts, :comments, :author_addresses
43
-
44
- def test_should_generate_valid_sql
45
- author = authors(:david)
46
- # this can fail on adapters which require ORDER BY expressions to be included in the SELECT expression
47
- # if the reorder clauses are not correctly handled
48
- assert author.posts_with_comments_sorted_by_comment_id.where('comments.id > 0').reorder('posts.comments_count DESC', 'posts.tags_count DESC').last
49
- end
50
- end
51
-
52
- class HasManyAssociationsTestPrimaryKeys < ActiveRecord::TestCase
53
- fixtures :authors, :essays, :subscribers, :subscriptions, :people
54
-
55
- def test_custom_primary_key_on_new_record_should_fetch_with_query
56
- subscriber = Subscriber.new(nick: 'webster132')
57
- assert !subscriber.subscriptions.loaded?
58
-
59
- assert_queries 1 do
60
- assert_equal 2, subscriber.subscriptions.size
61
- end
62
-
63
- assert_equal subscriber.subscriptions, Subscription.where(subscriber_id: 'webster132')
64
- end
65
-
66
- def test_association_primary_key_on_new_record_should_fetch_with_query
67
- author = Author.new(:name => "David")
68
- assert !author.essays.loaded?
69
-
70
- assert_queries 1 do
71
- assert_equal 1, author.essays.size
72
- end
73
-
74
- assert_equal author.essays, Essay.where(writer_id: "David")
75
- end
76
-
77
- def test_has_many_custom_primary_key
78
- david = authors(:david)
79
- assert_equal david.essays, Essay.where(writer_id: "David")
80
- end
81
-
82
- def test_has_many_assignment_with_custom_primary_key
83
- david = people(:david)
84
-
85
- assert_equal ["A Modest Proposal"], david.essays.map(&:name)
86
- david.essays = [Essay.create!(name: "Remote Work" )]
87
- assert_equal ["Remote Work"], david.essays.map(&:name)
88
- end
89
-
90
- def test_blank_custom_primary_key_on_new_record_should_not_run_queries
91
- author = Author.new
92
- assert !author.essays.loaded?
93
-
94
- assert_queries 0 do
95
- assert_equal 0, author.essays.size
96
- end
97
- end
98
- end
99
-
100
- class HasManyAssociationsTest < ActiveRecord::TestCase
101
- fixtures :accounts, :categories, :companies, :developers, :projects,
102
- :developers_projects, :topics, :authors, :comments,
103
- :posts, :readers, :taggings, :cars, :jobs, :tags,
104
- :categorizations, :zines, :interests
105
-
106
- def setup
107
- Client.destroyed_client_ids.clear
108
- end
109
-
110
- def test_sti_subselect_count
111
- tag = Tag.first
112
- len = Post.tagged_with(tag.id).limit(10).size
113
- assert_operator len, :>, 0
114
- end
115
-
116
- def test_anonymous_has_many
117
- developer = Class.new(ActiveRecord::Base) {
118
- self.table_name = 'developers'
119
- dev = self
120
-
121
- developer_project = Class.new(ActiveRecord::Base) {
122
- self.table_name = 'developers_projects'
123
- belongs_to :developer, :anonymous_class => dev
124
- }
125
- has_many :developer_projects, :anonymous_class => developer_project, :foreign_key => 'developer_id'
126
- }
127
- dev = developer.first
128
- named = Developer.find(dev.id)
129
- assert_operator dev.developer_projects.count, :>, 0
130
- assert_equal named.projects.map(&:id).sort,
131
- dev.developer_projects.map(&:project_id).sort
132
- end
133
-
134
- def test_default_scope_on_relations_is_not_cached
135
- counter = 0
136
- posts = Class.new(ActiveRecord::Base) {
137
- self.table_name = 'posts'
138
- self.inheritance_column = 'not_there'
139
- post = self
140
-
141
- comments = Class.new(ActiveRecord::Base) {
142
- self.table_name = 'comments'
143
- self.inheritance_column = 'not_there'
144
- belongs_to :post, :anonymous_class => post
145
- default_scope -> {
146
- counter += 1
147
- where("id = :inc", :inc => counter)
148
- }
149
- }
150
- has_many :comments, :anonymous_class => comments, :foreign_key => 'post_id'
151
- }
152
- assert_equal 0, counter
153
- post = posts.first
154
- assert_equal 0, counter
155
- sql = capture_sql { post.comments.to_a }
156
- post.comments.reset
157
- assert_not_equal sql, capture_sql { post.comments.to_a }
158
- end
159
-
160
- def test_has_many_build_with_options
161
- college = College.create(name: 'UFMT')
162
- Student.create(active: true, college_id: college.id, name: 'Sarah')
163
-
164
- assert_equal college.students, Student.where(active: true, college_id: college.id)
165
- end
166
-
167
- def test_create_from_association_should_respect_default_scope
168
- car = Car.create(:name => 'honda')
169
- assert_equal 'honda', car.name
170
-
171
- bulb = Bulb.create
172
- assert_equal 'defaulty', bulb.name
173
-
174
- bulb = car.bulbs.build
175
- assert_equal 'defaulty', bulb.name
176
-
177
- bulb = car.bulbs.create
178
- assert_equal 'defaulty', bulb.name
179
-
180
- bulb = car.bulbs.create(:name => 'exotic')
181
- assert_equal 'exotic', bulb.name
182
- end
183
-
184
- def test_build_from_association_should_respect_scope
185
- author = Author.new
186
-
187
- post = author.thinking_posts.build
188
- assert_equal 'So I was thinking', post.title
189
- end
190
-
191
- def test_create_from_association_with_nil_values_should_work
192
- car = Car.create(:name => 'honda')
193
-
194
- bulb = car.bulbs.new(nil)
195
- assert_equal 'defaulty', bulb.name
196
-
197
- bulb = car.bulbs.build(nil)
198
- assert_equal 'defaulty', bulb.name
199
-
200
- bulb = car.bulbs.create(nil)
201
- assert_equal 'defaulty', bulb.name
202
- end
203
-
204
- def test_do_not_call_callbacks_for_delete_all
205
- car = Car.create(:name => 'honda')
206
- car.funky_bulbs.create!
207
- assert_nothing_raised { car.reload.funky_bulbs.delete_all }
208
- assert_equal 0, Bulb.count, "bulbs should have been deleted using :delete_all strategy"
209
- end
210
-
211
- def test_delete_all_on_association_is_the_same_as_not_loaded
212
- author = authors :david
213
- author.thinking_posts.create!(:body => "test")
214
- author.reload
215
- expected_sql = capture_sql { author.thinking_posts.delete_all }
216
-
217
- author.thinking_posts.create!(:body => "test")
218
- author.reload
219
- author.thinking_posts.inspect
220
- loaded_sql = capture_sql { author.thinking_posts.delete_all }
221
- assert_equal(expected_sql, loaded_sql)
222
- end
223
-
224
- def test_delete_all_on_association_with_nil_dependency_is_the_same_as_not_loaded
225
- author = authors :david
226
- author.posts.create!(:title => "test", :body => "body")
227
- author.reload
228
- expected_sql = capture_sql { author.posts.delete_all }
229
-
230
- author.posts.create!(:title => "test", :body => "body")
231
- author.reload
232
- author.posts.to_a
233
- loaded_sql = capture_sql { author.posts.delete_all }
234
- assert_equal(expected_sql, loaded_sql)
235
- end
236
-
237
- def test_building_the_associated_object_with_implicit_sti_base_class
238
- firm = DependentFirm.new
239
- company = firm.companies.build
240
- assert_kind_of Company, company, "Expected #{company.class} to be a Company"
241
- end
242
-
243
- def test_building_the_associated_object_with_explicit_sti_base_class
244
- firm = DependentFirm.new
245
- company = firm.companies.build(:type => "Company")
246
- assert_kind_of Company, company, "Expected #{company.class} to be a Company"
247
- end
248
-
249
- def test_building_the_associated_object_with_sti_subclass
250
- firm = DependentFirm.new
251
- company = firm.companies.build(:type => "Client")
252
- assert_kind_of Client, company, "Expected #{company.class} to be a Client"
253
- end
254
-
255
- def test_building_the_associated_object_with_an_invalid_type
256
- firm = DependentFirm.new
257
- assert_raise(ActiveRecord::SubclassNotFound) { firm.companies.build(:type => "Invalid") }
258
- end
259
-
260
- def test_building_the_associated_object_with_an_unrelated_type
261
- firm = DependentFirm.new
262
- assert_raise(ActiveRecord::SubclassNotFound) { firm.companies.build(:type => "Account") }
263
- end
264
-
265
- test "building the association with an array" do
266
- speedometer = Speedometer.new(speedometer_id: "a")
267
- data = [{name: "first"}, {name: "second"}]
268
- speedometer.minivans.build(data)
269
-
270
- assert_equal 2, speedometer.minivans.size
271
- assert speedometer.save
272
- assert_equal ["first", "second"], speedometer.reload.minivans.map(&:name)
273
- end
274
-
275
- def test_association_keys_bypass_attribute_protection
276
- car = Car.create(:name => 'honda')
277
-
278
- bulb = car.bulbs.new
279
- assert_equal car.id, bulb.car_id
280
-
281
- bulb = car.bulbs.new :car_id => car.id + 1
282
- assert_equal car.id, bulb.car_id
283
-
284
- bulb = car.bulbs.build
285
- assert_equal car.id, bulb.car_id
286
-
287
- bulb = car.bulbs.build :car_id => car.id + 1
288
- assert_equal car.id, bulb.car_id
289
-
290
- bulb = car.bulbs.create
291
- assert_equal car.id, bulb.car_id
292
-
293
- bulb = car.bulbs.create :car_id => car.id + 1
294
- assert_equal car.id, bulb.car_id
295
- end
296
-
297
- def test_association_protect_foreign_key
298
- invoice = Invoice.create
299
-
300
- line_item = invoice.line_items.new
301
- assert_equal invoice.id, line_item.invoice_id
302
-
303
- line_item = invoice.line_items.new :invoice_id => invoice.id + 1
304
- assert_equal invoice.id, line_item.invoice_id
305
-
306
- line_item = invoice.line_items.build
307
- assert_equal invoice.id, line_item.invoice_id
308
-
309
- line_item = invoice.line_items.build :invoice_id => invoice.id + 1
310
- assert_equal invoice.id, line_item.invoice_id
311
-
312
- line_item = invoice.line_items.create
313
- assert_equal invoice.id, line_item.invoice_id
314
-
315
- line_item = invoice.line_items.create :invoice_id => invoice.id + 1
316
- assert_equal invoice.id, line_item.invoice_id
317
- end
318
-
319
- # When creating objects on the association, we must not do it within a scope (even though it
320
- # would be convenient), because this would cause that scope to be applied to any callbacks etc.
321
- def test_build_and_create_should_not_happen_within_scope
322
- car = cars(:honda)
323
- scoped_count = car.foo_bulbs.where_values.count
324
-
325
- bulb = car.foo_bulbs.build
326
- assert_not_equal scoped_count, bulb.scope_after_initialize.where_values.count
327
-
328
- bulb = car.foo_bulbs.create
329
- assert_not_equal scoped_count, bulb.scope_after_initialize.where_values.count
330
-
331
- bulb = car.foo_bulbs.create!
332
- assert_not_equal scoped_count, bulb.scope_after_initialize.where_values.count
333
- end
334
-
335
- def test_no_sql_should_be_fired_if_association_already_loaded
336
- Car.create(:name => 'honda')
337
- bulbs = Car.first.bulbs
338
- bulbs.to_a # to load all instances of bulbs
339
-
340
- assert_no_queries do
341
- bulbs.first()
342
- bulbs.first({})
343
- end
344
-
345
- assert_no_queries do
346
- bulbs.second()
347
- bulbs.second({})
348
- end
349
-
350
- assert_no_queries do
351
- bulbs.third()
352
- bulbs.third({})
353
- end
354
-
355
- assert_no_queries do
356
- bulbs.fourth()
357
- bulbs.fourth({})
358
- end
359
-
360
- assert_no_queries do
361
- bulbs.fifth()
362
- bulbs.fifth({})
363
- end
364
-
365
- assert_no_queries do
366
- bulbs.forty_two()
367
- bulbs.forty_two({})
368
- end
369
-
370
- assert_no_queries do
371
- bulbs.last()
372
- bulbs.last({})
373
- end
374
- end
375
-
376
- def test_create_resets_cached_counters
377
- person = Person.create!(:first_name => 'tenderlove')
378
- post = Post.first
379
-
380
- assert_equal [], person.readers
381
- assert_nil person.readers.find_by_post_id(post.id)
382
-
383
- person.readers.create(:post_id => post.id)
384
-
385
- assert_equal 1, person.readers.count
386
- assert_equal 1, person.readers.length
387
- assert_equal post, person.readers.first.post
388
- assert_equal person, person.readers.first.person
389
- end
390
-
391
- def force_signal37_to_load_all_clients_of_firm
392
- companies(:first_firm).clients_of_firm.each {|f| }
393
- end
394
-
395
- # sometimes tests on Oracle fail if ORDER BY is not provided therefore add always :order with :first
396
- def test_counting_with_counter_sql
397
- assert_equal 3, Firm.all.merge!(:order => "id").first.clients.count
398
- end
399
-
400
- def test_counting
401
- assert_equal 3, Firm.all.merge!(:order => "id").first.plain_clients.count
402
- end
403
-
404
- def test_counting_with_single_hash
405
- assert_equal 1, Firm.all.merge!(:order => "id").first.plain_clients.where(:name => "Microsoft").count
406
- end
407
-
408
- def test_counting_with_column_name_and_hash
409
- assert_equal 3, Firm.all.merge!(:order => "id").first.plain_clients.count(:name)
410
- end
411
-
412
- def test_counting_with_association_limit
413
- firm = companies(:first_firm)
414
- assert_equal firm.limited_clients.length, firm.limited_clients.size
415
- assert_equal firm.limited_clients.length, firm.limited_clients.count
416
- end
417
-
418
- def test_finding
419
- assert_equal 3, Firm.all.merge!(:order => "id").first.clients.length
420
- end
421
-
422
- def test_finding_array_compatibility
423
- assert_equal 3, Firm.order(:id).find{|f| f.id > 0}.clients.length
424
- end
425
-
426
- def test_find_many_with_merged_options
427
- assert_equal 1, companies(:first_firm).limited_clients.size
428
- assert_equal 1, companies(:first_firm).limited_clients.to_a.size
429
- assert_equal 3, companies(:first_firm).limited_clients.limit(nil).to_a.size
430
- end
431
-
432
- def test_find_should_append_to_association_order
433
- ordered_clients = companies(:first_firm).clients_sorted_desc.order('companies.id')
434
- assert_equal ['id DESC', 'companies.id'], ordered_clients.order_values
435
- end
436
-
437
- def test_dynamic_find_should_respect_association_order
438
- assert_equal companies(:another_first_firm_client), companies(:first_firm).clients_sorted_desc.where("type = 'Client'").first
439
- assert_equal companies(:another_first_firm_client), companies(:first_firm).clients_sorted_desc.find_by_type('Client')
440
- end
441
-
442
- def test_taking
443
- posts(:other_by_bob).destroy
444
- assert_equal posts(:misc_by_bob), authors(:bob).posts.take
445
- assert_equal posts(:misc_by_bob), authors(:bob).posts.take!
446
- authors(:bob).posts.to_a
447
- assert_equal posts(:misc_by_bob), authors(:bob).posts.take
448
- assert_equal posts(:misc_by_bob), authors(:bob).posts.take!
449
- end
450
-
451
- def test_taking_not_found
452
- authors(:bob).posts.delete_all
453
- assert_raise(ActiveRecord::RecordNotFound) { authors(:bob).posts.take! }
454
- authors(:bob).posts.to_a
455
- assert_raise(ActiveRecord::RecordNotFound) { authors(:bob).posts.take! }
456
- end
457
-
458
- def test_taking_with_a_number
459
- # taking from unloaded Relation
460
- bob = Author.find(authors(:bob).id)
461
- assert_equal [posts(:misc_by_bob)], bob.posts.take(1)
462
- bob = Author.find(authors(:bob).id)
463
- assert_equal [posts(:misc_by_bob), posts(:other_by_bob)], bob.posts.take(2)
464
-
465
- # taking from loaded Relation
466
- bob.posts.to_a
467
- assert_equal [posts(:misc_by_bob)], authors(:bob).posts.take(1)
468
- assert_equal [posts(:misc_by_bob), posts(:other_by_bob)], authors(:bob).posts.take(2)
469
- end
470
-
471
- def test_taking_with_inverse_of
472
- interests(:woodsmanship).destroy
473
- interests(:survival).destroy
474
-
475
- zine = zines(:going_out)
476
- interest = zine.interests.take
477
- assert_equal interests(:hunting), interest
478
- assert_same zine, interest.zine
479
- end
480
-
481
- def test_cant_save_has_many_readonly_association
482
- authors(:david).readonly_comments.each { |c| assert_raise(ActiveRecord::ReadOnlyRecord) { c.save! } }
483
- authors(:david).readonly_comments.each { |c| assert c.readonly? }
484
- end
485
-
486
- def test_finding_default_orders
487
- assert_equal "Summit", Firm.all.merge!(:order => "id").first.clients.first.name
488
- end
489
-
490
- def test_finding_with_different_class_name_and_order
491
- assert_equal "Apex", Firm.all.merge!(:order => "id").first.clients_sorted_desc.first.name
492
- end
493
-
494
- def test_finding_with_foreign_key
495
- assert_equal "Microsoft", Firm.all.merge!(:order => "id").first.clients_of_firm.first.name
496
- end
497
-
498
- def test_finding_with_condition
499
- assert_equal "Microsoft", Firm.all.merge!(:order => "id").first.clients_like_ms.first.name
500
- end
501
-
502
- def test_finding_with_condition_hash
503
- assert_equal "Microsoft", Firm.all.merge!(:order => "id").first.clients_like_ms_with_hash_conditions.first.name
504
- end
505
-
506
- def test_finding_using_primary_key
507
- assert_equal "Summit", Firm.all.merge!(:order => "id").first.clients_using_primary_key.first.name
508
- end
509
-
510
- def test_update_all_on_association_accessed_before_save
511
- firm = Firm.new(name: 'Firm')
512
- firm.clients << Client.first
513
- firm.save!
514
- assert_equal firm.clients.count, firm.clients.update_all(description: 'Great!')
515
- end
516
-
517
- def test_belongs_to_sanity
518
- c = Client.new
519
- assert_nil c.firm, "belongs_to failed sanity check on new object"
520
- end
521
-
522
- def test_find_ids
523
- firm = Firm.all.merge!(:order => "id").first
524
-
525
- assert_raise(ActiveRecord::RecordNotFound) { firm.clients.find }
526
-
527
- client = firm.clients.find(2)
528
- assert_kind_of Client, client
529
-
530
- client_ary = firm.clients.find([2])
531
- assert_kind_of Array, client_ary
532
- assert_equal client, client_ary.first
533
-
534
- client_ary = firm.clients.find(2, 3)
535
- assert_kind_of Array, client_ary
536
- assert_equal 2, client_ary.size
537
- assert_equal client, client_ary.first
538
-
539
- assert_raise(ActiveRecord::RecordNotFound) { firm.clients.find(2, 99) }
540
- end
541
-
542
- def test_find_ids_and_inverse_of
543
- force_signal37_to_load_all_clients_of_firm
544
-
545
- firm = companies(:first_firm)
546
- client = firm.clients_of_firm.find(3)
547
- assert_kind_of Client, client
548
-
549
- client_ary = firm.clients_of_firm.find([3])
550
- assert_kind_of Array, client_ary
551
- assert_equal client, client_ary.first
552
- end
553
-
554
- def test_find_all
555
- firm = Firm.all.merge!(:order => "id").first
556
- assert_equal 3, firm.clients.where("#{QUOTED_TYPE} = 'Client'").to_a.length
557
- assert_equal 1, firm.clients.where("name = 'Summit'").to_a.length
558
- end
559
-
560
- def test_find_each
561
- firm = companies(:first_firm)
562
-
563
- assert ! firm.clients.loaded?
564
-
565
- assert_queries(4) do
566
- firm.clients.find_each(:batch_size => 1) {|c| assert_equal firm.id, c.firm_id }
567
- end
568
-
569
- assert ! firm.clients.loaded?
570
- end
571
-
572
- def test_find_each_with_conditions
573
- firm = companies(:first_firm)
574
-
575
- assert_queries(2) do
576
- firm.clients.where(name: 'Microsoft').find_each(batch_size: 1) do |c|
577
- assert_equal firm.id, c.firm_id
578
- assert_equal "Microsoft", c.name
579
- end
580
- end
581
-
582
- assert ! firm.clients.loaded?
583
- end
584
-
585
- def test_find_in_batches
586
- firm = companies(:first_firm)
587
-
588
- assert ! firm.clients.loaded?
589
-
590
- assert_queries(2) do
591
- firm.clients.find_in_batches(:batch_size => 2) do |clients|
592
- clients.each {|c| assert_equal firm.id, c.firm_id }
593
- end
594
- end
595
-
596
- assert ! firm.clients.loaded?
597
- end
598
-
599
- def test_find_all_sanitized
600
- # sometimes tests on Oracle fail if ORDER BY is not provided therefore add always :order with :first
601
- firm = Firm.all.merge!(:order => "id").first
602
- summit = firm.clients.where("name = 'Summit'").to_a
603
- assert_equal summit, firm.clients.where("name = ?", "Summit").to_a
604
- assert_equal summit, firm.clients.where("name = :name", { :name => "Summit" }).to_a
605
- end
606
-
607
- def test_find_first
608
- firm = Firm.all.merge!(:order => "id").first
609
- client2 = Client.find(2)
610
- assert_equal firm.clients.first, firm.clients.order("id").first
611
- assert_equal client2, firm.clients.where("#{QUOTED_TYPE} = 'Client'").order("id").first
612
- end
613
-
614
- def test_find_first_sanitized
615
- firm = Firm.all.merge!(:order => "id").first
616
- client2 = Client.find(2)
617
- assert_equal client2, firm.clients.merge!(:where => ["#{QUOTED_TYPE} = ?", 'Client'], :order => "id").first
618
- assert_equal client2, firm.clients.merge!(:where => ["#{QUOTED_TYPE} = :type", { :type => 'Client' }], :order => "id").first
619
- end
620
-
621
- def test_find_all_with_include_and_conditions
622
- assert_nothing_raised do
623
- Developer.all.merge!(:joins => :audit_logs, :where => {'audit_logs.message' => nil, :name => 'Smith'}).to_a
624
- end
625
- end
626
-
627
- def test_find_in_collection
628
- assert_equal Client.find(2).name, companies(:first_firm).clients.find(2).name
629
- assert_raise(ActiveRecord::RecordNotFound) { companies(:first_firm).clients.find(6) }
630
- end
631
-
632
- def test_find_grouped
633
- all_clients_of_firm1 = Client.all.merge!(:where => "firm_id = 1").to_a
634
- grouped_clients_of_firm1 = Client.all.merge!(:where => "firm_id = 1", :group => "firm_id", :select => 'firm_id, count(id) as clients_count').to_a
635
- assert_equal 3, all_clients_of_firm1.size
636
- assert_equal 1, grouped_clients_of_firm1.size
637
- end
638
-
639
- def test_find_scoped_grouped
640
- assert_equal 1, companies(:first_firm).clients_grouped_by_firm_id.size
641
- assert_equal 1, companies(:first_firm).clients_grouped_by_firm_id.length
642
- assert_equal 3, companies(:first_firm).clients_grouped_by_name.size
643
- assert_equal 3, companies(:first_firm).clients_grouped_by_name.length
644
- end
645
-
646
- def test_find_scoped_grouped_having
647
- assert_equal 1, authors(:david).popular_grouped_posts.length
648
- assert_equal 0, authors(:mary).popular_grouped_posts.length
649
- end
650
-
651
- def test_default_select
652
- assert_equal Comment.column_names.sort, posts(:welcome).comments.first.attributes.keys.sort
653
- end
654
-
655
- def test_select_query_method
656
- assert_equal ['id', 'body'], posts(:welcome).comments.select(:id, :body).first.attributes.keys
657
- end
658
-
659
- def test_select_with_block
660
- assert_equal [1], posts(:welcome).comments.select { |c| c.id == 1 }.map(&:id)
661
- end
662
-
663
- def test_select_without_foreign_key
664
- assert_equal companies(:first_firm).accounts.first.credit_limit, companies(:first_firm).accounts.select(:credit_limit).first.credit_limit
665
- end
666
-
667
- def test_adding
668
- force_signal37_to_load_all_clients_of_firm
669
- natural = Client.new("name" => "Natural Company")
670
- companies(:first_firm).clients_of_firm << natural
671
- assert_equal 3, companies(:first_firm).clients_of_firm.size # checking via the collection
672
- assert_equal 3, companies(:first_firm).clients_of_firm(true).size # checking using the db
673
- assert_equal natural, companies(:first_firm).clients_of_firm.last
674
- end
675
-
676
- def test_adding_using_create
677
- first_firm = companies(:first_firm)
678
- assert_equal 3, first_firm.plain_clients.size
679
- first_firm.plain_clients.create(:name => "Natural Company")
680
- assert_equal 4, first_firm.plain_clients.length
681
- assert_equal 4, first_firm.plain_clients.size
682
- end
683
-
684
- def test_create_with_bang_on_has_many_when_parent_is_new_raises
685
- error = assert_raise(ActiveRecord::RecordNotSaved) do
686
- firm = Firm.new
687
- firm.plain_clients.create! :name=>"Whoever"
688
- end
689
-
690
- assert_equal "You cannot call create unless the parent is saved", error.message
691
- end
692
-
693
- def test_regular_create_on_has_many_when_parent_is_new_raises
694
- error = assert_raise(ActiveRecord::RecordNotSaved) do
695
- firm = Firm.new
696
- firm.plain_clients.create :name=>"Whoever"
697
- end
698
-
699
- assert_equal "You cannot call create unless the parent is saved", error.message
700
- end
701
-
702
- def test_create_with_bang_on_has_many_raises_when_record_not_saved
703
- assert_raise(ActiveRecord::RecordInvalid) do
704
- firm = Firm.all.merge!(:order => "id").first
705
- firm.plain_clients.create!
706
- end
707
- end
708
-
709
- def test_create_with_bang_on_habtm_when_parent_is_new_raises
710
- error = assert_raise(ActiveRecord::RecordNotSaved) do
711
- Developer.new("name" => "Aredridel").projects.create!
712
- end
713
-
714
- assert_equal "You cannot call create unless the parent is saved", error.message
715
- end
716
-
717
- def test_adding_a_mismatch_class
718
- assert_raise(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << nil }
719
- assert_raise(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << 1 }
720
- assert_raise(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << Topic.find(1) }
721
- end
722
-
723
- def test_adding_a_collection
724
- force_signal37_to_load_all_clients_of_firm
725
- companies(:first_firm).clients_of_firm.concat([Client.new("name" => "Natural Company"), Client.new("name" => "Apple")])
726
- assert_equal 4, companies(:first_firm).clients_of_firm.size
727
- assert_equal 4, companies(:first_firm).clients_of_firm(true).size
728
- end
729
-
730
- def test_transactions_when_adding_to_persisted
731
- good = Client.new(:name => "Good")
732
- bad = Client.new(:name => "Bad", :raise_on_save => true)
733
-
734
- begin
735
- companies(:first_firm).clients_of_firm.concat(good, bad)
736
- rescue Client::RaisedOnSave
737
- end
738
-
739
- assert !companies(:first_firm).clients_of_firm(true).include?(good)
740
- end
741
-
742
- def test_transactions_when_adding_to_new_record
743
- assert_no_queries(ignore_none: false) do
744
- firm = Firm.new
745
- firm.clients_of_firm.concat(Client.new("name" => "Natural Company"))
746
- end
747
- end
748
-
749
- def test_inverse_on_before_validate
750
- firm = companies(:first_firm)
751
- assert_queries(1) do
752
- firm.clients_of_firm << Client.new("name" => "Natural Company")
753
- end
754
- end
755
-
756
- def test_new_aliased_to_build
757
- company = companies(:first_firm)
758
- new_client = assert_no_queries(ignore_none: false) { company.clients_of_firm.new("name" => "Another Client") }
759
- assert !company.clients_of_firm.loaded?
760
-
761
- assert_equal "Another Client", new_client.name
762
- assert !new_client.persisted?
763
- assert_equal new_client, company.clients_of_firm.last
764
- end
765
-
766
- def test_build
767
- company = companies(:first_firm)
768
- new_client = assert_no_queries(ignore_none: false) { company.clients_of_firm.build("name" => "Another Client") }
769
- assert !company.clients_of_firm.loaded?
770
-
771
- assert_equal "Another Client", new_client.name
772
- assert !new_client.persisted?
773
- assert_equal new_client, company.clients_of_firm.last
774
- end
775
-
776
- def test_collection_size_after_building
777
- company = companies(:first_firm) # company already has one client
778
- company.clients_of_firm.build("name" => "Another Client")
779
- company.clients_of_firm.build("name" => "Yet Another Client")
780
- assert_equal 4, company.clients_of_firm.size
781
- end
782
-
783
- def test_collection_not_empty_after_building
784
- company = companies(:first_firm)
785
- assert_predicate company.contracts, :empty?
786
- company.contracts.build
787
- assert_not_predicate company.contracts, :empty?
788
- end
789
-
790
- def test_collection_size_twice_for_regressions
791
- post = posts(:thinking)
792
- assert_equal 0, post.readers.size
793
- # This test needs a post that has no readers, we assert it to ensure it holds,
794
- # but need to reload the post because the very call to #size hides the bug.
795
- post.reload
796
- post.readers.build
797
- size1 = post.readers.size
798
- size2 = post.readers.size
799
- assert_equal size1, size2
800
- end
801
-
802
- def test_build_many
803
- company = companies(:first_firm)
804
- new_clients = assert_no_queries(ignore_none: false) { company.clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}]) }
805
- assert_equal 2, new_clients.size
806
- end
807
-
808
- def test_build_followed_by_save_does_not_load_target
809
- companies(:first_firm).clients_of_firm.build("name" => "Another Client")
810
- assert companies(:first_firm).save
811
- assert !companies(:first_firm).clients_of_firm.loaded?
812
- end
813
-
814
- def test_build_without_loading_association
815
- first_topic = topics(:first)
816
- Reply.column_names
817
-
818
- assert_equal 1, first_topic.replies.length
819
-
820
- assert_no_queries do
821
- first_topic.replies.build(:title => "Not saved", :content => "Superstars")
822
- assert_equal 2, first_topic.replies.size
823
- end
824
-
825
- assert_equal 2, first_topic.replies.to_ary.size
826
- end
827
-
828
- def test_build_via_block
829
- company = companies(:first_firm)
830
- new_client = assert_no_queries(ignore_none: false) { company.clients_of_firm.build {|client| client.name = "Another Client" } }
831
- assert !company.clients_of_firm.loaded?
832
-
833
- assert_equal "Another Client", new_client.name
834
- assert !new_client.persisted?
835
- assert_equal new_client, company.clients_of_firm.last
836
- end
837
-
838
- def test_build_many_via_block
839
- company = companies(:first_firm)
840
- new_clients = assert_no_queries(ignore_none: false) do
841
- company.clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}]) do |client|
842
- client.name = "changed"
843
- end
844
- end
845
-
846
- assert_equal 2, new_clients.size
847
- assert_equal "changed", new_clients.first.name
848
- assert_equal "changed", new_clients.last.name
849
- end
850
-
851
- def test_create_without_loading_association
852
- first_firm = companies(:first_firm)
853
- Firm.column_names
854
- Client.column_names
855
-
856
- assert_equal 2, first_firm.clients_of_firm.size
857
- first_firm.clients_of_firm.reset
858
-
859
- assert_queries(1) do
860
- first_firm.clients_of_firm.create(:name => "Superstars")
861
- end
862
-
863
- assert_equal 3, first_firm.clients_of_firm.size
864
- end
865
-
866
- def test_create
867
- force_signal37_to_load_all_clients_of_firm
868
- new_client = companies(:first_firm).clients_of_firm.create("name" => "Another Client")
869
- assert new_client.persisted?
870
- assert_equal new_client, companies(:first_firm).clients_of_firm.last
871
- assert_equal new_client, companies(:first_firm).clients_of_firm(true).last
872
- end
873
-
874
- def test_create_many
875
- companies(:first_firm).clients_of_firm.create([{"name" => "Another Client"}, {"name" => "Another Client II"}])
876
- assert_equal 4, companies(:first_firm).clients_of_firm(true).size
877
- end
878
-
879
- def test_create_followed_by_save_does_not_load_target
880
- companies(:first_firm).clients_of_firm.create("name" => "Another Client")
881
- assert companies(:first_firm).save
882
- assert !companies(:first_firm).clients_of_firm.loaded?
883
- end
884
-
885
- def test_deleting
886
- force_signal37_to_load_all_clients_of_firm
887
- companies(:first_firm).clients_of_firm.delete(companies(:first_firm).clients_of_firm.first)
888
- assert_equal 1, companies(:first_firm).clients_of_firm.size
889
- assert_equal 1, companies(:first_firm).clients_of_firm(true).size
890
- end
891
-
892
- def test_deleting_before_save
893
- new_firm = Firm.new("name" => "A New Firm, Inc.")
894
- new_client = new_firm.clients_of_firm.build("name" => "Another Client")
895
- assert_equal 1, new_firm.clients_of_firm.size
896
- new_firm.clients_of_firm.delete(new_client)
897
- assert_equal 0, new_firm.clients_of_firm.size
898
- end
899
-
900
- def test_has_many_without_counter_cache_option
901
- # Ship has a conventionally named `treasures_count` column, but the counter_cache
902
- # option is not given on the association.
903
- ship = Ship.create(name: 'Countless', treasures_count: 10)
904
-
905
- assert_not ship.treasures.instance_variable_get('@association').send(:has_cached_counter?)
906
-
907
- # Count should come from sql count() of treasures rather than treasures_count attribute
908
- assert_equal ship.treasures.size, 0
909
-
910
- assert_no_difference lambda { ship.reload.treasures_count }, "treasures_count should not be changed" do
911
- ship.treasures.create(name: 'Gold')
912
- end
913
-
914
- assert_no_difference lambda { ship.reload.treasures_count }, "treasures_count should not be changed" do
915
- ship.treasures.destroy_all
916
- end
917
- end
918
-
919
- def test_deleting_updates_counter_cache
920
- topic = Topic.order("id ASC").first
921
- assert_equal topic.replies.to_a.size, topic.replies_count
922
-
923
- topic.replies.delete(topic.replies.first)
924
- topic.reload
925
- assert_equal topic.replies.to_a.size, topic.replies_count
926
- end
927
-
928
- def test_counter_cache_updates_in_memory_after_concat
929
- topic = Topic.create title: "Zoom-zoom-zoom"
930
-
931
- topic.replies << Reply.create(title: "re: zoom", content: "speedy quick!")
932
- assert_equal 1, topic.replies_count
933
- assert_equal 1, topic.replies.size
934
- assert_equal 1, topic.reload.replies.size
935
- end
936
-
937
- def test_counter_cache_updates_in_memory_after_create
938
- topic = Topic.create title: "Zoom-zoom-zoom"
939
-
940
- topic.replies.create!(title: "re: zoom", content: "speedy quick!")
941
- assert_equal 1, topic.replies_count
942
- assert_equal 1, topic.replies.size
943
- assert_equal 1, topic.reload.replies.size
944
- end
945
-
946
- def test_counter_cache_updates_in_memory_after_create_with_array
947
- topic = Topic.create title: "Zoom-zoom-zoom"
948
-
949
- topic.replies.create!([
950
- { title: "re: zoom", content: "speedy quick!" },
951
- { title: "re: zoom 2", content: "OMG lol!" },
952
- ])
953
- assert_equal 2, topic.replies_count
954
- assert_equal 2, topic.replies.size
955
- assert_equal 2, topic.reload.replies.size
956
- end
957
-
958
- def test_pushing_association_updates_counter_cache
959
- topic = Topic.order("id ASC").first
960
- reply = Reply.create!
961
-
962
- assert_difference "topic.reload.replies_count", 1 do
963
- topic.replies << reply
964
- end
965
- end
966
-
967
- def test_deleting_updates_counter_cache_without_dependent_option
968
- post = posts(:welcome)
969
-
970
- assert_difference "post.reload.tags_count", -1 do
971
- post.taggings.delete(post.taggings.first)
972
- end
973
- end
974
-
975
- def test_deleting_updates_counter_cache_with_dependent_delete_all
976
- post = posts(:welcome)
977
- post.update_columns(taggings_with_delete_all_count: post.tags_count)
978
-
979
- assert_difference "post.reload.taggings_with_delete_all_count", -1 do
980
- post.taggings_with_delete_all.delete(post.taggings_with_delete_all.first)
981
- end
982
- end
983
-
984
- def test_deleting_updates_counter_cache_with_dependent_destroy
985
- post = posts(:welcome)
986
- post.update_columns(taggings_with_destroy_count: post.tags_count)
987
-
988
- assert_difference "post.reload.taggings_with_destroy_count", -1 do
989
- post.taggings_with_destroy.delete(post.taggings_with_destroy.first)
990
- end
991
- end
992
-
993
- def test_calling_empty_with_counter_cache
994
- post = posts(:welcome)
995
- assert_queries(0) do
996
- assert_not post.comments.empty?
997
- end
998
- end
999
-
1000
- def test_custom_named_counter_cache
1001
- topic = topics(:first)
1002
-
1003
- assert_difference "topic.reload.replies_count", -1 do
1004
- topic.approved_replies.clear
1005
- end
1006
- end
1007
-
1008
- def test_calling_update_attributes_on_id_changes_the_counter_cache
1009
- topic = Topic.order("id ASC").first
1010
- original_count = topic.replies.to_a.size
1011
- assert_equal original_count, topic.replies_count
1012
-
1013
- first_reply = topic.replies.first
1014
- first_reply.update_attributes(:parent_id => nil)
1015
- assert_equal original_count - 1, topic.reload.replies_count
1016
-
1017
- first_reply.update_attributes(:parent_id => topic.id)
1018
- assert_equal original_count, topic.reload.replies_count
1019
- end
1020
-
1021
- def test_calling_update_attributes_changing_ids_doesnt_change_counter_cache
1022
- topic1 = Topic.find(1)
1023
- topic2 = Topic.find(3)
1024
- original_count1 = topic1.replies.to_a.size
1025
- original_count2 = topic2.replies.to_a.size
1026
-
1027
- reply1 = topic1.replies.first
1028
- reply2 = topic2.replies.first
1029
-
1030
- reply1.update_attributes(:parent_id => topic2.id)
1031
- assert_equal original_count1 - 1, topic1.reload.replies_count
1032
- assert_equal original_count2 + 1, topic2.reload.replies_count
1033
-
1034
- reply2.update_attributes(:parent_id => topic1.id)
1035
- assert_equal original_count1, topic1.reload.replies_count
1036
- assert_equal original_count2, topic2.reload.replies_count
1037
- end
1038
-
1039
- def test_deleting_a_collection
1040
- force_signal37_to_load_all_clients_of_firm
1041
- companies(:first_firm).clients_of_firm.create("name" => "Another Client")
1042
- assert_equal 3, companies(:first_firm).clients_of_firm.size
1043
- companies(:first_firm).clients_of_firm.delete([companies(:first_firm).clients_of_firm[0], companies(:first_firm).clients_of_firm[1], companies(:first_firm).clients_of_firm[2]])
1044
- assert_equal 0, companies(:first_firm).clients_of_firm.size
1045
- assert_equal 0, companies(:first_firm).clients_of_firm(true).size
1046
- end
1047
-
1048
- def test_delete_all
1049
- force_signal37_to_load_all_clients_of_firm
1050
- companies(:first_firm).dependent_clients_of_firm.create("name" => "Another Client")
1051
- clients = companies(:first_firm).dependent_clients_of_firm.to_a
1052
- assert_equal 3, clients.count
1053
-
1054
- assert_difference "Client.count", -(clients.count) do
1055
- companies(:first_firm).dependent_clients_of_firm.delete_all
1056
- end
1057
- end
1058
-
1059
- def test_delete_all_with_not_yet_loaded_association_collection
1060
- force_signal37_to_load_all_clients_of_firm
1061
- companies(:first_firm).clients_of_firm.create("name" => "Another Client")
1062
- assert_equal 3, companies(:first_firm).clients_of_firm.size
1063
- companies(:first_firm).clients_of_firm.reset
1064
- companies(:first_firm).clients_of_firm.delete_all
1065
- assert_equal 0, companies(:first_firm).clients_of_firm.size
1066
- assert_equal 0, companies(:first_firm).clients_of_firm(true).size
1067
- end
1068
-
1069
- def test_transaction_when_deleting_persisted
1070
- good = Client.new(:name => "Good")
1071
- bad = Client.new(:name => "Bad", :raise_on_destroy => true)
1072
-
1073
- companies(:first_firm).clients_of_firm = [good, bad]
1074
-
1075
- begin
1076
- companies(:first_firm).clients_of_firm.destroy(good, bad)
1077
- rescue Client::RaisedOnDestroy
1078
- end
1079
-
1080
- assert_equal [good, bad], companies(:first_firm).clients_of_firm(true)
1081
- end
1082
-
1083
- def test_transaction_when_deleting_new_record
1084
- assert_no_queries(ignore_none: false) do
1085
- firm = Firm.new
1086
- client = Client.new("name" => "New Client")
1087
- firm.clients_of_firm << client
1088
- firm.clients_of_firm.destroy(client)
1089
- end
1090
- end
1091
-
1092
- def test_clearing_an_association_collection
1093
- firm = companies(:first_firm)
1094
- client_id = firm.clients_of_firm.first.id
1095
- assert_equal 2, firm.clients_of_firm.size
1096
-
1097
- firm.clients_of_firm.clear
1098
-
1099
- assert_equal 0, firm.clients_of_firm.size
1100
- assert_equal 0, firm.clients_of_firm(true).size
1101
- assert_equal [], Client.destroyed_client_ids[firm.id]
1102
-
1103
- # Should not be destroyed since the association is not dependent.
1104
- assert_nothing_raised do
1105
- assert_nil Client.find(client_id).firm
1106
- end
1107
- end
1108
-
1109
- def test_clearing_updates_counter_cache
1110
- topic = Topic.first
1111
-
1112
- assert_difference 'topic.reload.replies_count', -1 do
1113
- topic.replies.clear
1114
- end
1115
- end
1116
-
1117
- def test_clearing_updates_counter_cache_when_inverse_counter_cache_is_a_symbol_with_dependent_destroy
1118
- car = Car.first
1119
- car.engines.create!
1120
-
1121
- assert_difference 'car.reload.engines_count', -1 do
1122
- car.engines.clear
1123
- end
1124
- end
1125
-
1126
- def test_clearing_a_dependent_association_collection
1127
- firm = companies(:first_firm)
1128
- client_id = firm.dependent_clients_of_firm.first.id
1129
- assert_equal 2, firm.dependent_clients_of_firm.size
1130
- assert_equal 1, Client.find_by_id(client_id).client_of
1131
-
1132
- # :delete_all is called on each client since the dependent options is :destroy
1133
- firm.dependent_clients_of_firm.clear
1134
-
1135
- assert_equal 0, firm.dependent_clients_of_firm.size
1136
- assert_equal 0, firm.dependent_clients_of_firm(true).size
1137
- assert_equal [], Client.destroyed_client_ids[firm.id]
1138
-
1139
- # Should be destroyed since the association is dependent.
1140
- assert_nil Client.find_by_id(client_id)
1141
- end
1142
-
1143
- def test_delete_all_with_option_delete_all
1144
- firm = companies(:first_firm)
1145
- client_id = firm.dependent_clients_of_firm.first.id
1146
- firm.dependent_clients_of_firm.delete_all(:delete_all)
1147
- assert_nil Client.find_by_id(client_id)
1148
- end
1149
-
1150
- def test_delete_all_accepts_limited_parameters
1151
- firm = companies(:first_firm)
1152
- assert_raise(ArgumentError) do
1153
- firm.dependent_clients_of_firm.delete_all(:destroy)
1154
- end
1155
- end
1156
-
1157
- def test_clearing_an_exclusively_dependent_association_collection
1158
- firm = companies(:first_firm)
1159
- client_id = firm.exclusively_dependent_clients_of_firm.first.id
1160
- assert_equal 2, firm.exclusively_dependent_clients_of_firm.size
1161
-
1162
- assert_equal [], Client.destroyed_client_ids[firm.id]
1163
-
1164
- # :exclusively_dependent means each client is deleted directly from
1165
- # the database without looping through them calling destroy.
1166
- firm.exclusively_dependent_clients_of_firm.clear
1167
-
1168
- assert_equal 0, firm.exclusively_dependent_clients_of_firm.size
1169
- assert_equal 0, firm.exclusively_dependent_clients_of_firm(true).size
1170
- # no destroy-filters should have been called
1171
- assert_equal [], Client.destroyed_client_ids[firm.id]
1172
-
1173
- # Should be destroyed since the association is exclusively dependent.
1174
- assert_nil Client.find_by_id(client_id)
1175
- end
1176
-
1177
- def test_dependent_association_respects_optional_conditions_on_delete
1178
- firm = companies(:odegy)
1179
- Client.create(:client_of => firm.id, :name => "BigShot Inc.")
1180
- Client.create(:client_of => firm.id, :name => "SmallTime Inc.")
1181
- # only one of two clients is included in the association due to the :conditions key
1182
- assert_equal 2, Client.where(client_of: firm.id).size
1183
- assert_equal 1, firm.dependent_conditional_clients_of_firm.size
1184
- firm.destroy
1185
- # only the correctly associated client should have been deleted
1186
- assert_equal 1, Client.where(client_of: firm.id).size
1187
- end
1188
-
1189
- def test_dependent_association_respects_optional_sanitized_conditions_on_delete
1190
- firm = companies(:odegy)
1191
- Client.create(:client_of => firm.id, :name => "BigShot Inc.")
1192
- Client.create(:client_of => firm.id, :name => "SmallTime Inc.")
1193
- # only one of two clients is included in the association due to the :conditions key
1194
- assert_equal 2, Client.where(client_of: firm.id).size
1195
- assert_equal 1, firm.dependent_sanitized_conditional_clients_of_firm.size
1196
- firm.destroy
1197
- # only the correctly associated client should have been deleted
1198
- assert_equal 1, Client.where(client_of: firm.id).size
1199
- end
1200
-
1201
- def test_dependent_association_respects_optional_hash_conditions_on_delete
1202
- firm = companies(:odegy)
1203
- Client.create(:client_of => firm.id, :name => "BigShot Inc.")
1204
- Client.create(:client_of => firm.id, :name => "SmallTime Inc.")
1205
- # only one of two clients is included in the association due to the :conditions key
1206
- assert_equal 2, Client.where(client_of: firm.id).size
1207
- assert_equal 1, firm.dependent_sanitized_conditional_clients_of_firm.size
1208
- firm.destroy
1209
- # only the correctly associated client should have been deleted
1210
- assert_equal 1, Client.where(client_of: firm.id).size
1211
- end
1212
-
1213
- def test_delete_all_association_with_primary_key_deletes_correct_records
1214
- firm = Firm.first
1215
- # break the vanilla firm_id foreign key
1216
- assert_equal 3, firm.clients.count
1217
- firm.clients.first.update_columns(firm_id: nil)
1218
- assert_equal 2, firm.clients(true).count
1219
- assert_equal 2, firm.clients_using_primary_key_with_delete_all.count
1220
- old_record = firm.clients_using_primary_key_with_delete_all.first
1221
- firm = Firm.first
1222
- firm.destroy
1223
- assert_nil Client.find_by_id(old_record.id)
1224
- end
1225
-
1226
- def test_creation_respects_hash_condition
1227
- ms_client = companies(:first_firm).clients_like_ms_with_hash_conditions.build
1228
-
1229
- assert ms_client.save
1230
- assert_equal 'Microsoft', ms_client.name
1231
-
1232
- another_ms_client = companies(:first_firm).clients_like_ms_with_hash_conditions.create
1233
-
1234
- assert another_ms_client.persisted?
1235
- assert_equal 'Microsoft', another_ms_client.name
1236
- end
1237
-
1238
- def test_clearing_without_initial_access
1239
- firm = companies(:first_firm)
1240
-
1241
- firm.clients_of_firm.clear
1242
-
1243
- assert_equal 0, firm.clients_of_firm.size
1244
- assert_equal 0, firm.clients_of_firm(true).size
1245
- end
1246
-
1247
- def test_deleting_a_item_which_is_not_in_the_collection
1248
- force_signal37_to_load_all_clients_of_firm
1249
- summit = Client.find_by_name('Summit')
1250
- companies(:first_firm).clients_of_firm.delete(summit)
1251
- assert_equal 2, companies(:first_firm).clients_of_firm.size
1252
- assert_equal 2, companies(:first_firm).clients_of_firm(true).size
1253
- assert_equal 2, summit.client_of
1254
- end
1255
-
1256
- def test_deleting_by_fixnum_id
1257
- david = Developer.find(1)
1258
-
1259
- assert_difference 'david.projects.count', -1 do
1260
- assert_equal 1, david.projects.delete(1).size
1261
- end
1262
-
1263
- assert_equal 1, david.projects.size
1264
- end
1265
-
1266
- def test_deleting_by_string_id
1267
- david = Developer.find(1)
1268
-
1269
- assert_difference 'david.projects.count', -1 do
1270
- assert_equal 1, david.projects.delete('1').size
1271
- end
1272
-
1273
- assert_equal 1, david.projects.size
1274
- end
1275
-
1276
- def test_deleting_self_type_mismatch
1277
- david = Developer.find(1)
1278
- david.projects.reload
1279
- assert_raise(ActiveRecord::AssociationTypeMismatch) { david.projects.delete(Project.find(1).developers) }
1280
- end
1281
-
1282
- def test_destroying
1283
- force_signal37_to_load_all_clients_of_firm
1284
-
1285
- assert_difference "Client.count", -1 do
1286
- companies(:first_firm).clients_of_firm.destroy(companies(:first_firm).clients_of_firm.first)
1287
- end
1288
-
1289
- assert_equal 1, companies(:first_firm).reload.clients_of_firm.size
1290
- assert_equal 1, companies(:first_firm).clients_of_firm(true).size
1291
- end
1292
-
1293
- def test_destroying_by_fixnum_id
1294
- force_signal37_to_load_all_clients_of_firm
1295
-
1296
- assert_difference "Client.count", -1 do
1297
- companies(:first_firm).clients_of_firm.destroy(companies(:first_firm).clients_of_firm.first.id)
1298
- end
1299
-
1300
- assert_equal 1, companies(:first_firm).reload.clients_of_firm.size
1301
- assert_equal 1, companies(:first_firm).clients_of_firm(true).size
1302
- end
1303
-
1304
- def test_destroying_by_string_id
1305
- force_signal37_to_load_all_clients_of_firm
1306
-
1307
- assert_difference "Client.count", -1 do
1308
- companies(:first_firm).clients_of_firm.destroy(companies(:first_firm).clients_of_firm.first.id.to_s)
1309
- end
1310
-
1311
- assert_equal 1, companies(:first_firm).reload.clients_of_firm.size
1312
- assert_equal 1, companies(:first_firm).clients_of_firm(true).size
1313
- end
1314
-
1315
- def test_destroying_a_collection
1316
- force_signal37_to_load_all_clients_of_firm
1317
- companies(:first_firm).clients_of_firm.create("name" => "Another Client")
1318
- assert_equal 3, companies(:first_firm).clients_of_firm.size
1319
-
1320
- assert_difference "Client.count", -2 do
1321
- companies(:first_firm).clients_of_firm.destroy([companies(:first_firm).clients_of_firm[0], companies(:first_firm).clients_of_firm[1]])
1322
- end
1323
-
1324
- assert_equal 1, companies(:first_firm).reload.clients_of_firm.size
1325
- assert_equal 1, companies(:first_firm).clients_of_firm(true).size
1326
- end
1327
-
1328
- def test_destroy_all
1329
- force_signal37_to_load_all_clients_of_firm
1330
- clients = companies(:first_firm).clients_of_firm.to_a
1331
- assert !clients.empty?, "37signals has clients after load"
1332
- destroyed = companies(:first_firm).clients_of_firm.destroy_all
1333
- assert_equal clients.sort_by(&:id), destroyed.sort_by(&:id)
1334
- assert destroyed.all? { |client| client.frozen? }, "destroyed clients should be frozen"
1335
- assert companies(:first_firm).clients_of_firm.empty?, "37signals has no clients after destroy all"
1336
- assert companies(:first_firm).clients_of_firm(true).empty?, "37signals has no clients after destroy all and refresh"
1337
- end
1338
-
1339
- def test_dependence
1340
- firm = companies(:first_firm)
1341
- assert_equal 3, firm.clients.size
1342
- firm.destroy
1343
- assert Client.all.merge!(:where => "firm_id=#{firm.id}").to_a.empty?
1344
- end
1345
-
1346
- def test_dependence_for_associations_with_hash_condition
1347
- david = authors(:david)
1348
- assert_difference('Post.count', -1) { assert david.destroy }
1349
- end
1350
-
1351
- def test_destroy_dependent_when_deleted_from_association
1352
- # sometimes tests on Oracle fail if ORDER BY is not provided therefore add always :order with :first
1353
- firm = Firm.all.merge!(:order => "id").first
1354
- assert_equal 3, firm.clients.size
1355
-
1356
- client = firm.clients.first
1357
- firm.clients.delete(client)
1358
-
1359
- assert_raise(ActiveRecord::RecordNotFound) { Client.find(client.id) }
1360
- assert_raise(ActiveRecord::RecordNotFound) { firm.clients.find(client.id) }
1361
- assert_equal 2, firm.clients.size
1362
- end
1363
-
1364
- def test_three_levels_of_dependence
1365
- topic = Topic.create "title" => "neat and simple"
1366
- reply = topic.replies.create "title" => "neat and simple", "content" => "still digging it"
1367
- reply.replies.create "title" => "neat and simple", "content" => "ain't complaining"
1368
-
1369
- assert_nothing_raised { topic.destroy }
1370
- end
1371
-
1372
- uses_transaction :test_dependence_with_transaction_support_on_failure
1373
- def test_dependence_with_transaction_support_on_failure
1374
- firm = companies(:first_firm)
1375
- clients = firm.clients
1376
- assert_equal 3, clients.length
1377
- clients.last.instance_eval { def overwrite_to_raise() raise "Trigger rollback" end }
1378
-
1379
- firm.destroy rescue "do nothing"
1380
-
1381
- assert_equal 3, Client.all.merge!(:where => "firm_id=#{firm.id}").to_a.size
1382
- end
1383
-
1384
- def test_dependence_on_account
1385
- num_accounts = Account.count
1386
- companies(:first_firm).destroy
1387
- assert_equal num_accounts - 1, Account.count
1388
- end
1389
-
1390
- def test_depends_and_nullify
1391
- num_accounts = Account.count
1392
-
1393
- core = companies(:rails_core)
1394
- assert_equal accounts(:rails_core_account), core.account
1395
- assert_equal companies(:leetsoft, :jadedpixel), core.companies
1396
- core.destroy
1397
- assert_nil accounts(:rails_core_account).reload.firm_id
1398
- assert_nil companies(:leetsoft).reload.client_of
1399
- assert_nil companies(:jadedpixel).reload.client_of
1400
-
1401
- assert_equal num_accounts, Account.count
1402
- end
1403
-
1404
- def test_restrict_with_exception
1405
- firm = RestrictedWithExceptionFirm.create!(:name => 'restrict')
1406
- firm.companies.create(:name => 'child')
1407
-
1408
- assert !firm.companies.empty?
1409
- assert_raise(ActiveRecord::DeleteRestrictionError) { firm.destroy }
1410
- assert RestrictedWithExceptionFirm.exists?(:name => 'restrict')
1411
- assert firm.companies.exists?(:name => 'child')
1412
- end
1413
-
1414
- def test_restrict_with_error
1415
- firm = RestrictedWithErrorFirm.create!(:name => 'restrict')
1416
- firm.companies.create(:name => 'child')
1417
-
1418
- assert !firm.companies.empty?
1419
-
1420
- firm.destroy
1421
-
1422
- assert !firm.errors.empty?
1423
-
1424
- assert_equal "Cannot delete record because dependent companies exist", firm.errors[:base].first
1425
- assert RestrictedWithErrorFirm.exists?(:name => 'restrict')
1426
- assert firm.companies.exists?(:name => 'child')
1427
- end
1428
-
1429
- def test_included_in_collection
1430
- assert_equal true, companies(:first_firm).clients.include?(Client.find(2))
1431
- end
1432
-
1433
- def test_included_in_collection_for_new_records
1434
- client = Client.create(:name => 'Persisted')
1435
- assert_nil client.client_of
1436
- assert_equal false, Firm.new.clients_of_firm.include?(client),
1437
- 'includes a client that does not belong to any firm'
1438
- end
1439
-
1440
- def test_adding_array_and_collection
1441
- assert_nothing_raised { Firm.first.clients + Firm.all.last.clients }
1442
- end
1443
-
1444
- def test_replace_with_less
1445
- firm = Firm.all.merge!(:order => "id").first
1446
- firm.clients = [companies(:first_client)]
1447
- assert firm.save, "Could not save firm"
1448
- firm.reload
1449
- assert_equal 1, firm.clients.length
1450
- end
1451
-
1452
- def test_replace_with_less_and_dependent_nullify
1453
- num_companies = Company.count
1454
- companies(:rails_core).companies = []
1455
- assert_equal num_companies, Company.count
1456
- end
1457
-
1458
- def test_replace_with_new
1459
- firm = Firm.all.merge!(:order => "id").first
1460
- firm.clients = [companies(:second_client), Client.new("name" => "New Client")]
1461
- firm.save
1462
- firm.reload
1463
- assert_equal 2, firm.clients.length
1464
- assert_equal false, firm.clients.include?(:first_client)
1465
- end
1466
-
1467
- def test_replace_failure
1468
- firm = companies(:first_firm)
1469
- account = Account.new
1470
- orig_accounts = firm.accounts.to_a
1471
-
1472
- assert !account.valid?
1473
- assert !orig_accounts.empty?
1474
- error = assert_raise ActiveRecord::RecordNotSaved do
1475
- firm.accounts = [account]
1476
- end
1477
-
1478
- assert_equal orig_accounts, firm.accounts
1479
- assert_equal "Failed to replace accounts because one or more of the " \
1480
- "new records could not be saved.", error.message
1481
- end
1482
-
1483
- def test_replace_with_same_content
1484
- firm = Firm.first
1485
- firm.clients = []
1486
- firm.save
1487
-
1488
- assert_queries(0, ignore_none: true) do
1489
- firm.clients = []
1490
- end
1491
- end
1492
-
1493
- def test_transactions_when_replacing_on_persisted
1494
- good = Client.new(:name => "Good")
1495
- bad = Client.new(:name => "Bad", :raise_on_save => true)
1496
-
1497
- companies(:first_firm).clients_of_firm = [good]
1498
-
1499
- begin
1500
- companies(:first_firm).clients_of_firm = [bad]
1501
- rescue Client::RaisedOnSave
1502
- end
1503
-
1504
- assert_equal [good], companies(:first_firm).clients_of_firm(true)
1505
- end
1506
-
1507
- def test_transactions_when_replacing_on_new_record
1508
- assert_no_queries(ignore_none: false) do
1509
- firm = Firm.new
1510
- firm.clients_of_firm = [Client.new("name" => "New Client")]
1511
- end
1512
- end
1513
-
1514
- def test_get_ids
1515
- assert_equal [companies(:first_client).id, companies(:second_client).id, companies(:another_first_firm_client).id], companies(:first_firm).client_ids
1516
- end
1517
-
1518
- def test_get_ids_for_loaded_associations
1519
- company = companies(:first_firm)
1520
- company.clients(true)
1521
- assert_queries(0) do
1522
- company.client_ids
1523
- company.client_ids
1524
- end
1525
- end
1526
-
1527
- def test_get_ids_for_unloaded_associations_does_not_load_them
1528
- company = companies(:first_firm)
1529
- assert !company.clients.loaded?
1530
- assert_equal [companies(:first_client).id, companies(:second_client).id, companies(:another_first_firm_client).id], company.client_ids
1531
- assert !company.clients.loaded?
1532
- end
1533
-
1534
- def test_get_ids_ignores_include_option
1535
- assert_equal [readers(:michael_welcome).id], posts(:welcome).readers_with_person_ids
1536
- end
1537
-
1538
- def test_get_ids_for_ordered_association
1539
- assert_equal [companies(:another_first_firm_client).id, companies(:second_client).id, companies(:first_client).id], companies(:first_firm).clients_ordered_by_name_ids
1540
- end
1541
-
1542
- def test_get_ids_for_association_on_new_record_does_not_try_to_find_records
1543
- Company.columns # Load schema information so we don't query below
1544
- Contract.columns # if running just this test.
1545
-
1546
- company = Company.new
1547
- assert_queries(0) do
1548
- company.contract_ids
1549
- end
1550
-
1551
- assert_equal [], company.contract_ids
1552
- end
1553
-
1554
- def test_set_ids_for_association_on_new_record_applies_association_correctly
1555
- contract_a = Contract.create!
1556
- contract_b = Contract.create!
1557
- Contract.create! # another contract
1558
- company = Company.new(:name => "Some Company")
1559
-
1560
- company.contract_ids = [contract_a.id, contract_b.id]
1561
- assert_equal [contract_a.id, contract_b.id], company.contract_ids
1562
- assert_equal [contract_a, contract_b], company.contracts
1563
-
1564
- company.save!
1565
- assert_equal company, contract_a.reload.company
1566
- assert_equal company, contract_b.reload.company
1567
- end
1568
-
1569
- def test_assign_ids_ignoring_blanks
1570
- firm = Firm.create!(:name => 'Apple')
1571
- firm.client_ids = [companies(:first_client).id, nil, companies(:second_client).id, '']
1572
- firm.save!
1573
-
1574
- assert_equal 2, firm.clients(true).size
1575
- assert_equal true, firm.clients.include?(companies(:second_client))
1576
- end
1577
-
1578
- def test_get_ids_for_through
1579
- assert_equal [comments(:eager_other_comment1).id], authors(:mary).comment_ids
1580
- end
1581
-
1582
- def test_modifying_a_through_a_has_many_should_raise
1583
- [
1584
- lambda { authors(:mary).comment_ids = [comments(:greetings).id, comments(:more_greetings).id] },
1585
- lambda { authors(:mary).comments = [comments(:greetings), comments(:more_greetings)] },
1586
- lambda { authors(:mary).comments << Comment.create!(:body => "Yay", :post_id => 424242) },
1587
- lambda { authors(:mary).comments.delete(authors(:mary).comments.first) },
1588
- ].each {|block| assert_raise(ActiveRecord::HasManyThroughCantAssociateThroughHasOneOrManyReflection, &block) }
1589
- end
1590
-
1591
- def test_dynamic_find_should_respect_association_order_for_through
1592
- assert_equal Comment.find(10), authors(:david).comments_desc.where("comments.type = 'SpecialComment'").first
1593
- assert_equal Comment.find(10), authors(:david).comments_desc.find_by_type('SpecialComment')
1594
- end
1595
-
1596
- def test_has_many_through_respects_hash_conditions
1597
- assert_equal authors(:david).hello_posts, authors(:david).hello_posts_with_hash_conditions
1598
- assert_equal authors(:david).hello_post_comments, authors(:david).hello_post_comments_with_hash_conditions
1599
- end
1600
-
1601
- def test_include_uses_array_include_after_loaded
1602
- firm = companies(:first_firm)
1603
- firm.clients.load_target
1604
-
1605
- client = firm.clients.first
1606
-
1607
- assert_no_queries do
1608
- assert firm.clients.loaded?
1609
- assert_equal true, firm.clients.include?(client)
1610
- end
1611
- end
1612
-
1613
- def test_include_checks_if_record_exists_if_target_not_loaded
1614
- firm = companies(:first_firm)
1615
- client = firm.clients.first
1616
-
1617
- firm.reload
1618
- assert ! firm.clients.loaded?
1619
- assert_queries(1) do
1620
- assert_equal true, firm.clients.include?(client)
1621
- end
1622
- assert ! firm.clients.loaded?
1623
- end
1624
-
1625
- def test_include_returns_false_for_non_matching_record_to_verify_scoping
1626
- firm = companies(:first_firm)
1627
- client = Client.create!(:name => 'Not Associated')
1628
-
1629
- assert ! firm.clients.loaded?
1630
- assert_equal false, firm.clients.include?(client)
1631
- end
1632
-
1633
- def test_calling_first_nth_or_last_on_association_should_not_load_association
1634
- firm = companies(:first_firm)
1635
- firm.clients.first
1636
- firm.clients.second
1637
- firm.clients.last
1638
- assert !firm.clients.loaded?
1639
- end
1640
-
1641
- def test_calling_first_or_last_on_loaded_association_should_not_fetch_with_query
1642
- firm = companies(:first_firm)
1643
- firm.clients.load_target
1644
- assert firm.clients.loaded?
1645
-
1646
- assert_no_queries(ignore_none: false) do
1647
- firm.clients.first
1648
- assert_equal 2, firm.clients.first(2).size
1649
- firm.clients.last
1650
- assert_equal 2, firm.clients.last(2).size
1651
- end
1652
- end
1653
-
1654
- def test_calling_first_or_last_on_existing_record_with_build_should_load_association
1655
- firm = companies(:first_firm)
1656
- firm.clients.build(:name => 'Foo')
1657
- assert !firm.clients.loaded?
1658
-
1659
- assert_queries 1 do
1660
- firm.clients.first
1661
- firm.clients.second
1662
- firm.clients.last
1663
- end
1664
-
1665
- assert firm.clients.loaded?
1666
- end
1667
-
1668
- def test_calling_first_nth_or_last_on_existing_record_with_create_should_not_load_association
1669
- firm = companies(:first_firm)
1670
- firm.clients.create(:name => 'Foo')
1671
- assert !firm.clients.loaded?
1672
-
1673
- assert_queries 3 do
1674
- firm.clients.first
1675
- firm.clients.second
1676
- firm.clients.last
1677
- end
1678
-
1679
- assert !firm.clients.loaded?
1680
- end
1681
-
1682
- def test_calling_first_nth_or_last_on_new_record_should_not_run_queries
1683
- firm = Firm.new
1684
-
1685
- assert_no_queries do
1686
- firm.clients.first
1687
- firm.clients.second
1688
- firm.clients.last
1689
- end
1690
- end
1691
-
1692
- def test_calling_first_or_last_with_integer_on_association_should_not_load_association
1693
- firm = companies(:first_firm)
1694
- firm.clients.create(:name => 'Foo')
1695
- assert !firm.clients.loaded?
1696
-
1697
- assert_queries 2 do
1698
- firm.clients.first(2)
1699
- firm.clients.last(2)
1700
- end
1701
-
1702
- assert !firm.clients.loaded?
1703
- end
1704
-
1705
- def test_calling_many_should_count_instead_of_loading_association
1706
- firm = companies(:first_firm)
1707
- assert_queries(1) do
1708
- firm.clients.many? # use count query
1709
- end
1710
- assert !firm.clients.loaded?
1711
- end
1712
-
1713
- def test_calling_many_on_loaded_association_should_not_use_query
1714
- firm = companies(:first_firm)
1715
- firm.clients.collect # force load
1716
- assert_no_queries { assert firm.clients.many? }
1717
- end
1718
-
1719
- def test_calling_many_should_defer_to_collection_if_using_a_block
1720
- firm = companies(:first_firm)
1721
- assert_queries(1) do
1722
- firm.clients.expects(:size).never
1723
- firm.clients.many? { true }
1724
- end
1725
- assert firm.clients.loaded?
1726
- end
1727
-
1728
- def test_calling_many_should_return_false_if_none_or_one
1729
- firm = companies(:another_firm)
1730
- assert !firm.clients_like_ms.many?
1731
- assert_equal 0, firm.clients_like_ms.size
1732
-
1733
- firm = companies(:first_firm)
1734
- assert !firm.limited_clients.many?
1735
- assert_equal 1, firm.limited_clients.size
1736
- end
1737
-
1738
- def test_calling_many_should_return_true_if_more_than_one
1739
- firm = companies(:first_firm)
1740
- assert firm.clients.many?
1741
- assert_equal 3, firm.clients.size
1742
- end
1743
-
1744
- def test_joins_with_namespaced_model_should_use_correct_type
1745
- old = ActiveRecord::Base.store_full_sti_class
1746
- ActiveRecord::Base.store_full_sti_class = true
1747
-
1748
- firm = Namespaced::Firm.create({ :name => 'Some Company' })
1749
- firm.clients.create({ :name => 'Some Client' })
1750
-
1751
- stats = Namespaced::Firm.all.merge!(
1752
- :select => "#{Namespaced::Firm.table_name}.id, COUNT(#{Namespaced::Client.table_name}.id) AS num_clients",
1753
- :joins => :clients,
1754
- :group => "#{Namespaced::Firm.table_name}.id"
1755
- ).find firm.id
1756
- assert_equal 1, stats.num_clients.to_i
1757
- ensure
1758
- ActiveRecord::Base.store_full_sti_class = old
1759
- end
1760
-
1761
- def test_association_proxy_transaction_method_starts_transaction_in_association_class
1762
- Comment.expects(:transaction)
1763
- Post.first.comments.transaction do
1764
- # nothing
1765
- end
1766
- end
1767
-
1768
- def test_sending_new_to_association_proxy_should_have_same_effect_as_calling_new
1769
- client_association = companies(:first_firm).clients
1770
- assert_equal client_association.new.attributes, client_association.send(:new).attributes
1771
- end
1772
-
1773
- def test_respond_to_private_class_methods
1774
- client_association = companies(:first_firm).clients
1775
- assert !client_association.respond_to?(:private_method)
1776
- assert client_association.respond_to?(:private_method, true)
1777
- end
1778
-
1779
- def test_creating_using_primary_key
1780
- firm = Firm.all.merge!(:order => "id").first
1781
- client = firm.clients_using_primary_key.create!(:name => 'test')
1782
- assert_equal firm.name, client.firm_name
1783
- end
1784
-
1785
- def test_defining_has_many_association_with_delete_all_dependency_lazily_evaluates_target_class
1786
- ActiveRecord::Reflection::AssociationReflection.any_instance.expects(:class_name).never
1787
- class_eval(<<-EOF, __FILE__, __LINE__ + 1)
1788
- class DeleteAllModel < ActiveRecord::Base
1789
- has_many :nonentities, :dependent => :delete_all
1790
- end
1791
- EOF
1792
- end
1793
-
1794
- def test_defining_has_many_association_with_nullify_dependency_lazily_evaluates_target_class
1795
- ActiveRecord::Reflection::AssociationReflection.any_instance.expects(:class_name).never
1796
- class_eval(<<-EOF, __FILE__, __LINE__ + 1)
1797
- class NullifyModel < ActiveRecord::Base
1798
- has_many :nonentities, :dependent => :nullify
1799
- end
1800
- EOF
1801
- end
1802
-
1803
- def test_attributes_are_being_set_when_initialized_from_has_many_association_with_where_clause
1804
- new_comment = posts(:welcome).comments.where(:body => "Some content").build
1805
- assert_equal new_comment.body, "Some content"
1806
- end
1807
-
1808
- def test_attributes_are_being_set_when_initialized_from_has_many_association_with_multiple_where_clauses
1809
- new_comment = posts(:welcome).comments.where(:body => "Some content").where(:type => 'SpecialComment').build
1810
- assert_equal new_comment.body, "Some content"
1811
- assert_equal new_comment.type, "SpecialComment"
1812
- assert_equal new_comment.post_id, posts(:welcome).id
1813
- end
1814
-
1815
- def test_include_method_in_has_many_association_should_return_true_for_instance_added_with_build
1816
- post = Post.new
1817
- comment = post.comments.build
1818
- assert_equal true, post.comments.include?(comment)
1819
- end
1820
-
1821
- def test_load_target_respects_protected_attributes
1822
- topic = Topic.create!
1823
- reply = topic.replies.create(:title => "reply 1")
1824
- reply.approved = false
1825
- reply.save!
1826
-
1827
- # Save with a different object instance, so the instance that's still held
1828
- # in topic.relies doesn't know about the changed attribute.
1829
- reply2 = Reply.find(reply.id)
1830
- reply2.approved = true
1831
- reply2.save!
1832
-
1833
- # Force loading the collection from the db. This will merge the existing
1834
- # object (reply) with what gets loaded from the db (which includes the
1835
- # changed approved attribute). approved is a protected attribute, so if mass
1836
- # assignment is used, it won't get updated and will still be false.
1837
- first = topic.replies.to_a.first
1838
- assert_equal reply.id, first.id
1839
- assert_equal true, first.approved?
1840
- end
1841
-
1842
- def test_to_a_should_dup_target
1843
- ary = topics(:first).replies.to_a
1844
- target = topics(:first).replies.target
1845
-
1846
- assert_not_equal target.object_id, ary.object_id
1847
- end
1848
-
1849
- def test_merging_with_custom_attribute_writer
1850
- bulb = Bulb.new(:color => "red")
1851
- assert_equal "RED!", bulb.color
1852
-
1853
- car = Car.create!
1854
- car.bulbs << bulb
1855
-
1856
- assert_equal "RED!", car.bulbs.to_a.first.color
1857
- end
1858
-
1859
- def test_abstract_class_with_polymorphic_has_many
1860
- post = SubStiPost.create! :title => "fooo", :body => "baa"
1861
- tagging = Tagging.create! :taggable => post
1862
- assert_equal [tagging], post.taggings
1863
- end
1864
-
1865
- def test_with_polymorphic_has_many_with_custom_columns_name
1866
- post = Post.create! :title => 'foo', :body => 'bar'
1867
- image = Image.create!
1868
-
1869
- post.images << image
1870
-
1871
- assert_equal [image], post.images
1872
- end
1873
-
1874
- def test_build_with_polymorphic_has_many_does_not_allow_to_override_type_and_id
1875
- welcome = posts(:welcome)
1876
- tagging = welcome.taggings.build(:taggable_id => 99, :taggable_type => 'ShouldNotChange')
1877
-
1878
- assert_equal welcome.id, tagging.taggable_id
1879
- assert_equal 'Post', tagging.taggable_type
1880
- end
1881
-
1882
- def test_dont_call_save_callbacks_twice_on_has_many
1883
- firm = companies(:first_firm)
1884
- contract = firm.contracts.create!
1885
-
1886
- assert_equal 1, contract.hi_count
1887
- assert_equal 1, contract.bye_count
1888
- end
1889
-
1890
- def test_association_attributes_are_available_to_after_initialize
1891
- car = Car.create(:name => 'honda')
1892
- bulb = car.bulbs.build
1893
-
1894
- assert_equal car.id, bulb.attributes_after_initialize['car_id']
1895
- end
1896
-
1897
- def test_attributes_are_set_when_initialized_from_has_many_null_relationship
1898
- car = Car.new name: 'honda'
1899
- bulb = car.bulbs.where(name: 'headlight').first_or_initialize
1900
- assert_equal 'headlight', bulb.name
1901
- end
1902
-
1903
- def test_attributes_are_set_when_initialized_from_polymorphic_has_many_null_relationship
1904
- post = Post.new title: 'title', body: 'bar'
1905
- tag = Tag.create!(name: 'foo')
1906
-
1907
- tagging = post.taggings.where(tag: tag).first_or_initialize
1908
-
1909
- assert_equal tag.id, tagging.tag_id
1910
- assert_equal 'Post', tagging.taggable_type
1911
- end
1912
-
1913
- def test_replace
1914
- car = Car.create(:name => 'honda')
1915
- bulb1 = car.bulbs.create
1916
- bulb2 = Bulb.create
1917
-
1918
- assert_equal [bulb1], car.bulbs
1919
- car.bulbs.replace([bulb2])
1920
- assert_equal [bulb2], car.bulbs
1921
- assert_equal [bulb2], car.reload.bulbs
1922
- end
1923
-
1924
- def test_replace_returns_target
1925
- car = Car.create(:name => 'honda')
1926
- bulb1 = car.bulbs.create
1927
- bulb2 = car.bulbs.create
1928
- bulb3 = Bulb.create
1929
-
1930
- assert_equal [bulb1, bulb2], car.bulbs
1931
- result = car.bulbs.replace([bulb3, bulb1])
1932
- assert_equal [bulb1, bulb3], car.bulbs
1933
- assert_equal [bulb1, bulb3], result
1934
- end
1935
-
1936
- def test_collection_association_with_private_kernel_method
1937
- firm = companies(:first_firm)
1938
- assert_equal [accounts(:signals37)], firm.accounts.open
1939
- end
1940
-
1941
- test "first_or_initialize adds the record to the association" do
1942
- firm = Firm.create! name: 'omg'
1943
- client = firm.clients_of_firm.first_or_initialize
1944
- assert_equal [client], firm.clients_of_firm
1945
- end
1946
-
1947
- test "first_or_create adds the record to the association" do
1948
- firm = Firm.create! name: 'omg'
1949
- firm.clients_of_firm.load_target
1950
- client = firm.clients_of_firm.first_or_create name: 'lol'
1951
- assert_equal [client], firm.clients_of_firm
1952
- assert_equal [client], firm.reload.clients_of_firm
1953
- end
1954
-
1955
- test "delete_all, when not loaded, doesn't load the records" do
1956
- post = posts(:welcome)
1957
-
1958
- assert post.taggings_with_delete_all.count > 0
1959
- assert !post.taggings_with_delete_all.loaded?
1960
-
1961
- # 2 queries: one DELETE and another to update the counter cache
1962
- assert_queries(2) do
1963
- post.taggings_with_delete_all.delete_all
1964
- end
1965
- end
1966
-
1967
- test "has many associations on new records use null relations" do
1968
- post = Post.new
1969
-
1970
- assert_no_queries(ignore_none: false) do
1971
- assert_equal [], post.comments
1972
- assert_equal [], post.comments.where(body: 'omg')
1973
- assert_equal [], post.comments.pluck(:body)
1974
- assert_equal 0, post.comments.sum(:id)
1975
- assert_equal 0, post.comments.count
1976
- end
1977
- end
1978
-
1979
- test "collection proxy respects default scope" do
1980
- author = authors(:mary)
1981
- assert !author.first_posts.exists?
1982
- end
1983
-
1984
- test "association with extend option" do
1985
- post = posts(:welcome)
1986
- assert_equal "lifo", post.comments_with_extend.author
1987
- assert_equal "hello", post.comments_with_extend.greeting
1988
- end
1989
-
1990
- test "association with extend option with multiple extensions" do
1991
- post = posts(:welcome)
1992
- assert_equal "lifo", post.comments_with_extend_2.author
1993
- assert_equal "hello", post.comments_with_extend_2.greeting
1994
- end
1995
-
1996
- test "delete record with complex joins" do
1997
- david = authors(:david)
1998
-
1999
- post = david.posts.first
2000
- post.type = 'PostWithSpecialCategorization'
2001
- post.save
2002
-
2003
- categorization = post.categorizations.first
2004
- categorization.special = true
2005
- categorization.save
2006
-
2007
- assert_not_equal [], david.posts_with_special_categorizations
2008
- david.posts_with_special_categorizations = []
2009
- assert_equal [], david.posts_with_special_categorizations
2010
- end
2011
-
2012
- test "does not duplicate associations when used with natural primary keys" do
2013
- speedometer = Speedometer.create!(id: '4')
2014
- speedometer.minivans.create!(minivan_id: 'a-van-red' ,name: 'a van', color: 'red')
2015
-
2016
- assert_equal 1, speedometer.minivans.to_a.size, "Only one association should be present:\n#{speedometer.minivans.to_a}"
2017
- assert_equal 1, speedometer.reload.minivans.to_a.size
2018
- end
2019
-
2020
- test "can unscope the default scope of the associated model" do
2021
- car = Car.create!
2022
- bulb1 = Bulb.create! name: "defaulty", car: car
2023
- bulb2 = Bulb.create! name: "other", car: car
2024
-
2025
- assert_equal [bulb1], car.bulbs
2026
- assert_equal [bulb1, bulb2], car.all_bulbs.sort_by(&:id)
2027
- end
2028
-
2029
- test 'unscopes the default scope of associated model when used with include' do
2030
- car = Car.create!
2031
- bulb = Bulb.create! name: "other", car: car
2032
-
2033
- assert_equal bulb, Car.find(car.id).all_bulbs.first
2034
- assert_equal bulb, Car.includes(:all_bulbs).find(car.id).all_bulbs.first
2035
- end
2036
-
2037
- test "raises RecordNotDestroyed when replaced child can't be destroyed" do
2038
- car = Car.create!
2039
- original_child = FailedBulb.create!(car: car)
2040
-
2041
- error = assert_raise(ActiveRecord::RecordNotDestroyed) do
2042
- car.failed_bulbs = [FailedBulb.create!]
2043
- end
2044
-
2045
- assert_equal [original_child], car.reload.failed_bulbs
2046
- assert_equal "Failed to destroy the record", error.message
2047
- end
2048
-
2049
- test 'updates counter cache when default scope is given' do
2050
- topic = DefaultRejectedTopic.create approved: true
2051
-
2052
- assert_difference "topic.reload.replies_count", 1 do
2053
- topic.approved_replies.create!
2054
- end
2055
- end
2056
-
2057
- test 'dangerous association name raises ArgumentError' do
2058
- [:errors, 'errors', :save, 'save'].each do |name|
2059
- assert_raises(ArgumentError, "Association #{name} should not be allowed") do
2060
- Class.new(ActiveRecord::Base) do
2061
- has_many name
2062
- end
2063
- end
2064
- end
2065
- end
2066
-
2067
- test 'passes custom context validation to validate children' do
2068
- pirate = FamousPirate.new
2069
- pirate.famous_ships << ship = FamousShip.new
2070
-
2071
- assert pirate.valid?
2072
- assert_not pirate.valid?(:conference)
2073
- assert_equal "can't be blank", ship.errors[:name].first
2074
- end
2075
-
2076
- test 'association with instance dependent scope' do
2077
- bob = authors(:bob)
2078
- Post.create!(title: "signed post by bob", body: "stuff", author: authors(:bob))
2079
- Post.create!(title: "anonymous post", body: "more stuff", author: authors(:bob))
2080
- assert_equal ["misc post by bob", "other post by bob",
2081
- "signed post by bob"], bob.posts_with_signature.map(&:title).sort
2082
-
2083
- assert_equal [], authors(:david).posts_with_signature.map(&:title)
2084
- end
2085
-
2086
- test 'associations autosaves when object is already persited' do
2087
- bulb = Bulb.create!
2088
- tyre = Tyre.create!
2089
-
2090
- car = Car.create! do |c|
2091
- c.bulbs << bulb
2092
- c.tyres << tyre
2093
- end
2094
-
2095
- assert_equal 1, car.bulbs.count
2096
- assert_equal 1, car.tyres.count
2097
- end
2098
-
2099
- test 'associations replace in memory when records have the same id' do
2100
- bulb = Bulb.create!
2101
- car = Car.create!(bulbs: [bulb])
2102
-
2103
- new_bulb = Bulb.find(bulb.id)
2104
- new_bulb.name = "foo"
2105
- car.bulbs = [new_bulb]
2106
-
2107
- assert_equal "foo", car.bulbs.first.name
2108
- end
2109
-
2110
- test 'in memory replacement executes no queries' do
2111
- bulb = Bulb.create!
2112
- car = Car.create!(bulbs: [bulb])
2113
-
2114
- new_bulb = Bulb.find(bulb.id)
2115
-
2116
- assert_no_queries do
2117
- car.bulbs = [new_bulb]
2118
- end
2119
- end
2120
-
2121
- test 'in memory replacements do not execute callbacks' do
2122
- raise_after_add = false
2123
- klass = Class.new(ActiveRecord::Base) do
2124
- self.table_name = :cars
2125
- has_many :bulbs, after_add: proc { raise if raise_after_add }
2126
-
2127
- def self.name
2128
- "Car"
2129
- end
2130
- end
2131
- bulb = Bulb.create!
2132
- car = klass.create!(bulbs: [bulb])
2133
-
2134
- new_bulb = Bulb.find(bulb.id)
2135
- raise_after_add = true
2136
-
2137
- assert_nothing_raised do
2138
- car.bulbs = [new_bulb]
2139
- end
2140
- end
2141
-
2142
- test 'in memory replacements sets inverse instance' do
2143
- bulb = Bulb.create!
2144
- car = Car.create!(bulbs: [bulb])
2145
-
2146
- new_bulb = Bulb.find(bulb.id)
2147
- car.bulbs = [new_bulb]
2148
-
2149
- assert_same car, new_bulb.car
2150
- end
2151
-
2152
- test 'in memory replacement maintains order' do
2153
- first_bulb = Bulb.create!
2154
- second_bulb = Bulb.create!
2155
- car = Car.create!(bulbs: [first_bulb, second_bulb])
2156
-
2157
- same_bulb = Bulb.find(first_bulb.id)
2158
- car.bulbs = [second_bulb, same_bulb]
2159
-
2160
- assert_equal [first_bulb, second_bulb], car.bulbs
2161
- end
2162
- end
1
+ require "cases/helper"
2
+ require 'models/developer'
3
+ require 'models/computer'
4
+ require 'models/project'
5
+ require 'models/company'
6
+ require 'models/contract'
7
+ require 'models/topic'
8
+ require 'models/reply'
9
+ require 'models/category'
10
+ require 'models/image'
11
+ require 'models/post'
12
+ require 'models/author'
13
+ require 'models/essay'
14
+ require 'models/comment'
15
+ require 'models/person'
16
+ require 'models/reader'
17
+ require 'models/tagging'
18
+ require 'models/tag'
19
+ require 'models/invoice'
20
+ require 'models/line_item'
21
+ require 'models/car'
22
+ require 'models/bulb'
23
+ require 'models/engine'
24
+ require 'models/categorization'
25
+ require 'models/minivan'
26
+ require 'models/speedometer'
27
+ require 'models/reference'
28
+ require 'models/job'
29
+ require 'models/college'
30
+ require 'models/student'
31
+ require 'models/pirate'
32
+ require 'models/ship'
33
+ require 'models/treasure'
34
+ require 'models/parrot'
35
+ require 'models/tyre'
36
+ require 'models/subscriber'
37
+ require 'models/subscription'
38
+ require 'models/zine'
39
+ require 'models/interest'
40
+
41
+ class HasManyAssociationsTestForReorderWithJoinDependency < ActiveRecord::TestCase
42
+ fixtures :authors, :posts, :comments, :author_addresses
43
+
44
+ def test_should_generate_valid_sql
45
+ author = authors(:david)
46
+ # this can fail on adapters which require ORDER BY expressions to be included in the SELECT expression
47
+ # if the reorder clauses are not correctly handled
48
+ assert author.posts_with_comments_sorted_by_comment_id.where('comments.id > 0').reorder('posts.comments_count DESC', 'posts.tags_count DESC').last
49
+ end
50
+ end
51
+
52
+ class HasManyAssociationsTestPrimaryKeys < ActiveRecord::TestCase
53
+ fixtures :authors, :essays, :subscribers, :subscriptions, :people
54
+
55
+ def test_custom_primary_key_on_new_record_should_fetch_with_query
56
+ subscriber = Subscriber.new(nick: 'webster132')
57
+ assert !subscriber.subscriptions.loaded?
58
+
59
+ assert_queries 1 do
60
+ assert_equal 2, subscriber.subscriptions.size
61
+ end
62
+
63
+ assert_equal subscriber.subscriptions, Subscription.where(subscriber_id: 'webster132')
64
+ end
65
+
66
+ def test_association_primary_key_on_new_record_should_fetch_with_query
67
+ author = Author.new(:name => "David")
68
+ assert !author.essays.loaded?
69
+
70
+ assert_queries 1 do
71
+ assert_equal 1, author.essays.size
72
+ end
73
+
74
+ assert_equal author.essays, Essay.where(writer_id: "David")
75
+ end
76
+
77
+ def test_has_many_custom_primary_key
78
+ david = authors(:david)
79
+ assert_equal david.essays, Essay.where(writer_id: "David")
80
+ end
81
+
82
+ def test_has_many_assignment_with_custom_primary_key
83
+ david = people(:david)
84
+
85
+ assert_equal ["A Modest Proposal"], david.essays.map(&:name)
86
+ david.essays = [Essay.create!(name: "Remote Work" )]
87
+ assert_equal ["Remote Work"], david.essays.map(&:name)
88
+ end
89
+
90
+ def test_blank_custom_primary_key_on_new_record_should_not_run_queries
91
+ author = Author.new
92
+ assert !author.essays.loaded?
93
+
94
+ assert_queries 0 do
95
+ assert_equal 0, author.essays.size
96
+ end
97
+ end
98
+ end
99
+
100
+ class HasManyAssociationsTest < ActiveRecord::TestCase
101
+ fixtures :accounts, :categories, :companies, :developers, :projects,
102
+ :developers_projects, :topics, :authors, :comments,
103
+ :posts, :readers, :taggings, :cars, :jobs, :tags,
104
+ :categorizations, :zines, :interests
105
+
106
+ def setup
107
+ Client.destroyed_client_ids.clear
108
+ end
109
+
110
+ def test_sti_subselect_count
111
+ tag = Tag.first
112
+ len = Post.tagged_with(tag.id).limit(10).size
113
+ assert_operator len, :>, 0
114
+ end
115
+
116
+ def test_anonymous_has_many
117
+ developer = Class.new(ActiveRecord::Base) {
118
+ self.table_name = 'developers'
119
+ dev = self
120
+
121
+ developer_project = Class.new(ActiveRecord::Base) {
122
+ self.table_name = 'developers_projects'
123
+ belongs_to :developer, :anonymous_class => dev
124
+ }
125
+ has_many :developer_projects, :anonymous_class => developer_project, :foreign_key => 'developer_id'
126
+ }
127
+ dev = developer.first
128
+ named = Developer.find(dev.id)
129
+ assert_operator dev.developer_projects.count, :>, 0
130
+ assert_equal named.projects.map(&:id).sort,
131
+ dev.developer_projects.map(&:project_id).sort
132
+ end
133
+
134
+ def test_default_scope_on_relations_is_not_cached
135
+ counter = 0
136
+ posts = Class.new(ActiveRecord::Base) {
137
+ self.table_name = 'posts'
138
+ self.inheritance_column = 'not_there'
139
+ post = self
140
+
141
+ comments = Class.new(ActiveRecord::Base) {
142
+ self.table_name = 'comments'
143
+ self.inheritance_column = 'not_there'
144
+ belongs_to :post, :anonymous_class => post
145
+ default_scope -> {
146
+ counter += 1
147
+ where("id = :inc", :inc => counter)
148
+ }
149
+ }
150
+ has_many :comments, :anonymous_class => comments, :foreign_key => 'post_id'
151
+ }
152
+ assert_equal 0, counter
153
+ post = posts.first
154
+ assert_equal 0, counter
155
+ sql = capture_sql { post.comments.to_a }
156
+ post.comments.reset
157
+ assert_not_equal sql, capture_sql { post.comments.to_a }
158
+ end
159
+
160
+ def test_has_many_build_with_options
161
+ college = College.create(name: 'UFMT')
162
+ Student.create(active: true, college_id: college.id, name: 'Sarah')
163
+
164
+ assert_equal college.students, Student.where(active: true, college_id: college.id)
165
+ end
166
+
167
+ def test_create_from_association_should_respect_default_scope
168
+ car = Car.create(:name => 'honda')
169
+ assert_equal 'honda', car.name
170
+
171
+ bulb = Bulb.create
172
+ assert_equal 'defaulty', bulb.name
173
+
174
+ bulb = car.bulbs.build
175
+ assert_equal 'defaulty', bulb.name
176
+
177
+ bulb = car.bulbs.create
178
+ assert_equal 'defaulty', bulb.name
179
+
180
+ bulb = car.bulbs.create(:name => 'exotic')
181
+ assert_equal 'exotic', bulb.name
182
+ end
183
+
184
+ def test_build_from_association_should_respect_scope
185
+ author = Author.new
186
+
187
+ post = author.thinking_posts.build
188
+ assert_equal 'So I was thinking', post.title
189
+ end
190
+
191
+ def test_create_from_association_with_nil_values_should_work
192
+ car = Car.create(:name => 'honda')
193
+
194
+ bulb = car.bulbs.new(nil)
195
+ assert_equal 'defaulty', bulb.name
196
+
197
+ bulb = car.bulbs.build(nil)
198
+ assert_equal 'defaulty', bulb.name
199
+
200
+ bulb = car.bulbs.create(nil)
201
+ assert_equal 'defaulty', bulb.name
202
+ end
203
+
204
+ def test_do_not_call_callbacks_for_delete_all
205
+ car = Car.create(:name => 'honda')
206
+ car.funky_bulbs.create!
207
+ assert_nothing_raised { car.reload.funky_bulbs.delete_all }
208
+ assert_equal 0, Bulb.count, "bulbs should have been deleted using :delete_all strategy"
209
+ end
210
+
211
+ def test_delete_all_on_association_is_the_same_as_not_loaded
212
+ author = authors :david
213
+ author.thinking_posts.create!(:body => "test")
214
+ author.reload
215
+ expected_sql = capture_sql { author.thinking_posts.delete_all }
216
+
217
+ author.thinking_posts.create!(:body => "test")
218
+ author.reload
219
+ author.thinking_posts.inspect
220
+ loaded_sql = capture_sql { author.thinking_posts.delete_all }
221
+ assert_equal(expected_sql, loaded_sql)
222
+ end
223
+
224
+ def test_delete_all_on_association_with_nil_dependency_is_the_same_as_not_loaded
225
+ author = authors :david
226
+ author.posts.create!(:title => "test", :body => "body")
227
+ author.reload
228
+ expected_sql = capture_sql { author.posts.delete_all }
229
+
230
+ author.posts.create!(:title => "test", :body => "body")
231
+ author.reload
232
+ author.posts.to_a
233
+ loaded_sql = capture_sql { author.posts.delete_all }
234
+ assert_equal(expected_sql, loaded_sql)
235
+ end
236
+
237
+ def test_building_the_associated_object_with_implicit_sti_base_class
238
+ firm = DependentFirm.new
239
+ company = firm.companies.build
240
+ assert_kind_of Company, company, "Expected #{company.class} to be a Company"
241
+ end
242
+
243
+ def test_building_the_associated_object_with_explicit_sti_base_class
244
+ firm = DependentFirm.new
245
+ company = firm.companies.build(:type => "Company")
246
+ assert_kind_of Company, company, "Expected #{company.class} to be a Company"
247
+ end
248
+
249
+ def test_building_the_associated_object_with_sti_subclass
250
+ firm = DependentFirm.new
251
+ company = firm.companies.build(:type => "Client")
252
+ assert_kind_of Client, company, "Expected #{company.class} to be a Client"
253
+ end
254
+
255
+ def test_building_the_associated_object_with_an_invalid_type
256
+ firm = DependentFirm.new
257
+ assert_raise(ActiveRecord::SubclassNotFound) { firm.companies.build(:type => "Invalid") }
258
+ end
259
+
260
+ def test_building_the_associated_object_with_an_unrelated_type
261
+ firm = DependentFirm.new
262
+ assert_raise(ActiveRecord::SubclassNotFound) { firm.companies.build(:type => "Account") }
263
+ end
264
+
265
+ test "building the association with an array" do
266
+ speedometer = Speedometer.new(speedometer_id: "a")
267
+ data = [{name: "first"}, {name: "second"}]
268
+ speedometer.minivans.build(data)
269
+
270
+ assert_equal 2, speedometer.minivans.size
271
+ assert speedometer.save
272
+ assert_equal ["first", "second"], speedometer.reload.minivans.map(&:name)
273
+ end
274
+
275
+ def test_association_keys_bypass_attribute_protection
276
+ car = Car.create(:name => 'honda')
277
+
278
+ bulb = car.bulbs.new
279
+ assert_equal car.id, bulb.car_id
280
+
281
+ bulb = car.bulbs.new :car_id => car.id + 1
282
+ assert_equal car.id, bulb.car_id
283
+
284
+ bulb = car.bulbs.build
285
+ assert_equal car.id, bulb.car_id
286
+
287
+ bulb = car.bulbs.build :car_id => car.id + 1
288
+ assert_equal car.id, bulb.car_id
289
+
290
+ bulb = car.bulbs.create
291
+ assert_equal car.id, bulb.car_id
292
+
293
+ bulb = car.bulbs.create :car_id => car.id + 1
294
+ assert_equal car.id, bulb.car_id
295
+ end
296
+
297
+ def test_association_protect_foreign_key
298
+ invoice = Invoice.create
299
+
300
+ line_item = invoice.line_items.new
301
+ assert_equal invoice.id, line_item.invoice_id
302
+
303
+ line_item = invoice.line_items.new :invoice_id => invoice.id + 1
304
+ assert_equal invoice.id, line_item.invoice_id
305
+
306
+ line_item = invoice.line_items.build
307
+ assert_equal invoice.id, line_item.invoice_id
308
+
309
+ line_item = invoice.line_items.build :invoice_id => invoice.id + 1
310
+ assert_equal invoice.id, line_item.invoice_id
311
+
312
+ line_item = invoice.line_items.create
313
+ assert_equal invoice.id, line_item.invoice_id
314
+
315
+ line_item = invoice.line_items.create :invoice_id => invoice.id + 1
316
+ assert_equal invoice.id, line_item.invoice_id
317
+ end
318
+
319
+ # When creating objects on the association, we must not do it within a scope (even though it
320
+ # would be convenient), because this would cause that scope to be applied to any callbacks etc.
321
+ def test_build_and_create_should_not_happen_within_scope
322
+ car = cars(:honda)
323
+ scoped_count = car.foo_bulbs.where_values.count
324
+
325
+ bulb = car.foo_bulbs.build
326
+ assert_not_equal scoped_count, bulb.scope_after_initialize.where_values.count
327
+
328
+ bulb = car.foo_bulbs.create
329
+ assert_not_equal scoped_count, bulb.scope_after_initialize.where_values.count
330
+
331
+ bulb = car.foo_bulbs.create!
332
+ assert_not_equal scoped_count, bulb.scope_after_initialize.where_values.count
333
+ end
334
+
335
+ def test_no_sql_should_be_fired_if_association_already_loaded
336
+ Car.create(:name => 'honda')
337
+ bulbs = Car.first.bulbs
338
+ bulbs.to_a # to load all instances of bulbs
339
+
340
+ assert_no_queries do
341
+ bulbs.first()
342
+ bulbs.first({})
343
+ end
344
+
345
+ assert_no_queries do
346
+ bulbs.second()
347
+ bulbs.second({})
348
+ end
349
+
350
+ assert_no_queries do
351
+ bulbs.third()
352
+ bulbs.third({})
353
+ end
354
+
355
+ assert_no_queries do
356
+ bulbs.fourth()
357
+ bulbs.fourth({})
358
+ end
359
+
360
+ assert_no_queries do
361
+ bulbs.fifth()
362
+ bulbs.fifth({})
363
+ end
364
+
365
+ assert_no_queries do
366
+ bulbs.forty_two()
367
+ bulbs.forty_two({})
368
+ end
369
+
370
+ assert_no_queries do
371
+ bulbs.last()
372
+ bulbs.last({})
373
+ end
374
+ end
375
+
376
+ def test_create_resets_cached_counters
377
+ person = Person.create!(:first_name => 'tenderlove')
378
+ post = Post.first
379
+
380
+ assert_equal [], person.readers
381
+ assert_nil person.readers.find_by_post_id(post.id)
382
+
383
+ person.readers.create(:post_id => post.id)
384
+
385
+ assert_equal 1, person.readers.count
386
+ assert_equal 1, person.readers.length
387
+ assert_equal post, person.readers.first.post
388
+ assert_equal person, person.readers.first.person
389
+ end
390
+
391
+ def force_signal37_to_load_all_clients_of_firm
392
+ companies(:first_firm).clients_of_firm.each {|f| }
393
+ end
394
+
395
+ # sometimes tests on Oracle fail if ORDER BY is not provided therefore add always :order with :first
396
+ def test_counting_with_counter_sql
397
+ assert_equal 3, Firm.all.merge!(:order => "id").first.clients.count
398
+ end
399
+
400
+ def test_counting
401
+ assert_equal 3, Firm.all.merge!(:order => "id").first.plain_clients.count
402
+ end
403
+
404
+ def test_counting_with_single_hash
405
+ assert_equal 1, Firm.all.merge!(:order => "id").first.plain_clients.where(:name => "Microsoft").count
406
+ end
407
+
408
+ def test_counting_with_column_name_and_hash
409
+ assert_equal 3, Firm.all.merge!(:order => "id").first.plain_clients.count(:name)
410
+ end
411
+
412
+ def test_counting_with_association_limit
413
+ firm = companies(:first_firm)
414
+ assert_equal firm.limited_clients.length, firm.limited_clients.size
415
+ assert_equal firm.limited_clients.length, firm.limited_clients.count
416
+ end
417
+
418
+ def test_finding
419
+ assert_equal 3, Firm.all.merge!(:order => "id").first.clients.length
420
+ end
421
+
422
+ def test_finding_array_compatibility
423
+ assert_equal 3, Firm.order(:id).find{|f| f.id > 0}.clients.length
424
+ end
425
+
426
+ def test_find_many_with_merged_options
427
+ assert_equal 1, companies(:first_firm).limited_clients.size
428
+ assert_equal 1, companies(:first_firm).limited_clients.to_a.size
429
+ assert_equal 3, companies(:first_firm).limited_clients.limit(nil).to_a.size
430
+ end
431
+
432
+ def test_find_should_append_to_association_order
433
+ ordered_clients = companies(:first_firm).clients_sorted_desc.order('companies.id')
434
+ assert_equal ['id DESC', 'companies.id'], ordered_clients.order_values
435
+ end
436
+
437
+ def test_dynamic_find_should_respect_association_order
438
+ assert_equal companies(:another_first_firm_client), companies(:first_firm).clients_sorted_desc.where("type = 'Client'").first
439
+ assert_equal companies(:another_first_firm_client), companies(:first_firm).clients_sorted_desc.find_by_type('Client')
440
+ end
441
+
442
+ def test_taking
443
+ posts(:other_by_bob).destroy
444
+ assert_equal posts(:misc_by_bob), authors(:bob).posts.take
445
+ assert_equal posts(:misc_by_bob), authors(:bob).posts.take!
446
+ authors(:bob).posts.to_a
447
+ assert_equal posts(:misc_by_bob), authors(:bob).posts.take
448
+ assert_equal posts(:misc_by_bob), authors(:bob).posts.take!
449
+ end
450
+
451
+ def test_taking_not_found
452
+ authors(:bob).posts.delete_all
453
+ assert_raise(ActiveRecord::RecordNotFound) { authors(:bob).posts.take! }
454
+ authors(:bob).posts.to_a
455
+ assert_raise(ActiveRecord::RecordNotFound) { authors(:bob).posts.take! }
456
+ end
457
+
458
+ def test_taking_with_a_number
459
+ # taking from unloaded Relation
460
+ bob = Author.find(authors(:bob).id)
461
+ assert_equal [posts(:misc_by_bob)], bob.posts.take(1)
462
+ bob = Author.find(authors(:bob).id)
463
+ assert_equal [posts(:misc_by_bob), posts(:other_by_bob)], bob.posts.take(2)
464
+
465
+ # taking from loaded Relation
466
+ bob.posts.to_a
467
+ assert_equal [posts(:misc_by_bob)], authors(:bob).posts.take(1)
468
+ assert_equal [posts(:misc_by_bob), posts(:other_by_bob)], authors(:bob).posts.take(2)
469
+ end
470
+
471
+ def test_taking_with_inverse_of
472
+ interests(:woodsmanship).destroy
473
+ interests(:survival).destroy
474
+
475
+ zine = zines(:going_out)
476
+ interest = zine.interests.take
477
+ assert_equal interests(:hunting), interest
478
+ assert_same zine, interest.zine
479
+ end
480
+
481
+ def test_cant_save_has_many_readonly_association
482
+ authors(:david).readonly_comments.each { |c| assert_raise(ActiveRecord::ReadOnlyRecord) { c.save! } }
483
+ authors(:david).readonly_comments.each { |c| assert c.readonly? }
484
+ end
485
+
486
+ def test_finding_default_orders
487
+ assert_equal "Summit", Firm.all.merge!(:order => "id").first.clients.first.name
488
+ end
489
+
490
+ def test_finding_with_different_class_name_and_order
491
+ assert_equal "Apex", Firm.all.merge!(:order => "id").first.clients_sorted_desc.first.name
492
+ end
493
+
494
+ def test_finding_with_foreign_key
495
+ assert_equal "Microsoft", Firm.all.merge!(:order => "id").first.clients_of_firm.first.name
496
+ end
497
+
498
+ def test_finding_with_condition
499
+ assert_equal "Microsoft", Firm.all.merge!(:order => "id").first.clients_like_ms.first.name
500
+ end
501
+
502
+ def test_finding_with_condition_hash
503
+ assert_equal "Microsoft", Firm.all.merge!(:order => "id").first.clients_like_ms_with_hash_conditions.first.name
504
+ end
505
+
506
+ def test_finding_using_primary_key
507
+ assert_equal "Summit", Firm.all.merge!(:order => "id").first.clients_using_primary_key.first.name
508
+ end
509
+
510
+ def test_update_all_on_association_accessed_before_save
511
+ firm = Firm.new(name: 'Firm')
512
+ firm.clients << Client.first
513
+ firm.save!
514
+ assert_equal firm.clients.count, firm.clients.update_all(description: 'Great!')
515
+ end
516
+
517
+ def test_belongs_to_sanity
518
+ c = Client.new
519
+ assert_nil c.firm, "belongs_to failed sanity check on new object"
520
+ end
521
+
522
+ def test_find_ids
523
+ firm = Firm.all.merge!(:order => "id").first
524
+
525
+ assert_raise(ActiveRecord::RecordNotFound) { firm.clients.find }
526
+
527
+ client = firm.clients.find(2)
528
+ assert_kind_of Client, client
529
+
530
+ client_ary = firm.clients.find([2])
531
+ assert_kind_of Array, client_ary
532
+ assert_equal client, client_ary.first
533
+
534
+ client_ary = firm.clients.find(2, 3)
535
+ assert_kind_of Array, client_ary
536
+ assert_equal 2, client_ary.size
537
+ assert_equal client, client_ary.first
538
+
539
+ assert_raise(ActiveRecord::RecordNotFound) { firm.clients.find(2, 99) }
540
+ end
541
+
542
+ def test_find_ids_and_inverse_of
543
+ force_signal37_to_load_all_clients_of_firm
544
+
545
+ firm = companies(:first_firm)
546
+ client = firm.clients_of_firm.find(3)
547
+ assert_kind_of Client, client
548
+
549
+ client_ary = firm.clients_of_firm.find([3])
550
+ assert_kind_of Array, client_ary
551
+ assert_equal client, client_ary.first
552
+ end
553
+
554
+ def test_find_all
555
+ firm = Firm.all.merge!(:order => "id").first
556
+ assert_equal 3, firm.clients.where("#{QUOTED_TYPE} = 'Client'").to_a.length
557
+ assert_equal 1, firm.clients.where("name = 'Summit'").to_a.length
558
+ end
559
+
560
+ def test_find_each
561
+ firm = companies(:first_firm)
562
+
563
+ assert ! firm.clients.loaded?
564
+
565
+ assert_queries(4) do
566
+ firm.clients.find_each(:batch_size => 1) {|c| assert_equal firm.id, c.firm_id }
567
+ end
568
+
569
+ assert ! firm.clients.loaded?
570
+ end
571
+
572
+ def test_find_each_with_conditions
573
+ firm = companies(:first_firm)
574
+
575
+ assert_queries(2) do
576
+ firm.clients.where(name: 'Microsoft').find_each(batch_size: 1) do |c|
577
+ assert_equal firm.id, c.firm_id
578
+ assert_equal "Microsoft", c.name
579
+ end
580
+ end
581
+
582
+ assert ! firm.clients.loaded?
583
+ end
584
+
585
+ def test_find_in_batches
586
+ firm = companies(:first_firm)
587
+
588
+ assert ! firm.clients.loaded?
589
+
590
+ assert_queries(2) do
591
+ firm.clients.find_in_batches(:batch_size => 2) do |clients|
592
+ clients.each {|c| assert_equal firm.id, c.firm_id }
593
+ end
594
+ end
595
+
596
+ assert ! firm.clients.loaded?
597
+ end
598
+
599
+ def test_find_all_sanitized
600
+ # sometimes tests on Oracle fail if ORDER BY is not provided therefore add always :order with :first
601
+ firm = Firm.all.merge!(:order => "id").first
602
+ summit = firm.clients.where("name = 'Summit'").to_a
603
+ assert_equal summit, firm.clients.where("name = ?", "Summit").to_a
604
+ assert_equal summit, firm.clients.where("name = :name", { :name => "Summit" }).to_a
605
+ end
606
+
607
+ def test_find_first
608
+ firm = Firm.all.merge!(:order => "id").first
609
+ client2 = Client.find(2)
610
+ assert_equal firm.clients.first, firm.clients.order("id").first
611
+ assert_equal client2, firm.clients.where("#{QUOTED_TYPE} = 'Client'").order("id").first
612
+ end
613
+
614
+ def test_find_first_sanitized
615
+ firm = Firm.all.merge!(:order => "id").first
616
+ client2 = Client.find(2)
617
+ assert_equal client2, firm.clients.merge!(:where => ["#{QUOTED_TYPE} = ?", 'Client'], :order => "id").first
618
+ assert_equal client2, firm.clients.merge!(:where => ["#{QUOTED_TYPE} = :type", { :type => 'Client' }], :order => "id").first
619
+ end
620
+
621
+ def test_find_all_with_include_and_conditions
622
+ assert_nothing_raised do
623
+ Developer.all.merge!(:joins => :audit_logs, :where => {'audit_logs.message' => nil, :name => 'Smith'}).to_a
624
+ end
625
+ end
626
+
627
+ def test_find_in_collection
628
+ assert_equal Client.find(2).name, companies(:first_firm).clients.find(2).name
629
+ assert_raise(ActiveRecord::RecordNotFound) { companies(:first_firm).clients.find(6) }
630
+ end
631
+
632
+ def test_find_grouped
633
+ all_clients_of_firm1 = Client.all.merge!(:where => "firm_id = 1").to_a
634
+ grouped_clients_of_firm1 = Client.all.merge!(:where => "firm_id = 1", :group => "firm_id", :select => 'firm_id, count(id) as clients_count').to_a
635
+ assert_equal 3, all_clients_of_firm1.size
636
+ assert_equal 1, grouped_clients_of_firm1.size
637
+ end
638
+
639
+ def test_find_scoped_grouped
640
+ assert_equal 1, companies(:first_firm).clients_grouped_by_firm_id.size
641
+ assert_equal 1, companies(:first_firm).clients_grouped_by_firm_id.length
642
+ assert_equal 3, companies(:first_firm).clients_grouped_by_name.size
643
+ assert_equal 3, companies(:first_firm).clients_grouped_by_name.length
644
+ end
645
+
646
+ def test_find_scoped_grouped_having
647
+ assert_equal 1, authors(:david).popular_grouped_posts.length
648
+ assert_equal 0, authors(:mary).popular_grouped_posts.length
649
+ end
650
+
651
+ def test_default_select
652
+ assert_equal Comment.column_names.sort, posts(:welcome).comments.first.attributes.keys.sort
653
+ end
654
+
655
+ def test_select_query_method
656
+ assert_equal ['id', 'body'], posts(:welcome).comments.select(:id, :body).first.attributes.keys
657
+ end
658
+
659
+ def test_select_with_block
660
+ assert_equal [1], posts(:welcome).comments.select { |c| c.id == 1 }.map(&:id)
661
+ end
662
+
663
+ def test_select_without_foreign_key
664
+ assert_equal companies(:first_firm).accounts.first.credit_limit, companies(:first_firm).accounts.select(:credit_limit).first.credit_limit
665
+ end
666
+
667
+ def test_adding
668
+ force_signal37_to_load_all_clients_of_firm
669
+ natural = Client.new("name" => "Natural Company")
670
+ companies(:first_firm).clients_of_firm << natural
671
+ assert_equal 3, companies(:first_firm).clients_of_firm.size # checking via the collection
672
+ assert_equal 3, companies(:first_firm).clients_of_firm(true).size # checking using the db
673
+ assert_equal natural, companies(:first_firm).clients_of_firm.last
674
+ end
675
+
676
+ def test_adding_using_create
677
+ first_firm = companies(:first_firm)
678
+ assert_equal 3, first_firm.plain_clients.size
679
+ first_firm.plain_clients.create(:name => "Natural Company")
680
+ assert_equal 4, first_firm.plain_clients.length
681
+ assert_equal 4, first_firm.plain_clients.size
682
+ end
683
+
684
+ def test_create_with_bang_on_has_many_when_parent_is_new_raises
685
+ error = assert_raise(ActiveRecord::RecordNotSaved) do
686
+ firm = Firm.new
687
+ firm.plain_clients.create! :name=>"Whoever"
688
+ end
689
+
690
+ assert_equal "You cannot call create unless the parent is saved", error.message
691
+ end
692
+
693
+ def test_regular_create_on_has_many_when_parent_is_new_raises
694
+ error = assert_raise(ActiveRecord::RecordNotSaved) do
695
+ firm = Firm.new
696
+ firm.plain_clients.create :name=>"Whoever"
697
+ end
698
+
699
+ assert_equal "You cannot call create unless the parent is saved", error.message
700
+ end
701
+
702
+ def test_create_with_bang_on_has_many_raises_when_record_not_saved
703
+ assert_raise(ActiveRecord::RecordInvalid) do
704
+ firm = Firm.all.merge!(:order => "id").first
705
+ firm.plain_clients.create!
706
+ end
707
+ end
708
+
709
+ def test_create_with_bang_on_habtm_when_parent_is_new_raises
710
+ error = assert_raise(ActiveRecord::RecordNotSaved) do
711
+ Developer.new("name" => "Aredridel").projects.create!
712
+ end
713
+
714
+ assert_equal "You cannot call create unless the parent is saved", error.message
715
+ end
716
+
717
+ def test_adding_a_mismatch_class
718
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << nil }
719
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << 1 }
720
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << Topic.find(1) }
721
+ end
722
+
723
+ def test_adding_a_collection
724
+ force_signal37_to_load_all_clients_of_firm
725
+ companies(:first_firm).clients_of_firm.concat([Client.new("name" => "Natural Company"), Client.new("name" => "Apple")])
726
+ assert_equal 4, companies(:first_firm).clients_of_firm.size
727
+ assert_equal 4, companies(:first_firm).clients_of_firm(true).size
728
+ end
729
+
730
+ def test_transactions_when_adding_to_persisted
731
+ good = Client.new(:name => "Good")
732
+ bad = Client.new(:name => "Bad", :raise_on_save => true)
733
+
734
+ begin
735
+ companies(:first_firm).clients_of_firm.concat(good, bad)
736
+ rescue Client::RaisedOnSave
737
+ end
738
+
739
+ assert !companies(:first_firm).clients_of_firm(true).include?(good)
740
+ end
741
+
742
+ def test_transactions_when_adding_to_new_record
743
+ assert_no_queries(ignore_none: false) do
744
+ firm = Firm.new
745
+ firm.clients_of_firm.concat(Client.new("name" => "Natural Company"))
746
+ end
747
+ end
748
+
749
+ def test_inverse_on_before_validate
750
+ firm = companies(:first_firm)
751
+ assert_queries(1) do
752
+ firm.clients_of_firm << Client.new("name" => "Natural Company")
753
+ end
754
+ end
755
+
756
+ def test_new_aliased_to_build
757
+ company = companies(:first_firm)
758
+ new_client = assert_no_queries(ignore_none: false) { company.clients_of_firm.new("name" => "Another Client") }
759
+ assert !company.clients_of_firm.loaded?
760
+
761
+ assert_equal "Another Client", new_client.name
762
+ assert !new_client.persisted?
763
+ assert_equal new_client, company.clients_of_firm.last
764
+ end
765
+
766
+ def test_build
767
+ company = companies(:first_firm)
768
+ new_client = assert_no_queries(ignore_none: false) { company.clients_of_firm.build("name" => "Another Client") }
769
+ assert !company.clients_of_firm.loaded?
770
+
771
+ assert_equal "Another Client", new_client.name
772
+ assert !new_client.persisted?
773
+ assert_equal new_client, company.clients_of_firm.last
774
+ end
775
+
776
+ def test_collection_size_after_building
777
+ company = companies(:first_firm) # company already has one client
778
+ company.clients_of_firm.build("name" => "Another Client")
779
+ company.clients_of_firm.build("name" => "Yet Another Client")
780
+ assert_equal 4, company.clients_of_firm.size
781
+ end
782
+
783
+ def test_collection_not_empty_after_building
784
+ company = companies(:first_firm)
785
+ assert_predicate company.contracts, :empty?
786
+ company.contracts.build
787
+ assert_not_predicate company.contracts, :empty?
788
+ end
789
+
790
+ def test_collection_size_twice_for_regressions
791
+ post = posts(:thinking)
792
+ assert_equal 0, post.readers.size
793
+ # This test needs a post that has no readers, we assert it to ensure it holds,
794
+ # but need to reload the post because the very call to #size hides the bug.
795
+ post.reload
796
+ post.readers.build
797
+ size1 = post.readers.size
798
+ size2 = post.readers.size
799
+ assert_equal size1, size2
800
+ end
801
+
802
+ def test_build_many
803
+ company = companies(:first_firm)
804
+ new_clients = assert_no_queries(ignore_none: false) { company.clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}]) }
805
+ assert_equal 2, new_clients.size
806
+ end
807
+
808
+ def test_build_followed_by_save_does_not_load_target
809
+ companies(:first_firm).clients_of_firm.build("name" => "Another Client")
810
+ assert companies(:first_firm).save
811
+ assert !companies(:first_firm).clients_of_firm.loaded?
812
+ end
813
+
814
+ def test_build_without_loading_association
815
+ first_topic = topics(:first)
816
+ Reply.column_names
817
+
818
+ assert_equal 1, first_topic.replies.length
819
+
820
+ assert_no_queries do
821
+ first_topic.replies.build(:title => "Not saved", :content => "Superstars")
822
+ assert_equal 2, first_topic.replies.size
823
+ end
824
+
825
+ assert_equal 2, first_topic.replies.to_ary.size
826
+ end
827
+
828
+ def test_build_via_block
829
+ company = companies(:first_firm)
830
+ new_client = assert_no_queries(ignore_none: false) { company.clients_of_firm.build {|client| client.name = "Another Client" } }
831
+ assert !company.clients_of_firm.loaded?
832
+
833
+ assert_equal "Another Client", new_client.name
834
+ assert !new_client.persisted?
835
+ assert_equal new_client, company.clients_of_firm.last
836
+ end
837
+
838
+ def test_build_many_via_block
839
+ company = companies(:first_firm)
840
+ new_clients = assert_no_queries(ignore_none: false) do
841
+ company.clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}]) do |client|
842
+ client.name = "changed"
843
+ end
844
+ end
845
+
846
+ assert_equal 2, new_clients.size
847
+ assert_equal "changed", new_clients.first.name
848
+ assert_equal "changed", new_clients.last.name
849
+ end
850
+
851
+ def test_create_without_loading_association
852
+ first_firm = companies(:first_firm)
853
+ Firm.column_names
854
+ Client.column_names
855
+
856
+ assert_equal 2, first_firm.clients_of_firm.size
857
+ first_firm.clients_of_firm.reset
858
+
859
+ assert_queries(1) do
860
+ first_firm.clients_of_firm.create(:name => "Superstars")
861
+ end
862
+
863
+ assert_equal 3, first_firm.clients_of_firm.size
864
+ end
865
+
866
+ def test_create
867
+ force_signal37_to_load_all_clients_of_firm
868
+ new_client = companies(:first_firm).clients_of_firm.create("name" => "Another Client")
869
+ assert new_client.persisted?
870
+ assert_equal new_client, companies(:first_firm).clients_of_firm.last
871
+ assert_equal new_client, companies(:first_firm).clients_of_firm(true).last
872
+ end
873
+
874
+ def test_create_many
875
+ companies(:first_firm).clients_of_firm.create([{"name" => "Another Client"}, {"name" => "Another Client II"}])
876
+ assert_equal 4, companies(:first_firm).clients_of_firm(true).size
877
+ end
878
+
879
+ def test_create_followed_by_save_does_not_load_target
880
+ companies(:first_firm).clients_of_firm.create("name" => "Another Client")
881
+ assert companies(:first_firm).save
882
+ assert !companies(:first_firm).clients_of_firm.loaded?
883
+ end
884
+
885
+ def test_deleting
886
+ force_signal37_to_load_all_clients_of_firm
887
+ companies(:first_firm).clients_of_firm.delete(companies(:first_firm).clients_of_firm.first)
888
+ assert_equal 1, companies(:first_firm).clients_of_firm.size
889
+ assert_equal 1, companies(:first_firm).clients_of_firm(true).size
890
+ end
891
+
892
+ def test_deleting_before_save
893
+ new_firm = Firm.new("name" => "A New Firm, Inc.")
894
+ new_client = new_firm.clients_of_firm.build("name" => "Another Client")
895
+ assert_equal 1, new_firm.clients_of_firm.size
896
+ new_firm.clients_of_firm.delete(new_client)
897
+ assert_equal 0, new_firm.clients_of_firm.size
898
+ end
899
+
900
+ def test_has_many_without_counter_cache_option
901
+ # Ship has a conventionally named `treasures_count` column, but the counter_cache
902
+ # option is not given on the association.
903
+ ship = Ship.create(name: 'Countless', treasures_count: 10)
904
+
905
+ assert_not ship.treasures.instance_variable_get('@association').send(:has_cached_counter?)
906
+
907
+ # Count should come from sql count() of treasures rather than treasures_count attribute
908
+ assert_equal ship.treasures.size, 0
909
+
910
+ assert_no_difference lambda { ship.reload.treasures_count }, "treasures_count should not be changed" do
911
+ ship.treasures.create(name: 'Gold')
912
+ end
913
+
914
+ assert_no_difference lambda { ship.reload.treasures_count }, "treasures_count should not be changed" do
915
+ ship.treasures.destroy_all
916
+ end
917
+ end
918
+
919
+ def test_deleting_updates_counter_cache
920
+ topic = Topic.order("id ASC").first
921
+ assert_equal topic.replies.to_a.size, topic.replies_count
922
+
923
+ topic.replies.delete(topic.replies.first)
924
+ topic.reload
925
+ assert_equal topic.replies.to_a.size, topic.replies_count
926
+ end
927
+
928
+ def test_counter_cache_updates_in_memory_after_concat
929
+ topic = Topic.create title: "Zoom-zoom-zoom"
930
+
931
+ topic.replies << Reply.create(title: "re: zoom", content: "speedy quick!")
932
+ assert_equal 1, topic.replies_count
933
+ assert_equal 1, topic.replies.size
934
+ assert_equal 1, topic.reload.replies.size
935
+ end
936
+
937
+ def test_counter_cache_updates_in_memory_after_create
938
+ topic = Topic.create title: "Zoom-zoom-zoom"
939
+
940
+ topic.replies.create!(title: "re: zoom", content: "speedy quick!")
941
+ assert_equal 1, topic.replies_count
942
+ assert_equal 1, topic.replies.size
943
+ assert_equal 1, topic.reload.replies.size
944
+ end
945
+
946
+ def test_counter_cache_updates_in_memory_after_create_with_array
947
+ topic = Topic.create title: "Zoom-zoom-zoom"
948
+
949
+ topic.replies.create!([
950
+ { title: "re: zoom", content: "speedy quick!" },
951
+ { title: "re: zoom 2", content: "OMG lol!" },
952
+ ])
953
+ assert_equal 2, topic.replies_count
954
+ assert_equal 2, topic.replies.size
955
+ assert_equal 2, topic.reload.replies.size
956
+ end
957
+
958
+ def test_pushing_association_updates_counter_cache
959
+ topic = Topic.order("id ASC").first
960
+ reply = Reply.create!
961
+
962
+ assert_difference "topic.reload.replies_count", 1 do
963
+ topic.replies << reply
964
+ end
965
+ end
966
+
967
+ def test_deleting_updates_counter_cache_without_dependent_option
968
+ post = posts(:welcome)
969
+
970
+ assert_difference "post.reload.tags_count", -1 do
971
+ post.taggings.delete(post.taggings.first)
972
+ end
973
+ end
974
+
975
+ def test_deleting_updates_counter_cache_with_dependent_delete_all
976
+ post = posts(:welcome)
977
+ post.update_columns(taggings_with_delete_all_count: post.tags_count)
978
+
979
+ assert_difference "post.reload.taggings_with_delete_all_count", -1 do
980
+ post.taggings_with_delete_all.delete(post.taggings_with_delete_all.first)
981
+ end
982
+ end
983
+
984
+ def test_deleting_updates_counter_cache_with_dependent_destroy
985
+ post = posts(:welcome)
986
+ post.update_columns(taggings_with_destroy_count: post.tags_count)
987
+
988
+ assert_difference "post.reload.taggings_with_destroy_count", -1 do
989
+ post.taggings_with_destroy.delete(post.taggings_with_destroy.first)
990
+ end
991
+ end
992
+
993
+ def test_calling_empty_with_counter_cache
994
+ post = posts(:welcome)
995
+ assert_queries(0) do
996
+ assert_not post.comments.empty?
997
+ end
998
+ end
999
+
1000
+ def test_custom_named_counter_cache
1001
+ topic = topics(:first)
1002
+
1003
+ assert_difference "topic.reload.replies_count", -1 do
1004
+ topic.approved_replies.clear
1005
+ end
1006
+ end
1007
+
1008
+ def test_calling_update_attributes_on_id_changes_the_counter_cache
1009
+ topic = Topic.order("id ASC").first
1010
+ original_count = topic.replies.to_a.size
1011
+ assert_equal original_count, topic.replies_count
1012
+
1013
+ first_reply = topic.replies.first
1014
+ first_reply.update_attributes(:parent_id => nil)
1015
+ assert_equal original_count - 1, topic.reload.replies_count
1016
+
1017
+ first_reply.update_attributes(:parent_id => topic.id)
1018
+ assert_equal original_count, topic.reload.replies_count
1019
+ end
1020
+
1021
+ def test_calling_update_attributes_changing_ids_doesnt_change_counter_cache
1022
+ topic1 = Topic.find(1)
1023
+ topic2 = Topic.find(3)
1024
+ original_count1 = topic1.replies.to_a.size
1025
+ original_count2 = topic2.replies.to_a.size
1026
+
1027
+ reply1 = topic1.replies.first
1028
+ reply2 = topic2.replies.first
1029
+
1030
+ reply1.update_attributes(:parent_id => topic2.id)
1031
+ assert_equal original_count1 - 1, topic1.reload.replies_count
1032
+ assert_equal original_count2 + 1, topic2.reload.replies_count
1033
+
1034
+ reply2.update_attributes(:parent_id => topic1.id)
1035
+ assert_equal original_count1, topic1.reload.replies_count
1036
+ assert_equal original_count2, topic2.reload.replies_count
1037
+ end
1038
+
1039
+ def test_deleting_a_collection
1040
+ force_signal37_to_load_all_clients_of_firm
1041
+ companies(:first_firm).clients_of_firm.create("name" => "Another Client")
1042
+ assert_equal 3, companies(:first_firm).clients_of_firm.size
1043
+ companies(:first_firm).clients_of_firm.delete([companies(:first_firm).clients_of_firm[0], companies(:first_firm).clients_of_firm[1], companies(:first_firm).clients_of_firm[2]])
1044
+ assert_equal 0, companies(:first_firm).clients_of_firm.size
1045
+ assert_equal 0, companies(:first_firm).clients_of_firm(true).size
1046
+ end
1047
+
1048
+ def test_delete_all
1049
+ force_signal37_to_load_all_clients_of_firm
1050
+ companies(:first_firm).dependent_clients_of_firm.create("name" => "Another Client")
1051
+ clients = companies(:first_firm).dependent_clients_of_firm.to_a
1052
+ assert_equal 3, clients.count
1053
+
1054
+ assert_difference "Client.count", -(clients.count) do
1055
+ companies(:first_firm).dependent_clients_of_firm.delete_all
1056
+ end
1057
+ end
1058
+
1059
+ def test_delete_all_with_not_yet_loaded_association_collection
1060
+ force_signal37_to_load_all_clients_of_firm
1061
+ companies(:first_firm).clients_of_firm.create("name" => "Another Client")
1062
+ assert_equal 3, companies(:first_firm).clients_of_firm.size
1063
+ companies(:first_firm).clients_of_firm.reset
1064
+ companies(:first_firm).clients_of_firm.delete_all
1065
+ assert_equal 0, companies(:first_firm).clients_of_firm.size
1066
+ assert_equal 0, companies(:first_firm).clients_of_firm(true).size
1067
+ end
1068
+
1069
+ def test_transaction_when_deleting_persisted
1070
+ good = Client.new(:name => "Good")
1071
+ bad = Client.new(:name => "Bad", :raise_on_destroy => true)
1072
+
1073
+ companies(:first_firm).clients_of_firm = [good, bad]
1074
+
1075
+ begin
1076
+ companies(:first_firm).clients_of_firm.destroy(good, bad)
1077
+ rescue Client::RaisedOnDestroy
1078
+ end
1079
+
1080
+ assert_equal [good, bad], companies(:first_firm).clients_of_firm(true)
1081
+ end
1082
+
1083
+ def test_transaction_when_deleting_new_record
1084
+ assert_no_queries(ignore_none: false) do
1085
+ firm = Firm.new
1086
+ client = Client.new("name" => "New Client")
1087
+ firm.clients_of_firm << client
1088
+ firm.clients_of_firm.destroy(client)
1089
+ end
1090
+ end
1091
+
1092
+ def test_clearing_an_association_collection
1093
+ firm = companies(:first_firm)
1094
+ client_id = firm.clients_of_firm.first.id
1095
+ assert_equal 2, firm.clients_of_firm.size
1096
+
1097
+ firm.clients_of_firm.clear
1098
+
1099
+ assert_equal 0, firm.clients_of_firm.size
1100
+ assert_equal 0, firm.clients_of_firm(true).size
1101
+ assert_equal [], Client.destroyed_client_ids[firm.id]
1102
+
1103
+ # Should not be destroyed since the association is not dependent.
1104
+ assert_nothing_raised do
1105
+ assert_nil Client.find(client_id).firm
1106
+ end
1107
+ end
1108
+
1109
+ def test_clearing_updates_counter_cache
1110
+ topic = Topic.first
1111
+
1112
+ assert_difference 'topic.reload.replies_count', -1 do
1113
+ topic.replies.clear
1114
+ end
1115
+ end
1116
+
1117
+ def test_clearing_updates_counter_cache_when_inverse_counter_cache_is_a_symbol_with_dependent_destroy
1118
+ car = Car.first
1119
+ car.engines.create!
1120
+
1121
+ assert_difference 'car.reload.engines_count', -1 do
1122
+ car.engines.clear
1123
+ end
1124
+ end
1125
+
1126
+ def test_clearing_a_dependent_association_collection
1127
+ firm = companies(:first_firm)
1128
+ client_id = firm.dependent_clients_of_firm.first.id
1129
+ assert_equal 2, firm.dependent_clients_of_firm.size
1130
+ assert_equal 1, Client.find_by_id(client_id).client_of
1131
+
1132
+ # :delete_all is called on each client since the dependent options is :destroy
1133
+ firm.dependent_clients_of_firm.clear
1134
+
1135
+ assert_equal 0, firm.dependent_clients_of_firm.size
1136
+ assert_equal 0, firm.dependent_clients_of_firm(true).size
1137
+ assert_equal [], Client.destroyed_client_ids[firm.id]
1138
+
1139
+ # Should be destroyed since the association is dependent.
1140
+ assert_nil Client.find_by_id(client_id)
1141
+ end
1142
+
1143
+ def test_delete_all_with_option_delete_all
1144
+ firm = companies(:first_firm)
1145
+ client_id = firm.dependent_clients_of_firm.first.id
1146
+ firm.dependent_clients_of_firm.delete_all(:delete_all)
1147
+ assert_nil Client.find_by_id(client_id)
1148
+ end
1149
+
1150
+ def test_delete_all_accepts_limited_parameters
1151
+ firm = companies(:first_firm)
1152
+ assert_raise(ArgumentError) do
1153
+ firm.dependent_clients_of_firm.delete_all(:destroy)
1154
+ end
1155
+ end
1156
+
1157
+ def test_clearing_an_exclusively_dependent_association_collection
1158
+ firm = companies(:first_firm)
1159
+ client_id = firm.exclusively_dependent_clients_of_firm.first.id
1160
+ assert_equal 2, firm.exclusively_dependent_clients_of_firm.size
1161
+
1162
+ assert_equal [], Client.destroyed_client_ids[firm.id]
1163
+
1164
+ # :exclusively_dependent means each client is deleted directly from
1165
+ # the database without looping through them calling destroy.
1166
+ firm.exclusively_dependent_clients_of_firm.clear
1167
+
1168
+ assert_equal 0, firm.exclusively_dependent_clients_of_firm.size
1169
+ assert_equal 0, firm.exclusively_dependent_clients_of_firm(true).size
1170
+ # no destroy-filters should have been called
1171
+ assert_equal [], Client.destroyed_client_ids[firm.id]
1172
+
1173
+ # Should be destroyed since the association is exclusively dependent.
1174
+ assert_nil Client.find_by_id(client_id)
1175
+ end
1176
+
1177
+ def test_dependent_association_respects_optional_conditions_on_delete
1178
+ firm = companies(:odegy)
1179
+ Client.create(:client_of => firm.id, :name => "BigShot Inc.")
1180
+ Client.create(:client_of => firm.id, :name => "SmallTime Inc.")
1181
+ # only one of two clients is included in the association due to the :conditions key
1182
+ assert_equal 2, Client.where(client_of: firm.id).size
1183
+ assert_equal 1, firm.dependent_conditional_clients_of_firm.size
1184
+ firm.destroy
1185
+ # only the correctly associated client should have been deleted
1186
+ assert_equal 1, Client.where(client_of: firm.id).size
1187
+ end
1188
+
1189
+ def test_dependent_association_respects_optional_sanitized_conditions_on_delete
1190
+ firm = companies(:odegy)
1191
+ Client.create(:client_of => firm.id, :name => "BigShot Inc.")
1192
+ Client.create(:client_of => firm.id, :name => "SmallTime Inc.")
1193
+ # only one of two clients is included in the association due to the :conditions key
1194
+ assert_equal 2, Client.where(client_of: firm.id).size
1195
+ assert_equal 1, firm.dependent_sanitized_conditional_clients_of_firm.size
1196
+ firm.destroy
1197
+ # only the correctly associated client should have been deleted
1198
+ assert_equal 1, Client.where(client_of: firm.id).size
1199
+ end
1200
+
1201
+ def test_dependent_association_respects_optional_hash_conditions_on_delete
1202
+ firm = companies(:odegy)
1203
+ Client.create(:client_of => firm.id, :name => "BigShot Inc.")
1204
+ Client.create(:client_of => firm.id, :name => "SmallTime Inc.")
1205
+ # only one of two clients is included in the association due to the :conditions key
1206
+ assert_equal 2, Client.where(client_of: firm.id).size
1207
+ assert_equal 1, firm.dependent_sanitized_conditional_clients_of_firm.size
1208
+ firm.destroy
1209
+ # only the correctly associated client should have been deleted
1210
+ assert_equal 1, Client.where(client_of: firm.id).size
1211
+ end
1212
+
1213
+ def test_delete_all_association_with_primary_key_deletes_correct_records
1214
+ firm = Firm.first
1215
+ # break the vanilla firm_id foreign key
1216
+ assert_equal 3, firm.clients.count
1217
+ firm.clients.first.update_columns(firm_id: nil)
1218
+ assert_equal 2, firm.clients(true).count
1219
+ assert_equal 2, firm.clients_using_primary_key_with_delete_all.count
1220
+ old_record = firm.clients_using_primary_key_with_delete_all.first
1221
+ firm = Firm.first
1222
+ firm.destroy
1223
+ assert_nil Client.find_by_id(old_record.id)
1224
+ end
1225
+
1226
+ def test_creation_respects_hash_condition
1227
+ ms_client = companies(:first_firm).clients_like_ms_with_hash_conditions.build
1228
+
1229
+ assert ms_client.save
1230
+ assert_equal 'Microsoft', ms_client.name
1231
+
1232
+ another_ms_client = companies(:first_firm).clients_like_ms_with_hash_conditions.create
1233
+
1234
+ assert another_ms_client.persisted?
1235
+ assert_equal 'Microsoft', another_ms_client.name
1236
+ end
1237
+
1238
+ def test_clearing_without_initial_access
1239
+ firm = companies(:first_firm)
1240
+
1241
+ firm.clients_of_firm.clear
1242
+
1243
+ assert_equal 0, firm.clients_of_firm.size
1244
+ assert_equal 0, firm.clients_of_firm(true).size
1245
+ end
1246
+
1247
+ def test_deleting_a_item_which_is_not_in_the_collection
1248
+ force_signal37_to_load_all_clients_of_firm
1249
+ summit = Client.find_by_name('Summit')
1250
+ companies(:first_firm).clients_of_firm.delete(summit)
1251
+ assert_equal 2, companies(:first_firm).clients_of_firm.size
1252
+ assert_equal 2, companies(:first_firm).clients_of_firm(true).size
1253
+ assert_equal 2, summit.client_of
1254
+ end
1255
+
1256
+ def test_deleting_by_fixnum_id
1257
+ david = Developer.find(1)
1258
+
1259
+ assert_difference 'david.projects.count', -1 do
1260
+ assert_equal 1, david.projects.delete(1).size
1261
+ end
1262
+
1263
+ assert_equal 1, david.projects.size
1264
+ end
1265
+
1266
+ def test_deleting_by_string_id
1267
+ david = Developer.find(1)
1268
+
1269
+ assert_difference 'david.projects.count', -1 do
1270
+ assert_equal 1, david.projects.delete('1').size
1271
+ end
1272
+
1273
+ assert_equal 1, david.projects.size
1274
+ end
1275
+
1276
+ def test_deleting_self_type_mismatch
1277
+ david = Developer.find(1)
1278
+ david.projects.reload
1279
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { david.projects.delete(Project.find(1).developers) }
1280
+ end
1281
+
1282
+ def test_destroying
1283
+ force_signal37_to_load_all_clients_of_firm
1284
+
1285
+ assert_difference "Client.count", -1 do
1286
+ companies(:first_firm).clients_of_firm.destroy(companies(:first_firm).clients_of_firm.first)
1287
+ end
1288
+
1289
+ assert_equal 1, companies(:first_firm).reload.clients_of_firm.size
1290
+ assert_equal 1, companies(:first_firm).clients_of_firm(true).size
1291
+ end
1292
+
1293
+ def test_destroying_by_fixnum_id
1294
+ force_signal37_to_load_all_clients_of_firm
1295
+
1296
+ assert_difference "Client.count", -1 do
1297
+ companies(:first_firm).clients_of_firm.destroy(companies(:first_firm).clients_of_firm.first.id)
1298
+ end
1299
+
1300
+ assert_equal 1, companies(:first_firm).reload.clients_of_firm.size
1301
+ assert_equal 1, companies(:first_firm).clients_of_firm(true).size
1302
+ end
1303
+
1304
+ def test_destroying_by_string_id
1305
+ force_signal37_to_load_all_clients_of_firm
1306
+
1307
+ assert_difference "Client.count", -1 do
1308
+ companies(:first_firm).clients_of_firm.destroy(companies(:first_firm).clients_of_firm.first.id.to_s)
1309
+ end
1310
+
1311
+ assert_equal 1, companies(:first_firm).reload.clients_of_firm.size
1312
+ assert_equal 1, companies(:first_firm).clients_of_firm(true).size
1313
+ end
1314
+
1315
+ def test_destroying_a_collection
1316
+ force_signal37_to_load_all_clients_of_firm
1317
+ companies(:first_firm).clients_of_firm.create("name" => "Another Client")
1318
+ assert_equal 3, companies(:first_firm).clients_of_firm.size
1319
+
1320
+ assert_difference "Client.count", -2 do
1321
+ companies(:first_firm).clients_of_firm.destroy([companies(:first_firm).clients_of_firm[0], companies(:first_firm).clients_of_firm[1]])
1322
+ end
1323
+
1324
+ assert_equal 1, companies(:first_firm).reload.clients_of_firm.size
1325
+ assert_equal 1, companies(:first_firm).clients_of_firm(true).size
1326
+ end
1327
+
1328
+ def test_destroy_all
1329
+ force_signal37_to_load_all_clients_of_firm
1330
+ clients = companies(:first_firm).clients_of_firm.to_a
1331
+ assert !clients.empty?, "37signals has clients after load"
1332
+ destroyed = companies(:first_firm).clients_of_firm.destroy_all
1333
+ assert_equal clients.sort_by(&:id), destroyed.sort_by(&:id)
1334
+ assert destroyed.all? { |client| client.frozen? }, "destroyed clients should be frozen"
1335
+ assert companies(:first_firm).clients_of_firm.empty?, "37signals has no clients after destroy all"
1336
+ assert companies(:first_firm).clients_of_firm(true).empty?, "37signals has no clients after destroy all and refresh"
1337
+ end
1338
+
1339
+ def test_dependence
1340
+ firm = companies(:first_firm)
1341
+ assert_equal 3, firm.clients.size
1342
+ firm.destroy
1343
+ assert Client.all.merge!(:where => "firm_id=#{firm.id}").to_a.empty?
1344
+ end
1345
+
1346
+ def test_dependence_for_associations_with_hash_condition
1347
+ david = authors(:david)
1348
+ assert_difference('Post.count', -1) { assert david.destroy }
1349
+ end
1350
+
1351
+ def test_destroy_dependent_when_deleted_from_association
1352
+ # sometimes tests on Oracle fail if ORDER BY is not provided therefore add always :order with :first
1353
+ firm = Firm.all.merge!(:order => "id").first
1354
+ assert_equal 3, firm.clients.size
1355
+
1356
+ client = firm.clients.first
1357
+ firm.clients.delete(client)
1358
+
1359
+ assert_raise(ActiveRecord::RecordNotFound) { Client.find(client.id) }
1360
+ assert_raise(ActiveRecord::RecordNotFound) { firm.clients.find(client.id) }
1361
+ assert_equal 2, firm.clients.size
1362
+ end
1363
+
1364
+ def test_three_levels_of_dependence
1365
+ topic = Topic.create "title" => "neat and simple"
1366
+ reply = topic.replies.create "title" => "neat and simple", "content" => "still digging it"
1367
+ reply.replies.create "title" => "neat and simple", "content" => "ain't complaining"
1368
+
1369
+ assert_nothing_raised { topic.destroy }
1370
+ end
1371
+
1372
+ uses_transaction :test_dependence_with_transaction_support_on_failure
1373
+ def test_dependence_with_transaction_support_on_failure
1374
+ firm = companies(:first_firm)
1375
+ clients = firm.clients
1376
+ assert_equal 3, clients.length
1377
+ clients.last.instance_eval { def overwrite_to_raise() raise "Trigger rollback" end }
1378
+
1379
+ firm.destroy rescue "do nothing"
1380
+
1381
+ assert_equal 3, Client.all.merge!(:where => "firm_id=#{firm.id}").to_a.size
1382
+ end
1383
+
1384
+ def test_dependence_on_account
1385
+ num_accounts = Account.count
1386
+ companies(:first_firm).destroy
1387
+ assert_equal num_accounts - 1, Account.count
1388
+ end
1389
+
1390
+ def test_depends_and_nullify
1391
+ num_accounts = Account.count
1392
+
1393
+ core = companies(:rails_core)
1394
+ assert_equal accounts(:rails_core_account), core.account
1395
+ assert_equal companies(:leetsoft, :jadedpixel), core.companies
1396
+ core.destroy
1397
+ assert_nil accounts(:rails_core_account).reload.firm_id
1398
+ assert_nil companies(:leetsoft).reload.client_of
1399
+ assert_nil companies(:jadedpixel).reload.client_of
1400
+
1401
+ assert_equal num_accounts, Account.count
1402
+ end
1403
+
1404
+ def test_restrict_with_exception
1405
+ firm = RestrictedWithExceptionFirm.create!(:name => 'restrict')
1406
+ firm.companies.create(:name => 'child')
1407
+
1408
+ assert !firm.companies.empty?
1409
+ assert_raise(ActiveRecord::DeleteRestrictionError) { firm.destroy }
1410
+ assert RestrictedWithExceptionFirm.exists?(:name => 'restrict')
1411
+ assert firm.companies.exists?(:name => 'child')
1412
+ end
1413
+
1414
+ def test_restrict_with_error
1415
+ firm = RestrictedWithErrorFirm.create!(:name => 'restrict')
1416
+ firm.companies.create(:name => 'child')
1417
+
1418
+ assert !firm.companies.empty?
1419
+
1420
+ firm.destroy
1421
+
1422
+ assert !firm.errors.empty?
1423
+
1424
+ assert_equal "Cannot delete record because dependent companies exist", firm.errors[:base].first
1425
+ assert RestrictedWithErrorFirm.exists?(:name => 'restrict')
1426
+ assert firm.companies.exists?(:name => 'child')
1427
+ end
1428
+
1429
+ def test_included_in_collection
1430
+ assert_equal true, companies(:first_firm).clients.include?(Client.find(2))
1431
+ end
1432
+
1433
+ def test_included_in_collection_for_new_records
1434
+ client = Client.create(:name => 'Persisted')
1435
+ assert_nil client.client_of
1436
+ assert_equal false, Firm.new.clients_of_firm.include?(client),
1437
+ 'includes a client that does not belong to any firm'
1438
+ end
1439
+
1440
+ def test_adding_array_and_collection
1441
+ assert_nothing_raised { Firm.first.clients + Firm.all.last.clients }
1442
+ end
1443
+
1444
+ def test_replace_with_less
1445
+ firm = Firm.all.merge!(:order => "id").first
1446
+ firm.clients = [companies(:first_client)]
1447
+ assert firm.save, "Could not save firm"
1448
+ firm.reload
1449
+ assert_equal 1, firm.clients.length
1450
+ end
1451
+
1452
+ def test_replace_with_less_and_dependent_nullify
1453
+ num_companies = Company.count
1454
+ companies(:rails_core).companies = []
1455
+ assert_equal num_companies, Company.count
1456
+ end
1457
+
1458
+ def test_replace_with_new
1459
+ firm = Firm.all.merge!(:order => "id").first
1460
+ firm.clients = [companies(:second_client), Client.new("name" => "New Client")]
1461
+ firm.save
1462
+ firm.reload
1463
+ assert_equal 2, firm.clients.length
1464
+ assert_equal false, firm.clients.include?(:first_client)
1465
+ end
1466
+
1467
+ def test_replace_failure
1468
+ firm = companies(:first_firm)
1469
+ account = Account.new
1470
+ orig_accounts = firm.accounts.to_a
1471
+
1472
+ assert !account.valid?
1473
+ assert !orig_accounts.empty?
1474
+ error = assert_raise ActiveRecord::RecordNotSaved do
1475
+ firm.accounts = [account]
1476
+ end
1477
+
1478
+ assert_equal orig_accounts, firm.accounts
1479
+ assert_equal "Failed to replace accounts because one or more of the " \
1480
+ "new records could not be saved.", error.message
1481
+ end
1482
+
1483
+ def test_replace_with_same_content
1484
+ firm = Firm.first
1485
+ firm.clients = []
1486
+ firm.save
1487
+
1488
+ assert_queries(0, ignore_none: true) do
1489
+ firm.clients = []
1490
+ end
1491
+ end
1492
+
1493
+ def test_transactions_when_replacing_on_persisted
1494
+ good = Client.new(:name => "Good")
1495
+ bad = Client.new(:name => "Bad", :raise_on_save => true)
1496
+
1497
+ companies(:first_firm).clients_of_firm = [good]
1498
+
1499
+ begin
1500
+ companies(:first_firm).clients_of_firm = [bad]
1501
+ rescue Client::RaisedOnSave
1502
+ end
1503
+
1504
+ assert_equal [good], companies(:first_firm).clients_of_firm(true)
1505
+ end
1506
+
1507
+ def test_transactions_when_replacing_on_new_record
1508
+ assert_no_queries(ignore_none: false) do
1509
+ firm = Firm.new
1510
+ firm.clients_of_firm = [Client.new("name" => "New Client")]
1511
+ end
1512
+ end
1513
+
1514
+ def test_get_ids
1515
+ assert_equal [companies(:first_client).id, companies(:second_client).id, companies(:another_first_firm_client).id], companies(:first_firm).client_ids
1516
+ end
1517
+
1518
+ def test_get_ids_for_loaded_associations
1519
+ company = companies(:first_firm)
1520
+ company.clients(true)
1521
+ assert_queries(0) do
1522
+ company.client_ids
1523
+ company.client_ids
1524
+ end
1525
+ end
1526
+
1527
+ def test_get_ids_for_unloaded_associations_does_not_load_them
1528
+ company = companies(:first_firm)
1529
+ assert !company.clients.loaded?
1530
+ assert_equal [companies(:first_client).id, companies(:second_client).id, companies(:another_first_firm_client).id], company.client_ids
1531
+ assert !company.clients.loaded?
1532
+ end
1533
+
1534
+ def test_get_ids_ignores_include_option
1535
+ assert_equal [readers(:michael_welcome).id], posts(:welcome).readers_with_person_ids
1536
+ end
1537
+
1538
+ def test_get_ids_for_ordered_association
1539
+ assert_equal [companies(:another_first_firm_client).id, companies(:second_client).id, companies(:first_client).id], companies(:first_firm).clients_ordered_by_name_ids
1540
+ end
1541
+
1542
+ def test_get_ids_for_association_on_new_record_does_not_try_to_find_records
1543
+ Company.columns # Load schema information so we don't query below
1544
+ Contract.columns # if running just this test.
1545
+
1546
+ company = Company.new
1547
+ assert_queries(0) do
1548
+ company.contract_ids
1549
+ end
1550
+
1551
+ assert_equal [], company.contract_ids
1552
+ end
1553
+
1554
+ def test_set_ids_for_association_on_new_record_applies_association_correctly
1555
+ contract_a = Contract.create!
1556
+ contract_b = Contract.create!
1557
+ Contract.create! # another contract
1558
+ company = Company.new(:name => "Some Company")
1559
+
1560
+ company.contract_ids = [contract_a.id, contract_b.id]
1561
+ assert_equal [contract_a.id, contract_b.id], company.contract_ids
1562
+ assert_equal [contract_a, contract_b], company.contracts
1563
+
1564
+ company.save!
1565
+ assert_equal company, contract_a.reload.company
1566
+ assert_equal company, contract_b.reload.company
1567
+ end
1568
+
1569
+ def test_assign_ids_ignoring_blanks
1570
+ firm = Firm.create!(:name => 'Apple')
1571
+ firm.client_ids = [companies(:first_client).id, nil, companies(:second_client).id, '']
1572
+ firm.save!
1573
+
1574
+ assert_equal 2, firm.clients(true).size
1575
+ assert_equal true, firm.clients.include?(companies(:second_client))
1576
+ end
1577
+
1578
+ def test_get_ids_for_through
1579
+ assert_equal [comments(:eager_other_comment1).id], authors(:mary).comment_ids
1580
+ end
1581
+
1582
+ def test_modifying_a_through_a_has_many_should_raise
1583
+ [
1584
+ lambda { authors(:mary).comment_ids = [comments(:greetings).id, comments(:more_greetings).id] },
1585
+ lambda { authors(:mary).comments = [comments(:greetings), comments(:more_greetings)] },
1586
+ lambda { authors(:mary).comments << Comment.create!(:body => "Yay", :post_id => 424242) },
1587
+ lambda { authors(:mary).comments.delete(authors(:mary).comments.first) },
1588
+ ].each {|block| assert_raise(ActiveRecord::HasManyThroughCantAssociateThroughHasOneOrManyReflection, &block) }
1589
+ end
1590
+
1591
+ def test_dynamic_find_should_respect_association_order_for_through
1592
+ assert_equal Comment.find(10), authors(:david).comments_desc.where("comments.type = 'SpecialComment'").first
1593
+ assert_equal Comment.find(10), authors(:david).comments_desc.find_by_type('SpecialComment')
1594
+ end
1595
+
1596
+ def test_has_many_through_respects_hash_conditions
1597
+ assert_equal authors(:david).hello_posts, authors(:david).hello_posts_with_hash_conditions
1598
+ assert_equal authors(:david).hello_post_comments, authors(:david).hello_post_comments_with_hash_conditions
1599
+ end
1600
+
1601
+ def test_include_uses_array_include_after_loaded
1602
+ firm = companies(:first_firm)
1603
+ firm.clients.load_target
1604
+
1605
+ client = firm.clients.first
1606
+
1607
+ assert_no_queries do
1608
+ assert firm.clients.loaded?
1609
+ assert_equal true, firm.clients.include?(client)
1610
+ end
1611
+ end
1612
+
1613
+ def test_include_checks_if_record_exists_if_target_not_loaded
1614
+ firm = companies(:first_firm)
1615
+ client = firm.clients.first
1616
+
1617
+ firm.reload
1618
+ assert ! firm.clients.loaded?
1619
+ assert_queries(1) do
1620
+ assert_equal true, firm.clients.include?(client)
1621
+ end
1622
+ assert ! firm.clients.loaded?
1623
+ end
1624
+
1625
+ def test_include_returns_false_for_non_matching_record_to_verify_scoping
1626
+ firm = companies(:first_firm)
1627
+ client = Client.create!(:name => 'Not Associated')
1628
+
1629
+ assert ! firm.clients.loaded?
1630
+ assert_equal false, firm.clients.include?(client)
1631
+ end
1632
+
1633
+ def test_calling_first_nth_or_last_on_association_should_not_load_association
1634
+ firm = companies(:first_firm)
1635
+ firm.clients.first
1636
+ firm.clients.second
1637
+ firm.clients.last
1638
+ assert !firm.clients.loaded?
1639
+ end
1640
+
1641
+ def test_calling_first_or_last_on_loaded_association_should_not_fetch_with_query
1642
+ firm = companies(:first_firm)
1643
+ firm.clients.load_target
1644
+ assert firm.clients.loaded?
1645
+
1646
+ assert_no_queries(ignore_none: false) do
1647
+ firm.clients.first
1648
+ assert_equal 2, firm.clients.first(2).size
1649
+ firm.clients.last
1650
+ assert_equal 2, firm.clients.last(2).size
1651
+ end
1652
+ end
1653
+
1654
+ def test_calling_first_or_last_on_existing_record_with_build_should_load_association
1655
+ firm = companies(:first_firm)
1656
+ firm.clients.build(:name => 'Foo')
1657
+ assert !firm.clients.loaded?
1658
+
1659
+ assert_queries 1 do
1660
+ firm.clients.first
1661
+ firm.clients.second
1662
+ firm.clients.last
1663
+ end
1664
+
1665
+ assert firm.clients.loaded?
1666
+ end
1667
+
1668
+ def test_calling_first_nth_or_last_on_existing_record_with_create_should_not_load_association
1669
+ firm = companies(:first_firm)
1670
+ firm.clients.create(:name => 'Foo')
1671
+ assert !firm.clients.loaded?
1672
+
1673
+ assert_queries 3 do
1674
+ firm.clients.first
1675
+ firm.clients.second
1676
+ firm.clients.last
1677
+ end
1678
+
1679
+ assert !firm.clients.loaded?
1680
+ end
1681
+
1682
+ def test_calling_first_nth_or_last_on_new_record_should_not_run_queries
1683
+ firm = Firm.new
1684
+
1685
+ assert_no_queries do
1686
+ firm.clients.first
1687
+ firm.clients.second
1688
+ firm.clients.last
1689
+ end
1690
+ end
1691
+
1692
+ def test_calling_first_or_last_with_integer_on_association_should_not_load_association
1693
+ firm = companies(:first_firm)
1694
+ firm.clients.create(:name => 'Foo')
1695
+ assert !firm.clients.loaded?
1696
+
1697
+ assert_queries 2 do
1698
+ firm.clients.first(2)
1699
+ firm.clients.last(2)
1700
+ end
1701
+
1702
+ assert !firm.clients.loaded?
1703
+ end
1704
+
1705
+ def test_calling_many_should_count_instead_of_loading_association
1706
+ firm = companies(:first_firm)
1707
+ assert_queries(1) do
1708
+ firm.clients.many? # use count query
1709
+ end
1710
+ assert !firm.clients.loaded?
1711
+ end
1712
+
1713
+ def test_calling_many_on_loaded_association_should_not_use_query
1714
+ firm = companies(:first_firm)
1715
+ firm.clients.collect # force load
1716
+ assert_no_queries { assert firm.clients.many? }
1717
+ end
1718
+
1719
+ def test_calling_many_should_defer_to_collection_if_using_a_block
1720
+ firm = companies(:first_firm)
1721
+ assert_queries(1) do
1722
+ firm.clients.expects(:size).never
1723
+ firm.clients.many? { true }
1724
+ end
1725
+ assert firm.clients.loaded?
1726
+ end
1727
+
1728
+ def test_calling_many_should_return_false_if_none_or_one
1729
+ firm = companies(:another_firm)
1730
+ assert !firm.clients_like_ms.many?
1731
+ assert_equal 0, firm.clients_like_ms.size
1732
+
1733
+ firm = companies(:first_firm)
1734
+ assert !firm.limited_clients.many?
1735
+ assert_equal 1, firm.limited_clients.size
1736
+ end
1737
+
1738
+ def test_calling_many_should_return_true_if_more_than_one
1739
+ firm = companies(:first_firm)
1740
+ assert firm.clients.many?
1741
+ assert_equal 3, firm.clients.size
1742
+ end
1743
+
1744
+ def test_joins_with_namespaced_model_should_use_correct_type
1745
+ old = ActiveRecord::Base.store_full_sti_class
1746
+ ActiveRecord::Base.store_full_sti_class = true
1747
+
1748
+ firm = Namespaced::Firm.create({ :name => 'Some Company' })
1749
+ firm.clients.create({ :name => 'Some Client' })
1750
+
1751
+ stats = Namespaced::Firm.all.merge!(
1752
+ :select => "#{Namespaced::Firm.table_name}.id, COUNT(#{Namespaced::Client.table_name}.id) AS num_clients",
1753
+ :joins => :clients,
1754
+ :group => "#{Namespaced::Firm.table_name}.id"
1755
+ ).find firm.id
1756
+ assert_equal 1, stats.num_clients.to_i
1757
+ ensure
1758
+ ActiveRecord::Base.store_full_sti_class = old
1759
+ end
1760
+
1761
+ def test_association_proxy_transaction_method_starts_transaction_in_association_class
1762
+ Comment.expects(:transaction)
1763
+ Post.first.comments.transaction do
1764
+ # nothing
1765
+ end
1766
+ end
1767
+
1768
+ def test_sending_new_to_association_proxy_should_have_same_effect_as_calling_new
1769
+ client_association = companies(:first_firm).clients
1770
+ assert_equal client_association.new.attributes, client_association.send(:new).attributes
1771
+ end
1772
+
1773
+ def test_respond_to_private_class_methods
1774
+ client_association = companies(:first_firm).clients
1775
+ assert !client_association.respond_to?(:private_method)
1776
+ assert client_association.respond_to?(:private_method, true)
1777
+ end
1778
+
1779
+ def test_creating_using_primary_key
1780
+ firm = Firm.all.merge!(:order => "id").first
1781
+ client = firm.clients_using_primary_key.create!(:name => 'test')
1782
+ assert_equal firm.name, client.firm_name
1783
+ end
1784
+
1785
+ def test_defining_has_many_association_with_delete_all_dependency_lazily_evaluates_target_class
1786
+ ActiveRecord::Reflection::AssociationReflection.any_instance.expects(:class_name).never
1787
+ class_eval(<<-EOF, __FILE__, __LINE__ + 1)
1788
+ class DeleteAllModel < ActiveRecord::Base
1789
+ has_many :nonentities, :dependent => :delete_all
1790
+ end
1791
+ EOF
1792
+ end
1793
+
1794
+ def test_defining_has_many_association_with_nullify_dependency_lazily_evaluates_target_class
1795
+ ActiveRecord::Reflection::AssociationReflection.any_instance.expects(:class_name).never
1796
+ class_eval(<<-EOF, __FILE__, __LINE__ + 1)
1797
+ class NullifyModel < ActiveRecord::Base
1798
+ has_many :nonentities, :dependent => :nullify
1799
+ end
1800
+ EOF
1801
+ end
1802
+
1803
+ def test_attributes_are_being_set_when_initialized_from_has_many_association_with_where_clause
1804
+ new_comment = posts(:welcome).comments.where(:body => "Some content").build
1805
+ assert_equal new_comment.body, "Some content"
1806
+ end
1807
+
1808
+ def test_attributes_are_being_set_when_initialized_from_has_many_association_with_multiple_where_clauses
1809
+ new_comment = posts(:welcome).comments.where(:body => "Some content").where(:type => 'SpecialComment').build
1810
+ assert_equal new_comment.body, "Some content"
1811
+ assert_equal new_comment.type, "SpecialComment"
1812
+ assert_equal new_comment.post_id, posts(:welcome).id
1813
+ end
1814
+
1815
+ def test_include_method_in_has_many_association_should_return_true_for_instance_added_with_build
1816
+ post = Post.new
1817
+ comment = post.comments.build
1818
+ assert_equal true, post.comments.include?(comment)
1819
+ end
1820
+
1821
+ def test_load_target_respects_protected_attributes
1822
+ topic = Topic.create!
1823
+ reply = topic.replies.create(:title => "reply 1")
1824
+ reply.approved = false
1825
+ reply.save!
1826
+
1827
+ # Save with a different object instance, so the instance that's still held
1828
+ # in topic.relies doesn't know about the changed attribute.
1829
+ reply2 = Reply.find(reply.id)
1830
+ reply2.approved = true
1831
+ reply2.save!
1832
+
1833
+ # Force loading the collection from the db. This will merge the existing
1834
+ # object (reply) with what gets loaded from the db (which includes the
1835
+ # changed approved attribute). approved is a protected attribute, so if mass
1836
+ # assignment is used, it won't get updated and will still be false.
1837
+ first = topic.replies.to_a.first
1838
+ assert_equal reply.id, first.id
1839
+ assert_equal true, first.approved?
1840
+ end
1841
+
1842
+ def test_to_a_should_dup_target
1843
+ ary = topics(:first).replies.to_a
1844
+ target = topics(:first).replies.target
1845
+
1846
+ assert_not_equal target.object_id, ary.object_id
1847
+ end
1848
+
1849
+ def test_merging_with_custom_attribute_writer
1850
+ bulb = Bulb.new(:color => "red")
1851
+ assert_equal "RED!", bulb.color
1852
+
1853
+ car = Car.create!
1854
+ car.bulbs << bulb
1855
+
1856
+ assert_equal "RED!", car.bulbs.to_a.first.color
1857
+ end
1858
+
1859
+ def test_abstract_class_with_polymorphic_has_many
1860
+ post = SubStiPost.create! :title => "fooo", :body => "baa"
1861
+ tagging = Tagging.create! :taggable => post
1862
+ assert_equal [tagging], post.taggings
1863
+ end
1864
+
1865
+ def test_with_polymorphic_has_many_with_custom_columns_name
1866
+ post = Post.create! :title => 'foo', :body => 'bar'
1867
+ image = Image.create!
1868
+
1869
+ post.images << image
1870
+
1871
+ assert_equal [image], post.images
1872
+ end
1873
+
1874
+ def test_build_with_polymorphic_has_many_does_not_allow_to_override_type_and_id
1875
+ welcome = posts(:welcome)
1876
+ tagging = welcome.taggings.build(:taggable_id => 99, :taggable_type => 'ShouldNotChange')
1877
+
1878
+ assert_equal welcome.id, tagging.taggable_id
1879
+ assert_equal 'Post', tagging.taggable_type
1880
+ end
1881
+
1882
+ def test_dont_call_save_callbacks_twice_on_has_many
1883
+ firm = companies(:first_firm)
1884
+ contract = firm.contracts.create!
1885
+
1886
+ assert_equal 1, contract.hi_count
1887
+ assert_equal 1, contract.bye_count
1888
+ end
1889
+
1890
+ def test_association_attributes_are_available_to_after_initialize
1891
+ car = Car.create(:name => 'honda')
1892
+ bulb = car.bulbs.build
1893
+
1894
+ assert_equal car.id, bulb.attributes_after_initialize['car_id']
1895
+ end
1896
+
1897
+ def test_attributes_are_set_when_initialized_from_has_many_null_relationship
1898
+ car = Car.new name: 'honda'
1899
+ bulb = car.bulbs.where(name: 'headlight').first_or_initialize
1900
+ assert_equal 'headlight', bulb.name
1901
+ end
1902
+
1903
+ def test_attributes_are_set_when_initialized_from_polymorphic_has_many_null_relationship
1904
+ post = Post.new title: 'title', body: 'bar'
1905
+ tag = Tag.create!(name: 'foo')
1906
+
1907
+ tagging = post.taggings.where(tag: tag).first_or_initialize
1908
+
1909
+ assert_equal tag.id, tagging.tag_id
1910
+ assert_equal 'Post', tagging.taggable_type
1911
+ end
1912
+
1913
+ def test_replace
1914
+ car = Car.create(:name => 'honda')
1915
+ bulb1 = car.bulbs.create
1916
+ bulb2 = Bulb.create
1917
+
1918
+ assert_equal [bulb1], car.bulbs
1919
+ car.bulbs.replace([bulb2])
1920
+ assert_equal [bulb2], car.bulbs
1921
+ assert_equal [bulb2], car.reload.bulbs
1922
+ end
1923
+
1924
+ def test_replace_returns_target
1925
+ car = Car.create(:name => 'honda')
1926
+ bulb1 = car.bulbs.create
1927
+ bulb2 = car.bulbs.create
1928
+ bulb3 = Bulb.create
1929
+
1930
+ assert_equal [bulb1, bulb2], car.bulbs
1931
+ result = car.bulbs.replace([bulb3, bulb1])
1932
+ assert_equal [bulb1, bulb3], car.bulbs
1933
+ assert_equal [bulb1, bulb3], result
1934
+ end
1935
+
1936
+ def test_collection_association_with_private_kernel_method
1937
+ firm = companies(:first_firm)
1938
+ assert_equal [accounts(:signals37)], firm.accounts.open
1939
+ end
1940
+
1941
+ test "first_or_initialize adds the record to the association" do
1942
+ firm = Firm.create! name: 'omg'
1943
+ client = firm.clients_of_firm.first_or_initialize
1944
+ assert_equal [client], firm.clients_of_firm
1945
+ end
1946
+
1947
+ test "first_or_create adds the record to the association" do
1948
+ firm = Firm.create! name: 'omg'
1949
+ firm.clients_of_firm.load_target
1950
+ client = firm.clients_of_firm.first_or_create name: 'lol'
1951
+ assert_equal [client], firm.clients_of_firm
1952
+ assert_equal [client], firm.reload.clients_of_firm
1953
+ end
1954
+
1955
+ test "delete_all, when not loaded, doesn't load the records" do
1956
+ post = posts(:welcome)
1957
+
1958
+ assert post.taggings_with_delete_all.count > 0
1959
+ assert !post.taggings_with_delete_all.loaded?
1960
+
1961
+ # 2 queries: one DELETE and another to update the counter cache
1962
+ assert_queries(2) do
1963
+ post.taggings_with_delete_all.delete_all
1964
+ end
1965
+ end
1966
+
1967
+ test "has many associations on new records use null relations" do
1968
+ post = Post.new
1969
+
1970
+ assert_no_queries(ignore_none: false) do
1971
+ assert_equal [], post.comments
1972
+ assert_equal [], post.comments.where(body: 'omg')
1973
+ assert_equal [], post.comments.pluck(:body)
1974
+ assert_equal 0, post.comments.sum(:id)
1975
+ assert_equal 0, post.comments.count
1976
+ end
1977
+ end
1978
+
1979
+ test "collection proxy respects default scope" do
1980
+ author = authors(:mary)
1981
+ assert !author.first_posts.exists?
1982
+ end
1983
+
1984
+ test "association with extend option" do
1985
+ post = posts(:welcome)
1986
+ assert_equal "lifo", post.comments_with_extend.author
1987
+ assert_equal "hello", post.comments_with_extend.greeting
1988
+ end
1989
+
1990
+ test "association with extend option with multiple extensions" do
1991
+ post = posts(:welcome)
1992
+ assert_equal "lifo", post.comments_with_extend_2.author
1993
+ assert_equal "hello", post.comments_with_extend_2.greeting
1994
+ end
1995
+
1996
+ test "delete record with complex joins" do
1997
+ david = authors(:david)
1998
+
1999
+ post = david.posts.first
2000
+ post.type = 'PostWithSpecialCategorization'
2001
+ post.save
2002
+
2003
+ categorization = post.categorizations.first
2004
+ categorization.special = true
2005
+ categorization.save
2006
+
2007
+ assert_not_equal [], david.posts_with_special_categorizations
2008
+ david.posts_with_special_categorizations = []
2009
+ assert_equal [], david.posts_with_special_categorizations
2010
+ end
2011
+
2012
+ test "does not duplicate associations when used with natural primary keys" do
2013
+ speedometer = Speedometer.create!(id: '4')
2014
+ speedometer.minivans.create!(minivan_id: 'a-van-red' ,name: 'a van', color: 'red')
2015
+
2016
+ assert_equal 1, speedometer.minivans.to_a.size, "Only one association should be present:\n#{speedometer.minivans.to_a}"
2017
+ assert_equal 1, speedometer.reload.minivans.to_a.size
2018
+ end
2019
+
2020
+ test "can unscope the default scope of the associated model" do
2021
+ car = Car.create!
2022
+ bulb1 = Bulb.create! name: "defaulty", car: car
2023
+ bulb2 = Bulb.create! name: "other", car: car
2024
+
2025
+ assert_equal [bulb1], car.bulbs
2026
+ assert_equal [bulb1, bulb2], car.all_bulbs.sort_by(&:id)
2027
+ end
2028
+
2029
+ test "can unscope and where the default scope of the associated model" do
2030
+ Car.has_many :other_bulbs, -> { unscope(where: [:name]).where(name: 'other') }, class_name: "Bulb"
2031
+ car = Car.create!
2032
+ bulb1 = Bulb.create! name: "defaulty", car: car
2033
+ bulb2 = Bulb.create! name: "other", car: car
2034
+
2035
+ assert_equal [bulb1], car.bulbs
2036
+ assert_equal [bulb2], car.other_bulbs
2037
+ end
2038
+
2039
+ test "can rewhere the default scope of the associated model" do
2040
+ Car.has_many :old_bulbs, -> { rewhere(name: 'old') }, class_name: "Bulb"
2041
+ car = Car.create!
2042
+ bulb1 = Bulb.create! name: "defaulty", car: car
2043
+ bulb2 = Bulb.create! name: "old", car: car
2044
+
2045
+ assert_equal [bulb1], car.bulbs
2046
+ assert_equal [bulb2], car.old_bulbs
2047
+ end
2048
+
2049
+ test 'unscopes the default scope of associated model when used with include' do
2050
+ car = Car.create!
2051
+ bulb = Bulb.create! name: "other", car: car
2052
+
2053
+ assert_equal bulb, Car.find(car.id).all_bulbs.first
2054
+ assert_equal bulb, Car.includes(:all_bulbs).find(car.id).all_bulbs.first
2055
+ end
2056
+
2057
+ test "raises RecordNotDestroyed when replaced child can't be destroyed" do
2058
+ car = Car.create!
2059
+ original_child = FailedBulb.create!(car: car)
2060
+
2061
+ error = assert_raise(ActiveRecord::RecordNotDestroyed) do
2062
+ car.failed_bulbs = [FailedBulb.create!]
2063
+ end
2064
+
2065
+ assert_equal [original_child], car.reload.failed_bulbs
2066
+ assert_equal "Failed to destroy the record", error.message
2067
+ end
2068
+
2069
+ test 'updates counter cache when default scope is given' do
2070
+ topic = DefaultRejectedTopic.create approved: true
2071
+
2072
+ assert_difference "topic.reload.replies_count", 1 do
2073
+ topic.approved_replies.create!
2074
+ end
2075
+ end
2076
+
2077
+ test 'dangerous association name raises ArgumentError' do
2078
+ [:errors, 'errors', :save, 'save'].each do |name|
2079
+ assert_raises(ArgumentError, "Association #{name} should not be allowed") do
2080
+ Class.new(ActiveRecord::Base) do
2081
+ has_many name
2082
+ end
2083
+ end
2084
+ end
2085
+ end
2086
+
2087
+ test 'passes custom context validation to validate children' do
2088
+ pirate = FamousPirate.new
2089
+ pirate.famous_ships << ship = FamousShip.new
2090
+
2091
+ assert pirate.valid?
2092
+ assert_not pirate.valid?(:conference)
2093
+ assert_equal "can't be blank", ship.errors[:name].first
2094
+ end
2095
+
2096
+ test 'association with instance dependent scope' do
2097
+ bob = authors(:bob)
2098
+ Post.create!(title: "signed post by bob", body: "stuff", author: authors(:bob))
2099
+ Post.create!(title: "anonymous post", body: "more stuff", author: authors(:bob))
2100
+ assert_equal ["misc post by bob", "other post by bob",
2101
+ "signed post by bob"], bob.posts_with_signature.map(&:title).sort
2102
+
2103
+ assert_equal [], authors(:david).posts_with_signature.map(&:title)
2104
+ end
2105
+
2106
+ test 'associations autosaves when object is already persited' do
2107
+ bulb = Bulb.create!
2108
+ tyre = Tyre.create!
2109
+
2110
+ car = Car.create! do |c|
2111
+ c.bulbs << bulb
2112
+ c.tyres << tyre
2113
+ end
2114
+
2115
+ assert_equal 1, car.bulbs.count
2116
+ assert_equal 1, car.tyres.count
2117
+ end
2118
+
2119
+ test 'associations replace in memory when records have the same id' do
2120
+ bulb = Bulb.create!
2121
+ car = Car.create!(bulbs: [bulb])
2122
+
2123
+ new_bulb = Bulb.find(bulb.id)
2124
+ new_bulb.name = "foo"
2125
+ car.bulbs = [new_bulb]
2126
+
2127
+ assert_equal "foo", car.bulbs.first.name
2128
+ end
2129
+
2130
+ test 'in memory replacement executes no queries' do
2131
+ bulb = Bulb.create!
2132
+ car = Car.create!(bulbs: [bulb])
2133
+
2134
+ new_bulb = Bulb.find(bulb.id)
2135
+
2136
+ assert_no_queries do
2137
+ car.bulbs = [new_bulb]
2138
+ end
2139
+ end
2140
+
2141
+ test 'in memory replacements do not execute callbacks' do
2142
+ raise_after_add = false
2143
+ klass = Class.new(ActiveRecord::Base) do
2144
+ self.table_name = :cars
2145
+ has_many :bulbs, after_add: proc { raise if raise_after_add }
2146
+
2147
+ def self.name
2148
+ "Car"
2149
+ end
2150
+ end
2151
+ bulb = Bulb.create!
2152
+ car = klass.create!(bulbs: [bulb])
2153
+
2154
+ new_bulb = Bulb.find(bulb.id)
2155
+ raise_after_add = true
2156
+
2157
+ assert_nothing_raised do
2158
+ car.bulbs = [new_bulb]
2159
+ end
2160
+ end
2161
+
2162
+ test 'in memory replacements sets inverse instance' do
2163
+ bulb = Bulb.create!
2164
+ car = Car.create!(bulbs: [bulb])
2165
+
2166
+ new_bulb = Bulb.find(bulb.id)
2167
+ car.bulbs = [new_bulb]
2168
+
2169
+ assert_same car, new_bulb.car
2170
+ end
2171
+
2172
+ test 'in memory replacement maintains order' do
2173
+ first_bulb = Bulb.create!
2174
+ second_bulb = Bulb.create!
2175
+ car = Car.create!(bulbs: [first_bulb, second_bulb])
2176
+
2177
+ same_bulb = Bulb.find(first_bulb.id)
2178
+ car.bulbs = [second_bulb, same_bulb]
2179
+
2180
+ assert_equal [first_bulb, second_bulb], car.bulbs
2181
+ end
2182
+ end