ibm_db 4.0.0-x86-mingw32 → 5.0.2-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 (570) hide show
  1. checksums.yaml +5 -5
  2. data/MANIFEST +14 -14
  3. data/README +208 -208
  4. data/ext/Makefile +269 -0
  5. data/ext/Makefile.nt32 +181 -181
  6. data/ext/Makefile.nt32.191 +212 -212
  7. data/ext/extconf.rb +322 -291
  8. data/ext/gil_release_version +3 -0
  9. data/ext/ibm_db.c +11879 -11887
  10. data/ext/mkmf.log +110 -0
  11. data/ext/ruby_ibm_db.h +241 -241
  12. data/ext/ruby_ibm_db_cli.c +866 -866
  13. data/ext/ruby_ibm_db_cli.h +500 -500
  14. data/ext/unicode_support_version +3 -0
  15. data/init.rb +41 -41
  16. data/lib/IBM_DB.rb +27 -27
  17. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +3533 -3452
  18. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +5 -5
  19. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
  20. data/lib/mswin32/ibm_db.rb +90 -90
  21. data/lib/mswin32/rb2x/i386/ibm_db.so +0 -0
  22. data/test/active_record/connection_adapters/fake_adapter.rb +49 -49
  23. data/test/assets/example.log +1 -1
  24. data/test/assets/test.txt +1 -1
  25. data/test/cases/adapter_test.rb +351 -351
  26. data/test/cases/adapters/mysql2/active_schema_test.rb +193 -193
  27. data/test/cases/adapters/mysql2/bind_parameter_test.rb +50 -50
  28. data/test/cases/adapters/mysql2/boolean_test.rb +100 -100
  29. data/test/cases/adapters/mysql2/case_sensitivity_test.rb +63 -63
  30. data/test/cases/adapters/mysql2/charset_collation_test.rb +54 -54
  31. data/test/cases/adapters/mysql2/connection_test.rb +210 -210
  32. data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +45 -45
  33. data/test/cases/adapters/mysql2/enum_test.rb +26 -26
  34. data/test/cases/adapters/mysql2/explain_test.rb +21 -21
  35. data/test/cases/adapters/mysql2/json_test.rb +195 -195
  36. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +83 -83
  37. data/test/cases/adapters/mysql2/reserved_word_test.rb +152 -152
  38. data/test/cases/adapters/mysql2/schema_migrations_test.rb +59 -59
  39. data/test/cases/adapters/mysql2/schema_test.rb +126 -126
  40. data/test/cases/adapters/mysql2/sp_test.rb +36 -36
  41. data/test/cases/adapters/mysql2/sql_types_test.rb +14 -14
  42. data/test/cases/adapters/mysql2/table_options_test.rb +42 -42
  43. data/test/cases/adapters/mysql2/unsigned_type_test.rb +66 -66
  44. data/test/cases/adapters/postgresql/active_schema_test.rb +98 -98
  45. data/test/cases/adapters/postgresql/array_test.rb +339 -339
  46. data/test/cases/adapters/postgresql/bit_string_test.rb +82 -82
  47. data/test/cases/adapters/postgresql/bytea_test.rb +134 -134
  48. data/test/cases/adapters/postgresql/case_insensitive_test.rb +26 -26
  49. data/test/cases/adapters/postgresql/change_schema_test.rb +38 -38
  50. data/test/cases/adapters/postgresql/cidr_test.rb +25 -25
  51. data/test/cases/adapters/postgresql/citext_test.rb +78 -78
  52. data/test/cases/adapters/postgresql/collation_test.rb +53 -53
  53. data/test/cases/adapters/postgresql/composite_test.rb +132 -132
  54. data/test/cases/adapters/postgresql/connection_test.rb +257 -257
  55. data/test/cases/adapters/postgresql/datatype_test.rb +92 -92
  56. data/test/cases/adapters/postgresql/domain_test.rb +47 -47
  57. data/test/cases/adapters/postgresql/enum_test.rb +91 -91
  58. data/test/cases/adapters/postgresql/explain_test.rb +20 -20
  59. data/test/cases/adapters/postgresql/extension_migration_test.rb +63 -63
  60. data/test/cases/adapters/postgresql/full_text_test.rb +44 -44
  61. data/test/cases/adapters/postgresql/geometric_test.rb +378 -378
  62. data/test/cases/adapters/postgresql/hstore_test.rb +382 -382
  63. data/test/cases/adapters/postgresql/infinity_test.rb +69 -69
  64. data/test/cases/adapters/postgresql/integer_test.rb +25 -25
  65. data/test/cases/adapters/postgresql/json_test.rb +237 -237
  66. data/test/cases/adapters/postgresql/ltree_test.rb +53 -53
  67. data/test/cases/adapters/postgresql/money_test.rb +96 -96
  68. data/test/cases/adapters/postgresql/network_test.rb +94 -94
  69. data/test/cases/adapters/postgresql/numbers_test.rb +49 -49
  70. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +405 -405
  71. data/test/cases/adapters/postgresql/prepared_statements_test.rb +22 -22
  72. data/test/cases/adapters/postgresql/quoting_test.rb +44 -44
  73. data/test/cases/adapters/postgresql/range_test.rb +343 -343
  74. data/test/cases/adapters/postgresql/referential_integrity_test.rb +111 -111
  75. data/test/cases/adapters/postgresql/rename_table_test.rb +34 -34
  76. data/test/cases/adapters/postgresql/schema_authorization_test.rb +119 -119
  77. data/test/cases/adapters/postgresql/schema_test.rb +597 -597
  78. data/test/cases/adapters/postgresql/serial_test.rb +154 -154
  79. data/test/cases/adapters/postgresql/statement_pool_test.rb +41 -41
  80. data/test/cases/adapters/postgresql/timestamp_test.rb +90 -90
  81. data/test/cases/adapters/postgresql/type_lookup_test.rb +33 -33
  82. data/test/cases/adapters/postgresql/utils_test.rb +62 -62
  83. data/test/cases/adapters/postgresql/uuid_test.rb +294 -294
  84. data/test/cases/adapters/postgresql/xml_test.rb +54 -54
  85. data/test/cases/adapters/sqlite3/collation_test.rb +53 -53
  86. data/test/cases/adapters/sqlite3/copy_table_test.rb +98 -98
  87. data/test/cases/adapters/sqlite3/explain_test.rb +21 -21
  88. data/test/cases/adapters/sqlite3/quoting_test.rb +101 -101
  89. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +441 -441
  90. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +24 -24
  91. data/test/cases/adapters/sqlite3/statement_pool_test.rb +20 -20
  92. data/test/cases/aggregations_test.rb +168 -168
  93. data/test/cases/ar_schema_test.rb +146 -146
  94. data/test/cases/associations/association_scope_test.rb +16 -16
  95. data/test/cases/associations/belongs_to_associations_test.rb +1141 -1141
  96. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +41 -41
  97. data/test/cases/associations/callbacks_test.rb +190 -190
  98. data/test/cases/associations/cascaded_eager_loading_test.rb +188 -188
  99. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -36
  100. data/test/cases/associations/eager_load_nested_include_test.rb +126 -126
  101. data/test/cases/associations/eager_singularization_test.rb +148 -148
  102. data/test/cases/associations/eager_test.rb +1514 -1514
  103. data/test/cases/associations/extension_test.rb +87 -87
  104. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +1004 -1004
  105. data/test/cases/associations/has_many_associations_test.rb +2501 -2501
  106. data/test/cases/associations/has_many_through_associations_test.rb +1271 -1271
  107. data/test/cases/associations/has_one_associations_test.rb +707 -707
  108. data/test/cases/associations/has_one_through_associations_test.rb +383 -383
  109. data/test/cases/associations/inner_join_association_test.rb +139 -139
  110. data/test/cases/associations/inverse_associations_test.rb +733 -733
  111. data/test/cases/associations/join_model_test.rb +777 -777
  112. data/test/cases/associations/left_outer_join_association_test.rb +88 -88
  113. data/test/cases/associations/nested_through_associations_test.rb +579 -579
  114. data/test/cases/associations/required_test.rb +102 -102
  115. data/test/cases/associations_test.rb +385 -385
  116. data/test/cases/attribute_decorators_test.rb +126 -125
  117. data/test/cases/attribute_methods/read_test.rb +60 -60
  118. data/test/cases/attribute_methods_test.rb +1009 -1009
  119. data/test/cases/attribute_set_test.rb +270 -270
  120. data/test/cases/attribute_test.rb +246 -246
  121. data/test/cases/attributes_test.rb +253 -253
  122. data/test/cases/autosave_association_test.rb +1708 -1708
  123. data/test/cases/base_test.rb +1713 -1713
  124. data/test/cases/batches_test.rb +489 -489
  125. data/test/cases/binary_test.rb +44 -44
  126. data/test/cases/bind_parameter_test.rb +110 -110
  127. data/test/cases/cache_key_test.rb +26 -25
  128. data/test/cases/calculations_test.rb +798 -798
  129. data/test/cases/callbacks_test.rb +636 -636
  130. data/test/cases/clone_test.rb +40 -40
  131. data/test/cases/coders/json_test.rb +15 -15
  132. data/test/cases/coders/yaml_column_test.rb +63 -63
  133. data/test/cases/collection_cache_key_test.rb +115 -115
  134. data/test/cases/column_alias_test.rb +17 -17
  135. data/test/cases/column_definition_test.rb +92 -92
  136. data/test/cases/comment_test.rb +145 -143
  137. data/test/cases/connection_adapters/adapter_leasing_test.rb +56 -56
  138. data/test/cases/connection_adapters/connection_handler_test.rb +160 -160
  139. data/test/cases/connection_adapters/connection_specification_test.rb +12 -12
  140. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +255 -255
  141. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +69 -69
  142. data/test/cases/connection_adapters/quoting_test.rb +13 -13
  143. data/test/cases/connection_adapters/schema_cache_test.rb +61 -61
  144. data/test/cases/connection_adapters/type_lookup_test.rb +118 -118
  145. data/test/cases/connection_management_test.rb +112 -112
  146. data/test/cases/connection_pool_test.rb +521 -521
  147. data/test/cases/connection_specification/resolver_test.rb +131 -131
  148. data/test/cases/core_test.rb +112 -112
  149. data/test/cases/counter_cache_test.rb +214 -214
  150. data/test/cases/custom_locking_test.rb +17 -17
  151. data/test/cases/database_statements_test.rb +34 -34
  152. data/test/cases/date_test.rb +44 -44
  153. data/test/cases/date_time_precision_test.rb +107 -106
  154. data/test/cases/date_time_test.rb +61 -61
  155. data/test/cases/defaults_test.rb +219 -218
  156. data/test/cases/dirty_test.rb +763 -763
  157. data/test/cases/disconnected_test.rb +30 -30
  158. data/test/cases/dup_test.rb +157 -157
  159. data/test/cases/enum_test.rb +444 -444
  160. data/test/cases/errors_test.rb +16 -16
  161. data/test/cases/explain_subscriber_test.rb +64 -64
  162. data/test/cases/explain_test.rb +87 -87
  163. data/test/cases/finder_respond_to_test.rb +60 -60
  164. data/test/cases/finder_test.rb +1294 -1294
  165. data/test/cases/fixture_set/file_test.rb +156 -156
  166. data/test/cases/fixtures_test.rb +988 -988
  167. data/test/cases/forbidden_attributes_protection_test.rb +165 -165
  168. data/test/cases/habtm_destroy_order_test.rb +61 -61
  169. data/test/cases/helper.rb +204 -204
  170. data/test/cases/hot_compatibility_test.rb +142 -142
  171. data/test/cases/i18n_test.rb +45 -45
  172. data/test/cases/inheritance_test.rb +606 -606
  173. data/test/cases/integration_test.rb +155 -155
  174. data/test/cases/invalid_connection_test.rb +24 -24
  175. data/test/cases/invertible_migration_test.rb +387 -387
  176. data/test/cases/json_serialization_test.rb +311 -311
  177. data/test/cases/locking_test.rb +493 -493
  178. data/test/cases/log_subscriber_test.rb +225 -225
  179. data/test/cases/migration/change_schema_test.rb +458 -458
  180. data/test/cases/migration/change_table_test.rb +256 -256
  181. data/test/cases/migration/column_attributes_test.rb +176 -176
  182. data/test/cases/migration/column_positioning_test.rb +56 -56
  183. data/test/cases/migration/columns_test.rb +310 -310
  184. data/test/cases/migration/command_recorder_test.rb +350 -350
  185. data/test/cases/migration/compatibility_test.rb +118 -118
  186. data/test/cases/migration/create_join_table_test.rb +157 -157
  187. data/test/cases/migration/foreign_key_test.rb +362 -360
  188. data/test/cases/migration/helper.rb +39 -39
  189. data/test/cases/migration/index_test.rb +218 -218
  190. data/test/cases/migration/logger_test.rb +36 -36
  191. data/test/cases/migration/pending_migrations_test.rb +52 -52
  192. data/test/cases/migration/references_foreign_key_test.rb +221 -216
  193. data/test/cases/migration/references_index_test.rb +101 -101
  194. data/test/cases/migration/references_statements_test.rb +136 -136
  195. data/test/cases/migration/rename_table_test.rb +93 -93
  196. data/test/cases/migration_test.rb +1157 -1157
  197. data/test/cases/migrator_test.rb +471 -470
  198. data/test/cases/mixin_test.rb +68 -68
  199. data/test/cases/modules_test.rb +172 -172
  200. data/test/cases/multiparameter_attributes_test.rb +372 -372
  201. data/test/cases/multiple_db_test.rb +122 -122
  202. data/test/cases/nested_attributes_test.rb +1098 -1098
  203. data/test/cases/nested_attributes_with_callbacks_test.rb +144 -144
  204. data/test/cases/persistence_test.rb +1001 -1001
  205. data/test/cases/pooled_connections_test.rb +81 -81
  206. data/test/cases/primary_keys_test.rb +376 -376
  207. data/test/cases/query_cache_test.rb +446 -446
  208. data/test/cases/quoting_test.rb +202 -202
  209. data/test/cases/readonly_test.rb +119 -119
  210. data/test/cases/reaper_test.rb +85 -85
  211. data/test/cases/reflection_test.rb +509 -509
  212. data/test/cases/relation/delegation_test.rb +63 -63
  213. data/test/cases/relation/merging_test.rb +157 -157
  214. data/test/cases/relation/mutation_test.rb +183 -183
  215. data/test/cases/relation/or_test.rb +92 -92
  216. data/test/cases/relation/predicate_builder_test.rb +16 -16
  217. data/test/cases/relation/record_fetch_warning_test.rb +40 -40
  218. data/test/cases/relation/where_chain_test.rb +105 -105
  219. data/test/cases/relation/where_clause_test.rb +182 -182
  220. data/test/cases/relation/where_test.rb +322 -322
  221. data/test/cases/relation_test.rb +328 -328
  222. data/test/cases/relations_test.rb +2026 -2026
  223. data/test/cases/reload_models_test.rb +22 -22
  224. data/test/cases/result_test.rb +90 -90
  225. data/test/cases/sanitize_test.rb +176 -176
  226. data/test/cases/schema_dumper_test.rb +457 -457
  227. data/test/cases/schema_loading_test.rb +52 -52
  228. data/test/cases/scoping/default_scoping_test.rb +528 -528
  229. data/test/cases/scoping/named_scoping_test.rb +561 -561
  230. data/test/cases/scoping/relation_scoping_test.rb +400 -400
  231. data/test/cases/secure_token_test.rb +32 -32
  232. data/test/cases/serialization_test.rb +104 -104
  233. data/test/cases/serialized_attribute_test.rb +364 -364
  234. data/test/cases/statement_cache_test.rb +136 -136
  235. data/test/cases/store_test.rb +195 -195
  236. data/test/cases/suppressor_test.rb +63 -63
  237. data/test/cases/tasks/database_tasks_test.rb +462 -462
  238. data/test/cases/tasks/mysql_rake_test.rb +345 -345
  239. data/test/cases/tasks/postgresql_rake_test.rb +304 -304
  240. data/test/cases/tasks/sqlite_rake_test.rb +220 -220
  241. data/test/cases/test_case.rb +131 -131
  242. data/test/cases/test_fixtures_test.rb +36 -36
  243. data/test/cases/time_precision_test.rb +103 -102
  244. data/test/cases/timestamp_test.rb +501 -501
  245. data/test/cases/touch_later_test.rb +121 -121
  246. data/test/cases/transaction_callbacks_test.rb +518 -518
  247. data/test/cases/transaction_isolation_test.rb +106 -106
  248. data/test/cases/transactions_test.rb +835 -834
  249. data/test/cases/type/adapter_specific_registry_test.rb +133 -133
  250. data/test/cases/type/date_time_test.rb +14 -14
  251. data/test/cases/type/integer_test.rb +27 -27
  252. data/test/cases/type/string_test.rb +22 -22
  253. data/test/cases/type/type_map_test.rb +177 -177
  254. data/test/cases/type_test.rb +39 -39
  255. data/test/cases/types_test.rb +24 -24
  256. data/test/cases/unconnected_test.rb +33 -33
  257. data/test/cases/validations/absence_validation_test.rb +73 -73
  258. data/test/cases/validations/association_validation_test.rb +97 -97
  259. data/test/cases/validations/i18n_generate_message_validation_test.rb +84 -84
  260. data/test/cases/validations/i18n_validation_test.rb +86 -86
  261. data/test/cases/validations/length_validation_test.rb +79 -79
  262. data/test/cases/validations/presence_validation_test.rb +103 -103
  263. data/test/cases/validations/uniqueness_validation_test.rb +548 -548
  264. data/test/cases/validations_repair_helper.rb +19 -19
  265. data/test/cases/validations_test.rb +194 -194
  266. data/test/cases/view_test.rb +216 -216
  267. data/test/cases/yaml_serialization_test.rb +121 -121
  268. data/test/config.example.yml +97 -97
  269. data/test/config.rb +5 -5
  270. data/test/connections/native_ibm_db/connection.rb +44 -0
  271. data/test/fixtures/accounts.yml +29 -29
  272. data/test/fixtures/admin/accounts.yml +2 -2
  273. data/test/fixtures/admin/users.yml +10 -10
  274. data/test/fixtures/author_addresses.yml +17 -17
  275. data/test/fixtures/author_favorites.yml +3 -3
  276. data/test/fixtures/authors.yml +23 -23
  277. data/test/fixtures/bad_posts.yml +9 -9
  278. data/test/fixtures/binaries.yml +133 -133
  279. data/test/fixtures/books.yml +31 -31
  280. data/test/fixtures/bulbs.yml +5 -5
  281. data/test/fixtures/cars.yml +9 -9
  282. data/test/fixtures/categories.yml +19 -19
  283. data/test/fixtures/categories/special_categories.yml +9 -9
  284. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -4
  285. data/test/fixtures/categories_ordered.yml +7 -7
  286. data/test/fixtures/categories_posts.yml +31 -31
  287. data/test/fixtures/categorizations.yml +23 -23
  288. data/test/fixtures/clubs.yml +8 -8
  289. data/test/fixtures/collections.yml +3 -3
  290. data/test/fixtures/colleges.yml +3 -3
  291. data/test/fixtures/comments.yml +65 -65
  292. data/test/fixtures/companies.yml +67 -67
  293. data/test/fixtures/computers.yml +10 -10
  294. data/test/fixtures/content.yml +3 -3
  295. data/test/fixtures/content_positions.yml +3 -3
  296. data/test/fixtures/courses.yml +8 -8
  297. data/test/fixtures/customers.yml +25 -25
  298. data/test/fixtures/dashboards.yml +6 -6
  299. data/test/fixtures/dead_parrots.yml +5 -5
  300. data/test/fixtures/developers.yml +22 -22
  301. data/test/fixtures/developers_projects.yml +16 -16
  302. data/test/fixtures/dog_lovers.yml +7 -7
  303. data/test/fixtures/dogs.yml +4 -4
  304. data/test/fixtures/doubloons.yml +3 -3
  305. data/test/fixtures/edges.yml +5 -5
  306. data/test/fixtures/entrants.yml +14 -14
  307. data/test/fixtures/essays.yml +6 -6
  308. data/test/fixtures/faces.yml +11 -11
  309. data/test/fixtures/fk_test_has_fk.yml +3 -3
  310. data/test/fixtures/fk_test_has_pk.yml +1 -1
  311. data/test/fixtures/friendships.yml +4 -4
  312. data/test/fixtures/funny_jokes.yml +10 -10
  313. data/test/fixtures/interests.yml +33 -33
  314. data/test/fixtures/items.yml +3 -3
  315. data/test/fixtures/jobs.yml +7 -7
  316. data/test/fixtures/legacy_things.yml +3 -3
  317. data/test/fixtures/live_parrots.yml +4 -4
  318. data/test/fixtures/mateys.yml +4 -4
  319. data/test/fixtures/member_details.yml +8 -8
  320. data/test/fixtures/member_types.yml +6 -6
  321. data/test/fixtures/members.yml +11 -11
  322. data/test/fixtures/memberships.yml +34 -34
  323. data/test/fixtures/men.yml +5 -5
  324. data/test/fixtures/minimalistics.yml +2 -2
  325. data/test/fixtures/minivans.yml +5 -5
  326. data/test/fixtures/mixed_case_monkeys.yml +6 -6
  327. data/test/fixtures/mixins.yml +29 -29
  328. data/test/fixtures/movies.yml +7 -7
  329. data/test/fixtures/naked/yml/accounts.yml +1 -1
  330. data/test/fixtures/naked/yml/companies.yml +1 -1
  331. data/test/fixtures/naked/yml/courses.yml +1 -1
  332. data/test/fixtures/naked/yml/parrots.yml +2 -2
  333. data/test/fixtures/naked/yml/trees.yml +3 -3
  334. data/test/fixtures/nodes.yml +29 -29
  335. data/test/fixtures/organizations.yml +5 -5
  336. data/test/fixtures/other_comments.yml +6 -6
  337. data/test/fixtures/other_dogs.yml +2 -2
  338. data/test/fixtures/other_posts.yml +7 -7
  339. data/test/fixtures/other_topics.yml +42 -42
  340. data/test/fixtures/owners.yml +9 -9
  341. data/test/fixtures/parrots.yml +27 -27
  342. data/test/fixtures/parrots_pirates.yml +7 -7
  343. data/test/fixtures/people.yml +24 -24
  344. data/test/fixtures/peoples_treasures.yml +3 -3
  345. data/test/fixtures/pets.yml +19 -19
  346. data/test/fixtures/pirates.yml +12 -15
  347. data/test/fixtures/posts.yml +80 -80
  348. data/test/fixtures/price_estimates.yml +16 -16
  349. data/test/fixtures/products.yml +4 -4
  350. data/test/fixtures/projects.yml +7 -7
  351. data/test/fixtures/ratings.yml +14 -14
  352. data/test/fixtures/readers.yml +11 -11
  353. data/test/fixtures/references.yml +17 -17
  354. data/test/fixtures/reserved_words/distinct.yml +5 -5
  355. data/test/fixtures/reserved_words/distinct_select.yml +11 -11
  356. data/test/fixtures/reserved_words/group.yml +14 -14
  357. data/test/fixtures/reserved_words/select.yml +8 -8
  358. data/test/fixtures/reserved_words/values.yml +7 -7
  359. data/test/fixtures/ships.yml +6 -6
  360. data/test/fixtures/speedometers.yml +8 -8
  361. data/test/fixtures/sponsors.yml +12 -12
  362. data/test/fixtures/string_key_objects.yml +7 -7
  363. data/test/fixtures/subscribers.yml +10 -10
  364. data/test/fixtures/subscriptions.yml +12 -12
  365. data/test/fixtures/taggings.yml +78 -78
  366. data/test/fixtures/tags.yml +11 -11
  367. data/test/fixtures/tasks.yml +7 -7
  368. data/test/fixtures/teapots.yml +3 -3
  369. data/test/fixtures/to_be_linked/accounts.yml +2 -2
  370. data/test/fixtures/to_be_linked/users.yml +10 -10
  371. data/test/fixtures/topics.yml +49 -49
  372. data/test/fixtures/toys.yml +14 -14
  373. data/test/fixtures/traffic_lights.yml +9 -9
  374. data/test/fixtures/treasures.yml +10 -10
  375. data/test/fixtures/trees.yml +3 -3
  376. data/test/fixtures/uuid_children.yml +3 -3
  377. data/test/fixtures/uuid_parents.yml +2 -2
  378. data/test/fixtures/variants.yml +4 -4
  379. data/test/fixtures/vegetables.yml +19 -19
  380. data/test/fixtures/vertices.yml +3 -3
  381. data/test/fixtures/warehouse_things.yml +2 -2
  382. data/test/fixtures/zines.yml +5 -5
  383. data/test/migrations/10_urban/9_add_expressions.rb +11 -11
  384. data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -15
  385. data/test/migrations/magic/1_currencies_have_symbols.rb +12 -12
  386. data/test/migrations/missing/1000_people_have_middle_names.rb +9 -9
  387. data/test/migrations/missing/1_people_have_last_names.rb +9 -9
  388. data/test/migrations/missing/3_we_need_reminders.rb +12 -12
  389. data/test/migrations/missing/4_innocent_jointable.rb +12 -12
  390. data/test/migrations/rename/1_we_need_things.rb +11 -11
  391. data/test/migrations/rename/2_rename_things.rb +9 -9
  392. data/test/migrations/to_copy/1_people_have_hobbies.rb +9 -9
  393. data/test/migrations/to_copy/2_people_have_descriptions.rb +9 -9
  394. data/test/migrations/to_copy2/1_create_articles.rb +7 -7
  395. data/test/migrations/to_copy2/2_create_comments.rb +7 -7
  396. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +9 -9
  397. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +9 -9
  398. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +9 -9
  399. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +7 -7
  400. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +7 -7
  401. data/test/migrations/valid/1_valid_people_have_last_names.rb +9 -9
  402. data/test/migrations/valid/2_we_need_reminders.rb +12 -12
  403. data/test/migrations/valid/3_innocent_jointable.rb +12 -12
  404. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +9 -9
  405. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +12 -12
  406. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +12 -12
  407. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +9 -9
  408. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +12 -12
  409. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +12 -12
  410. data/test/migrations/version_check/20131219224947_migration_version_check.rb +8 -8
  411. data/test/models/admin.rb +5 -5
  412. data/test/models/admin/account.rb +3 -3
  413. data/test/models/admin/user.rb +40 -40
  414. data/test/models/aircraft.rb +5 -5
  415. data/test/models/arunit2_model.rb +3 -3
  416. data/test/models/author.rb +209 -209
  417. data/test/models/auto_id.rb +4 -4
  418. data/test/models/autoloadable/extra_firm.rb +2 -2
  419. data/test/models/binary.rb +2 -2
  420. data/test/models/bird.rb +12 -12
  421. data/test/models/book.rb +23 -23
  422. data/test/models/boolean.rb +2 -2
  423. data/test/models/bulb.rb +52 -52
  424. data/test/models/cake_designer.rb +3 -3
  425. data/test/models/car.rb +29 -29
  426. data/test/models/carrier.rb +2 -2
  427. data/test/models/cat.rb +10 -10
  428. data/test/models/categorization.rb +19 -19
  429. data/test/models/category.rb +35 -35
  430. data/test/models/chef.rb +8 -8
  431. data/test/models/citation.rb +3 -3
  432. data/test/models/club.rb +25 -25
  433. data/test/models/college.rb +10 -10
  434. data/test/models/column.rb +3 -3
  435. data/test/models/column_name.rb +3 -3
  436. data/test/models/comment.rb +76 -76
  437. data/test/models/company.rb +230 -230
  438. data/test/models/company_in_module.rb +98 -98
  439. data/test/models/computer.rb +3 -3
  440. data/test/models/contact.rb +41 -41
  441. data/test/models/content.rb +40 -40
  442. data/test/models/contract.rb +20 -20
  443. data/test/models/country.rb +7 -7
  444. data/test/models/course.rb +6 -6
  445. data/test/models/customer.rb +83 -83
  446. data/test/models/customer_carrier.rb +14 -14
  447. data/test/models/dashboard.rb +3 -3
  448. data/test/models/default.rb +2 -2
  449. data/test/models/department.rb +4 -4
  450. data/test/models/developer.rb +274 -274
  451. data/test/models/dog.rb +5 -5
  452. data/test/models/dog_lover.rb +5 -5
  453. data/test/models/doubloon.rb +12 -12
  454. data/test/models/drink_designer.rb +3 -3
  455. data/test/models/edge.rb +5 -5
  456. data/test/models/electron.rb +5 -5
  457. data/test/models/engine.rb +4 -4
  458. data/test/models/entrant.rb +3 -3
  459. data/test/models/essay.rb +5 -5
  460. data/test/models/event.rb +3 -3
  461. data/test/models/eye.rb +37 -37
  462. data/test/models/face.rb +9 -9
  463. data/test/models/friendship.rb +6 -6
  464. data/test/models/guid.rb +2 -2
  465. data/test/models/guitar.rb +4 -4
  466. data/test/models/hotel.rb +11 -11
  467. data/test/models/image.rb +3 -3
  468. data/test/models/interest.rb +5 -5
  469. data/test/models/invoice.rb +4 -4
  470. data/test/models/item.rb +7 -7
  471. data/test/models/job.rb +7 -7
  472. data/test/models/joke.rb +7 -7
  473. data/test/models/keyboard.rb +3 -3
  474. data/test/models/legacy_thing.rb +3 -3
  475. data/test/models/lesson.rb +11 -11
  476. data/test/models/line_item.rb +3 -3
  477. data/test/models/liquid.rb +4 -4
  478. data/test/models/man.rb +11 -11
  479. data/test/models/matey.rb +4 -4
  480. data/test/models/member.rb +42 -42
  481. data/test/models/member_detail.rb +8 -8
  482. data/test/models/member_type.rb +3 -3
  483. data/test/models/membership.rb +35 -35
  484. data/test/models/mentor.rb +2 -2
  485. data/test/models/minimalistic.rb +2 -2
  486. data/test/models/minivan.rb +9 -9
  487. data/test/models/mixed_case_monkey.rb +3 -3
  488. data/test/models/mocktail_designer.rb +2 -2
  489. data/test/models/molecule.rb +6 -6
  490. data/test/models/movie.rb +5 -5
  491. data/test/models/node.rb +5 -5
  492. data/test/models/non_primary_key.rb +2 -2
  493. data/test/models/notification.rb +3 -3
  494. data/test/models/order.rb +4 -4
  495. data/test/models/organization.rb +14 -14
  496. data/test/models/other_dog.rb +5 -5
  497. data/test/models/owner.rb +37 -37
  498. data/test/models/parrot.rb +28 -28
  499. data/test/models/person.rb +142 -142
  500. data/test/models/personal_legacy_thing.rb +4 -4
  501. data/test/models/pet.rb +18 -18
  502. data/test/models/pet_treasure.rb +6 -6
  503. data/test/models/pirate.rb +92 -92
  504. data/test/models/possession.rb +3 -3
  505. data/test/models/post.rb +273 -273
  506. data/test/models/price_estimate.rb +4 -4
  507. data/test/models/professor.rb +5 -5
  508. data/test/models/project.rb +40 -40
  509. data/test/models/publisher.rb +2 -2
  510. data/test/models/publisher/article.rb +4 -4
  511. data/test/models/publisher/magazine.rb +3 -3
  512. data/test/models/rating.rb +4 -4
  513. data/test/models/reader.rb +23 -23
  514. data/test/models/recipe.rb +3 -3
  515. data/test/models/record.rb +2 -2
  516. data/test/models/reference.rb +22 -22
  517. data/test/models/reply.rb +61 -61
  518. data/test/models/ship.rb +39 -39
  519. data/test/models/ship_part.rb +8 -8
  520. data/test/models/shop.rb +17 -17
  521. data/test/models/shop_account.rb +6 -6
  522. data/test/models/speedometer.rb +6 -6
  523. data/test/models/sponsor.rb +7 -7
  524. data/test/models/string_key_object.rb +3 -3
  525. data/test/models/student.rb +4 -4
  526. data/test/models/subject.rb +16 -16
  527. data/test/models/subscriber.rb +8 -8
  528. data/test/models/subscription.rb +4 -4
  529. data/test/models/tag.rb +13 -13
  530. data/test/models/tagging.rb +13 -13
  531. data/test/models/task.rb +5 -5
  532. data/test/models/topic.rb +118 -118
  533. data/test/models/toy.rb +6 -6
  534. data/test/models/traffic_light.rb +4 -4
  535. data/test/models/treasure.rb +14 -14
  536. data/test/models/treaty.rb +7 -7
  537. data/test/models/tree.rb +3 -3
  538. data/test/models/tuning_peg.rb +4 -4
  539. data/test/models/tyre.rb +11 -11
  540. data/test/models/user.rb +14 -14
  541. data/test/models/uuid_child.rb +3 -3
  542. data/test/models/uuid_item.rb +6 -6
  543. data/test/models/uuid_parent.rb +3 -3
  544. data/test/models/vegetables.rb +24 -24
  545. data/test/models/vehicle.rb +6 -6
  546. data/test/models/vertex.rb +9 -9
  547. data/test/models/warehouse_thing.rb +5 -5
  548. data/test/models/wheel.rb +3 -3
  549. data/test/models/without_table.rb +3 -3
  550. data/test/models/zine.rb +3 -3
  551. data/test/schema/i5/ibm_db_specific_schema.rb +137 -0
  552. data/test/schema/ids/ibm_db_specific_schema.rb +140 -0
  553. data/test/schema/luw/ibm_db_specific_schema.rb +137 -0
  554. data/test/schema/mysql2_specific_schema.rb +68 -68
  555. data/test/schema/oracle_specific_schema.rb +40 -40
  556. data/test/schema/postgresql_specific_schema.rb +114 -114
  557. data/test/schema/schema.rb +1057 -1057
  558. data/test/schema/schema.rb.original +1057 -1057
  559. data/test/schema/sqlite_specific_schema.rb +18 -18
  560. data/test/schema/zOS/ibm_db_specific_schema.rb +208 -0
  561. data/test/support/config.rb +43 -43
  562. data/test/support/connection.rb +23 -23
  563. data/test/support/connection_helper.rb +14 -14
  564. data/test/support/ddl_helper.rb +8 -8
  565. data/test/support/schema_dumping_helper.rb +20 -20
  566. data/test/support/yaml_compatibility_fixtures/rails_4_1.yml +22 -22
  567. data/test/support/yaml_compatibility_fixtures/rails_4_2_0.yml +182 -182
  568. metadata +24 -13
  569. data/test/fixtures/author_addresses.original +0 -11
  570. data/test/fixtures/authors.original +0 -17
@@ -1,87 +1,87 @@
1
- require "cases/helper"
2
- require 'models/post'
3
- require 'models/comment'
4
- require 'models/project'
5
- require 'models/developer'
6
- require 'models/computer'
7
- require 'models/company_in_module'
8
-
9
- class AssociationsExtensionsTest < ActiveRecord::TestCase
10
- fixtures :projects, :developers, :developers_projects, :comments, :posts
11
-
12
- def test_extension_on_has_many
13
- assert_equal comments(:more_greetings), posts(:welcome).comments.find_most_recent
14
- end
15
-
16
- def test_extension_on_habtm
17
- assert_equal projects(:action_controller), developers(:david).projects.find_most_recent
18
- end
19
-
20
- def test_named_extension_on_habtm
21
- assert_equal projects(:action_controller), developers(:david).projects_extended_by_name.find_most_recent
22
- end
23
-
24
- def test_named_two_extensions_on_habtm
25
- assert_equal projects(:action_controller), developers(:david).projects_extended_by_name_twice.find_most_recent
26
- assert_equal projects(:active_record), developers(:david).projects_extended_by_name_twice.find_least_recent
27
- end
28
-
29
- def test_named_extension_and_block_on_habtm
30
- assert_equal projects(:action_controller), developers(:david).projects_extended_by_name_and_block.find_most_recent
31
- assert_equal projects(:active_record), developers(:david).projects_extended_by_name_and_block.find_least_recent
32
- end
33
-
34
- def test_extension_with_scopes
35
- assert_equal comments(:greetings), posts(:welcome).comments.offset(1).find_most_recent
36
- assert_equal comments(:greetings), posts(:welcome).comments.not_again.find_most_recent
37
- end
38
-
39
- def test_marshalling_extensions
40
- david = developers(:david)
41
- assert_equal projects(:action_controller), david.projects.find_most_recent
42
-
43
- marshalled = Marshal.dump(david)
44
-
45
- # Marshaling an association shouldn't make it unusable by wiping its reflection.
46
- assert_not_nil david.association(:projects).reflection
47
-
48
- david_too = Marshal.load(marshalled)
49
- assert_equal projects(:action_controller), david_too.projects.find_most_recent
50
- end
51
-
52
- def test_marshalling_named_extensions
53
- david = developers(:david)
54
- assert_equal projects(:action_controller), david.projects_extended_by_name.find_most_recent
55
-
56
- marshalled = Marshal.dump(david)
57
- david = Marshal.load(marshalled)
58
-
59
- assert_equal projects(:action_controller), david.projects_extended_by_name.find_most_recent
60
- end
61
-
62
- def test_extension_name
63
- extend!(Developer)
64
- extend!(MyApplication::Business::Developer)
65
-
66
- assert Object.const_get 'DeveloperAssociationNameAssociationExtension'
67
- assert MyApplication::Business.const_get 'DeveloperAssociationNameAssociationExtension'
68
- end
69
-
70
- def test_proxy_association_after_scoped
71
- post = posts(:welcome)
72
- assert_equal post.association(:comments), post.comments.the_association
73
- assert_equal post.association(:comments), post.comments.where('1=1').the_association
74
- end
75
-
76
- def test_association_with_default_scope
77
- assert_raises OopsError do
78
- posts(:welcome).comments.destroy_all
79
- end
80
- end
81
-
82
- private
83
-
84
- def extend!(model)
85
- ActiveRecord::Associations::Builder::HasMany.define_extensions(model, :association_name) { }
86
- end
87
- end
1
+ require "cases/helper"
2
+ require 'models/post'
3
+ require 'models/comment'
4
+ require 'models/project'
5
+ require 'models/developer'
6
+ require 'models/computer'
7
+ require 'models/company_in_module'
8
+
9
+ class AssociationsExtensionsTest < ActiveRecord::TestCase
10
+ fixtures :projects, :developers, :developers_projects, :comments, :posts
11
+
12
+ def test_extension_on_has_many
13
+ assert_equal comments(:more_greetings), posts(:welcome).comments.find_most_recent
14
+ end
15
+
16
+ def test_extension_on_habtm
17
+ assert_equal projects(:action_controller), developers(:david).projects.find_most_recent
18
+ end
19
+
20
+ def test_named_extension_on_habtm
21
+ assert_equal projects(:action_controller), developers(:david).projects_extended_by_name.find_most_recent
22
+ end
23
+
24
+ def test_named_two_extensions_on_habtm
25
+ assert_equal projects(:action_controller), developers(:david).projects_extended_by_name_twice.find_most_recent
26
+ assert_equal projects(:active_record), developers(:david).projects_extended_by_name_twice.find_least_recent
27
+ end
28
+
29
+ def test_named_extension_and_block_on_habtm
30
+ assert_equal projects(:action_controller), developers(:david).projects_extended_by_name_and_block.find_most_recent
31
+ assert_equal projects(:active_record), developers(:david).projects_extended_by_name_and_block.find_least_recent
32
+ end
33
+
34
+ def test_extension_with_scopes
35
+ assert_equal comments(:greetings), posts(:welcome).comments.offset(1).find_most_recent
36
+ assert_equal comments(:greetings), posts(:welcome).comments.not_again.find_most_recent
37
+ end
38
+
39
+ def test_marshalling_extensions
40
+ david = developers(:david)
41
+ assert_equal projects(:action_controller), david.projects.find_most_recent
42
+
43
+ marshalled = Marshal.dump(david)
44
+
45
+ # Marshaling an association shouldn't make it unusable by wiping its reflection.
46
+ assert_not_nil david.association(:projects).reflection
47
+
48
+ david_too = Marshal.load(marshalled)
49
+ assert_equal projects(:action_controller), david_too.projects.find_most_recent
50
+ end
51
+
52
+ def test_marshalling_named_extensions
53
+ david = developers(:david)
54
+ assert_equal projects(:action_controller), david.projects_extended_by_name.find_most_recent
55
+
56
+ marshalled = Marshal.dump(david)
57
+ david = Marshal.load(marshalled)
58
+
59
+ assert_equal projects(:action_controller), david.projects_extended_by_name.find_most_recent
60
+ end
61
+
62
+ def test_extension_name
63
+ extend!(Developer)
64
+ extend!(MyApplication::Business::Developer)
65
+
66
+ assert Object.const_get 'DeveloperAssociationNameAssociationExtension'
67
+ assert MyApplication::Business.const_get 'DeveloperAssociationNameAssociationExtension'
68
+ end
69
+
70
+ def test_proxy_association_after_scoped
71
+ post = posts(:welcome)
72
+ assert_equal post.association(:comments), post.comments.the_association
73
+ assert_equal post.association(:comments), post.comments.where('1=1').the_association
74
+ end
75
+
76
+ def test_association_with_default_scope
77
+ assert_raises OopsError do
78
+ posts(:welcome).comments.destroy_all
79
+ end
80
+ end
81
+
82
+ private
83
+
84
+ def extend!(model)
85
+ ActiveRecord::Associations::Builder::HasMany.define_extensions(model, :association_name) { }
86
+ end
87
+ end
@@ -1,1004 +1,1004 @@
1
- require "cases/helper"
2
- require 'models/developer'
3
- require 'models/computer'
4
- require 'models/project'
5
- require 'models/company'
6
- require 'models/course'
7
- require 'models/customer'
8
- require 'models/order'
9
- require 'models/categorization'
10
- require 'models/category'
11
- require 'models/post'
12
- require 'models/author'
13
- require 'models/tag'
14
- require 'models/tagging'
15
- require 'models/parrot'
16
- require 'models/person'
17
- require 'models/pirate'
18
- require 'models/professor'
19
- require 'models/treasure'
20
- require 'models/price_estimate'
21
- require 'models/club'
22
- require 'models/user'
23
- require 'models/member'
24
- require 'models/membership'
25
- require 'models/sponsor'
26
- require 'models/country'
27
- require 'models/treaty'
28
- require 'models/vertex'
29
- require 'models/publisher'
30
- require 'models/publisher/article'
31
- require 'models/publisher/magazine'
32
- require 'active_support/core_ext/string/conversions'
33
-
34
- class ProjectWithAfterCreateHook < ActiveRecord::Base
35
- self.table_name = 'projects'
36
- has_and_belongs_to_many :developers,
37
- :class_name => "DeveloperForProjectWithAfterCreateHook",
38
- :join_table => "developers_projects",
39
- :foreign_key => "project_id",
40
- :association_foreign_key => "developer_id"
41
-
42
- after_create :add_david
43
-
44
- def add_david
45
- david = DeveloperForProjectWithAfterCreateHook.find_by_name('David')
46
- david.projects << self
47
- end
48
- end
49
-
50
- class DeveloperForProjectWithAfterCreateHook < ActiveRecord::Base
51
- self.table_name = 'developers'
52
- has_and_belongs_to_many :projects,
53
- :class_name => "ProjectWithAfterCreateHook",
54
- :join_table => "developers_projects",
55
- :association_foreign_key => "project_id",
56
- :foreign_key => "developer_id"
57
- end
58
-
59
- class ProjectWithSymbolsForKeys < ActiveRecord::Base
60
- self.table_name = 'projects'
61
- has_and_belongs_to_many :developers,
62
- :class_name => "DeveloperWithSymbolsForKeys",
63
- :join_table => :developers_projects,
64
- :foreign_key => :project_id,
65
- :association_foreign_key => "developer_id"
66
- end
67
-
68
- class DeveloperWithSymbolsForKeys < ActiveRecord::Base
69
- self.table_name = 'developers'
70
- has_and_belongs_to_many :projects,
71
- :class_name => "ProjectWithSymbolsForKeys",
72
- :join_table => :developers_projects,
73
- :association_foreign_key => :project_id,
74
- :foreign_key => "developer_id"
75
- end
76
-
77
- class SubDeveloper < Developer
78
- self.table_name = 'developers'
79
- has_and_belongs_to_many :special_projects,
80
- :join_table => 'developers_projects',
81
- :foreign_key => "project_id",
82
- :association_foreign_key => "developer_id"
83
- end
84
-
85
- class DeveloperWithSymbolClassName < Developer
86
- has_and_belongs_to_many :projects, class_name: :ProjectWithSymbolsForKeys
87
- end
88
-
89
- class DeveloperWithExtendOption < Developer
90
- module NamedExtension
91
- def category
92
- 'sns'
93
- end
94
- end
95
-
96
- has_and_belongs_to_many :projects, extend: NamedExtension
97
- end
98
-
99
- class ProjectUnscopingDavidDefaultScope < ActiveRecord::Base
100
- self.table_name = 'projects'
101
- has_and_belongs_to_many :developers, -> { unscope(where: 'name') },
102
- class_name: "LazyBlockDeveloperCalledDavid",
103
- join_table: "developers_projects",
104
- foreign_key: "project_id",
105
- association_foreign_key: "developer_id"
106
- end
107
-
108
- class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
109
- fixtures :accounts, :companies, :categories, :posts, :categories_posts, :developers, :projects, :developers_projects,
110
- :parrots, :pirates, :parrots_pirates, :treasures, :price_estimates, :tags, :taggings, :computers
111
-
112
- def setup_data_for_habtm_case
113
- ActiveRecord::Base.connection.execute('delete from countries_treaties')
114
-
115
- country = Country.new(:name => 'India')
116
- country.country_id = 'c1'
117
- country.save!
118
-
119
- treaty = Treaty.new(:name => 'peace')
120
- treaty.treaty_id = 't1'
121
- country.treaties << treaty
122
- end
123
-
124
- def test_marshal_dump
125
- post = posts :welcome
126
- preloaded = Post.includes(:categories).find post.id
127
- assert_equal preloaded, Marshal.load(Marshal.dump(preloaded))
128
- end
129
-
130
- def test_should_property_quote_string_primary_keys
131
- setup_data_for_habtm_case
132
-
133
- con = ActiveRecord::Base.connection
134
- sql = 'select * from countries_treaties'
135
- record = con.select_rows(sql).last
136
- assert_equal 'c1', record[0]
137
- assert_equal 't1', record[1]
138
- end
139
-
140
- def test_proper_usage_of_primary_keys_and_join_table
141
- setup_data_for_habtm_case
142
-
143
- assert_equal 'country_id', Country.primary_key
144
- assert_equal 'treaty_id', Treaty.primary_key
145
-
146
- country = Country.first
147
- assert_equal 1, country.treaties.count
148
- end
149
-
150
- def test_join_table_composite_primary_key_should_not_warn
151
- country = Country.new(:name => 'India')
152
- country.country_id = 'c1'
153
- country.save!
154
-
155
- treaty = Treaty.new(:name => 'peace')
156
- treaty.treaty_id = 't1'
157
- warning = capture(:stderr) do
158
- country.treaties << treaty
159
- end
160
- assert_no_match(/WARNING: Active Record does not support composite primary key\./, warning)
161
- end
162
-
163
- def test_has_and_belongs_to_many
164
- david = Developer.find(1)
165
-
166
- assert !david.projects.empty?
167
- assert_equal 2, david.projects.size
168
-
169
- active_record = Project.find(1)
170
- assert !active_record.developers.empty?
171
- assert_equal 3, active_record.developers.size
172
- assert active_record.developers.include?(david)
173
- end
174
-
175
- def test_adding_single
176
- jamis = Developer.find(2)
177
- jamis.projects.reload # causing the collection to load
178
- action_controller = Project.find(2)
179
- assert_equal 1, jamis.projects.size
180
- assert_equal 1, action_controller.developers.size
181
-
182
- jamis.projects << action_controller
183
-
184
- assert_equal 2, jamis.projects.size
185
- assert_equal 2, jamis.projects.reload.size
186
- assert_equal 2, action_controller.developers.reload.size
187
- end
188
-
189
- def test_adding_type_mismatch
190
- jamis = Developer.find(2)
191
- assert_raise(ActiveRecord::AssociationTypeMismatch) { jamis.projects << nil }
192
- assert_raise(ActiveRecord::AssociationTypeMismatch) { jamis.projects << 1 }
193
- end
194
-
195
- def test_adding_from_the_project
196
- jamis = Developer.find(2)
197
- action_controller = Project.find(2)
198
- action_controller.developers.reload
199
- assert_equal 1, jamis.projects.size
200
- assert_equal 1, action_controller.developers.size
201
-
202
- action_controller.developers << jamis
203
-
204
- assert_equal 2, jamis.projects.reload.size
205
- assert_equal 2, action_controller.developers.size
206
- assert_equal 2, action_controller.developers.reload.size
207
- end
208
-
209
- def test_adding_from_the_project_fixed_timestamp
210
- jamis = Developer.find(2)
211
- action_controller = Project.find(2)
212
- action_controller.developers.reload
213
- assert_equal 1, jamis.projects.size
214
- assert_equal 1, action_controller.developers.size
215
- updated_at = jamis.updated_at
216
-
217
- action_controller.developers << jamis
218
-
219
- assert_equal updated_at, jamis.updated_at
220
- assert_equal 2, jamis.projects.reload.size
221
- assert_equal 2, action_controller.developers.size
222
- assert_equal 2, action_controller.developers.reload.size
223
- end
224
-
225
- def test_adding_multiple
226
- aredridel = Developer.new("name" => "Aredridel")
227
- aredridel.save
228
- aredridel.projects.reload
229
- aredridel.projects.push(Project.find(1), Project.find(2))
230
- assert_equal 2, aredridel.projects.size
231
- assert_equal 2, aredridel.projects.reload.size
232
- end
233
-
234
- def test_adding_a_collection
235
- aredridel = Developer.new("name" => "Aredridel")
236
- aredridel.save
237
- aredridel.projects.reload
238
- aredridel.projects.concat([Project.find(1), Project.find(2)])
239
- assert_equal 2, aredridel.projects.size
240
- assert_equal 2, aredridel.projects.reload.size
241
- end
242
-
243
- def test_habtm_adding_before_save
244
- no_of_devels = Developer.count
245
- no_of_projects = Project.count
246
- aredridel = Developer.new("name" => "Aredridel")
247
- aredridel.projects.concat([Project.find(1), p = Project.new("name" => "Projekt")])
248
- assert !aredridel.persisted?
249
- assert !p.persisted?
250
- assert aredridel.save
251
- assert aredridel.persisted?
252
- assert_equal no_of_devels+1, Developer.count
253
- assert_equal no_of_projects+1, Project.count
254
- assert_equal 2, aredridel.projects.size
255
- assert_equal 2, aredridel.projects.reload.size
256
- end
257
-
258
- def test_habtm_saving_multiple_relationships
259
- new_project = Project.new("name" => "Grimetime")
260
- amount_of_developers = 4
261
- developers = (0...amount_of_developers).collect {|i| Developer.create(:name => "JME #{i}") }.reverse
262
-
263
- new_project.developer_ids = [developers[0].id, developers[1].id]
264
- new_project.developers_with_callback_ids = [developers[2].id, developers[3].id]
265
- assert new_project.save
266
-
267
- new_project.reload
268
- assert_equal amount_of_developers, new_project.developers.size
269
- assert_equal developers, new_project.developers
270
- end
271
-
272
- def test_habtm_distinct_order_preserved
273
- assert_equal developers(:poor_jamis, :jamis, :david), projects(:active_record).non_unique_developers
274
- assert_equal developers(:poor_jamis, :jamis, :david), projects(:active_record).developers
275
- end
276
-
277
- def test_habtm_collection_size_from_build
278
- devel = Developer.create("name" => "Fred Wu")
279
- devel.projects << Project.create("name" => "Grimetime")
280
- devel.projects.build
281
-
282
- assert_equal 2, devel.projects.size
283
- end
284
-
285
- def test_habtm_collection_size_from_params
286
- devel = Developer.new({
287
- projects_attributes: {
288
- '0' => {}
289
- }
290
- })
291
-
292
- assert_equal 1, devel.projects.size
293
- end
294
-
295
- def test_build
296
- devel = Developer.find(1)
297
- proj = assert_no_queries(ignore_none: false) { devel.projects.build("name" => "Projekt") }
298
- assert !devel.projects.loaded?
299
-
300
- assert_equal devel.projects.last, proj
301
- assert devel.projects.loaded?
302
-
303
- assert !proj.persisted?
304
- devel.save
305
- assert proj.persisted?
306
- assert_equal devel.projects.last, proj
307
- assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
308
- end
309
-
310
- def test_new_aliased_to_build
311
- devel = Developer.find(1)
312
- proj = assert_no_queries(ignore_none: false) { devel.projects.new("name" => "Projekt") }
313
- assert !devel.projects.loaded?
314
-
315
- assert_equal devel.projects.last, proj
316
- assert devel.projects.loaded?
317
-
318
- assert !proj.persisted?
319
- devel.save
320
- assert proj.persisted?
321
- assert_equal devel.projects.last, proj
322
- assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
323
- end
324
-
325
- def test_build_by_new_record
326
- devel = Developer.new(:name => "Marcel", :salary => 75000)
327
- devel.projects.build(:name => "Make bed")
328
- proj2 = devel.projects.build(:name => "Lie in it")
329
- assert_equal devel.projects.last, proj2
330
- assert !proj2.persisted?
331
- devel.save
332
- assert devel.persisted?
333
- assert proj2.persisted?
334
- assert_equal devel.projects.last, proj2
335
- assert_equal Developer.find_by_name("Marcel").projects.last, proj2 # prove join table is updated
336
- end
337
-
338
- def test_create
339
- devel = Developer.find(1)
340
- proj = devel.projects.create("name" => "Projekt")
341
- assert !devel.projects.loaded?
342
-
343
- assert_equal devel.projects.last, proj
344
- assert !devel.projects.loaded?
345
-
346
- assert proj.persisted?
347
- assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
348
- end
349
-
350
- def test_create_by_new_record
351
- devel = Developer.new(:name => "Marcel", :salary => 75000)
352
- devel.projects.build(:name => "Make bed")
353
- proj2 = devel.projects.build(:name => "Lie in it")
354
- assert_equal devel.projects.last, proj2
355
- assert !proj2.persisted?
356
- devel.save
357
- assert devel.persisted?
358
- assert proj2.persisted?
359
- assert_equal devel.projects.last, proj2
360
- assert_equal Developer.find_by_name("Marcel").projects.last, proj2 # prove join table is updated
361
- end
362
-
363
- def test_creation_respects_hash_condition
364
- # in Oracle '' is saved as null therefore need to save ' ' in not null column
365
- post = categories(:general).post_with_conditions.build(:body => ' ')
366
-
367
- assert post.save
368
- assert_equal 'Yet Another Testing Title', post.title
369
-
370
- # in Oracle '' is saved as null therefore need to save ' ' in not null column
371
- another_post = categories(:general).post_with_conditions.create(:body => ' ')
372
-
373
- assert another_post.persisted?
374
- assert_equal 'Yet Another Testing Title', another_post.title
375
- end
376
-
377
- def test_distinct_after_the_fact
378
- dev = developers(:jamis)
379
- dev.projects << projects(:active_record)
380
- dev.projects << projects(:active_record)
381
-
382
- assert_equal 3, dev.projects.size
383
- assert_equal 1, dev.projects.distinct.size
384
- end
385
-
386
- def test_distinct_before_the_fact
387
- projects(:active_record).developers << developers(:jamis)
388
- projects(:active_record).developers << developers(:david)
389
- assert_equal 3, projects(:active_record, :reload).developers.size
390
- end
391
-
392
- def test_distinct_option_prevents_duplicate_push
393
- project = projects(:active_record)
394
- project.developers << developers(:jamis)
395
- project.developers << developers(:david)
396
- assert_equal 3, project.developers.size
397
-
398
- project.developers << developers(:david)
399
- project.developers << developers(:jamis)
400
- assert_equal 3, project.developers.size
401
- end
402
-
403
- def test_distinct_when_association_already_loaded
404
- project = projects(:active_record)
405
- project.developers << [ developers(:jamis), developers(:david), developers(:jamis), developers(:david) ]
406
- assert_equal 3, Project.includes(:developers).find(project.id).developers.size
407
- end
408
-
409
- def test_deleting
410
- david = Developer.find(1)
411
- active_record = Project.find(1)
412
- david.projects.reload
413
- assert_equal 2, david.projects.size
414
- assert_equal 3, active_record.developers.size
415
-
416
- david.projects.delete(active_record)
417
-
418
- assert_equal 1, david.projects.size
419
- assert_equal 1, david.projects.reload.size
420
- assert_equal 2, active_record.developers.reload.size
421
- end
422
-
423
- def test_deleting_array
424
- david = Developer.find(1)
425
- david.projects.reload
426
- david.projects.delete(Project.all.to_a)
427
- assert_equal 0, david.projects.size
428
- assert_equal 0, david.projects.reload.size
429
- end
430
-
431
- def test_deleting_all
432
- david = Developer.find(1)
433
- david.projects.reload
434
- david.projects.clear
435
- assert_equal 0, david.projects.size
436
- assert_equal 0, david.projects.reload.size
437
- end
438
-
439
- def test_removing_associations_on_destroy
440
- david = DeveloperWithBeforeDestroyRaise.find(1)
441
- assert !david.projects.empty?
442
- david.destroy
443
- assert david.projects.empty?
444
- assert DeveloperWithBeforeDestroyRaise.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = 1").empty?
445
- end
446
-
447
- def test_destroying
448
- david = Developer.find(1)
449
- project = Project.find(1)
450
- david.projects.reload
451
- assert_equal 2, david.projects.size
452
- assert_equal 3, project.developers.size
453
-
454
- assert_no_difference "Project.count" do
455
- david.projects.destroy(project)
456
- end
457
-
458
- join_records = Developer.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = #{david.id} AND project_id = #{project.id}")
459
- assert join_records.empty?
460
-
461
- assert_equal 1, david.reload.projects.size
462
- assert_equal 1, david.projects.reload.size
463
- end
464
-
465
- def test_destroying_many
466
- david = Developer.find(1)
467
- david.projects.reload
468
- projects = Project.all.to_a
469
-
470
- assert_no_difference "Project.count" do
471
- david.projects.destroy(*projects)
472
- end
473
-
474
- join_records = Developer.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = #{david.id}")
475
- assert join_records.empty?
476
-
477
- assert_equal 0, david.reload.projects.size
478
- assert_equal 0, david.projects.reload.size
479
- end
480
-
481
- def test_destroy_all
482
- david = Developer.find(1)
483
- david.projects.reload
484
- assert !david.projects.empty?
485
-
486
- assert_no_difference "Project.count" do
487
- david.projects.destroy_all
488
- end
489
-
490
- join_records = Developer.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = #{david.id}")
491
- assert join_records.empty?
492
-
493
- assert david.projects.empty?
494
- assert david.projects.reload.empty?
495
- end
496
-
497
- def test_destroy_associations_destroys_multiple_associations
498
- george = parrots(:george)
499
- assert !george.pirates.empty?
500
- assert !george.treasures.empty?
501
-
502
- assert_no_difference "Pirate.count" do
503
- assert_no_difference "Treasure.count" do
504
- george.destroy_associations
505
- end
506
- end
507
-
508
- join_records = Parrot.connection.select_all("SELECT * FROM parrots_pirates WHERE parrot_id = #{george.id}")
509
- assert join_records.empty?
510
- assert george.pirates.reload.empty?
511
-
512
- join_records = Parrot.connection.select_all("SELECT * FROM parrots_treasures WHERE parrot_id = #{george.id}")
513
- assert join_records.empty?
514
- assert george.treasures.reload.empty?
515
- end
516
-
517
- def test_associations_with_conditions
518
- assert_equal 3, projects(:active_record).developers.size
519
- assert_equal 1, projects(:active_record).developers_named_david.size
520
- assert_equal 1, projects(:active_record).developers_named_david_with_hash_conditions.size
521
-
522
- assert_equal developers(:david), projects(:active_record).developers_named_david.find(developers(:david).id)
523
- assert_equal developers(:david), projects(:active_record).developers_named_david_with_hash_conditions.find(developers(:david).id)
524
- assert_equal developers(:david), projects(:active_record).salaried_developers.find(developers(:david).id)
525
-
526
- projects(:active_record).developers_named_david.clear
527
- assert_equal 2, projects(:active_record, :reload).developers.size
528
- end
529
-
530
- def test_find_in_association
531
- # Using sql
532
- assert_equal developers(:david), projects(:active_record).developers.find(developers(:david).id), "SQL find"
533
-
534
- # Using ruby
535
- active_record = projects(:active_record)
536
- active_record.developers.reload
537
- assert_equal developers(:david), active_record.developers.find(developers(:david).id), "Ruby find"
538
- end
539
-
540
- def test_include_uses_array_include_after_loaded
541
- project = projects(:active_record)
542
- project.developers.load_target
543
-
544
- developer = project.developers.first
545
-
546
- assert_no_queries(ignore_none: false) do
547
- assert project.developers.loaded?
548
- assert project.developers.include?(developer)
549
- end
550
- end
551
-
552
- def test_include_checks_if_record_exists_if_target_not_loaded
553
- project = projects(:active_record)
554
- developer = project.developers.first
555
-
556
- project.reload
557
- assert ! project.developers.loaded?
558
- assert_queries(1) do
559
- assert project.developers.include?(developer)
560
- end
561
- assert ! project.developers.loaded?
562
- end
563
-
564
- def test_include_returns_false_for_non_matching_record_to_verify_scoping
565
- project = projects(:active_record)
566
- developer = Developer.create :name => "Bryan", :salary => 50_000
567
-
568
- assert ! project.developers.loaded?
569
- assert ! project.developers.include?(developer)
570
- end
571
-
572
- def test_find_with_merged_options
573
- assert_equal 1, projects(:active_record).limited_developers.size
574
- assert_equal 1, projects(:active_record).limited_developers.to_a.size
575
- assert_equal 3, projects(:active_record).limited_developers.limit(nil).to_a.size
576
- end
577
-
578
- def test_dynamic_find_should_respect_association_order
579
- # Developers are ordered 'name DESC, id DESC'
580
- high_id_jamis = projects(:active_record).developers.create(:name => 'Jamis')
581
-
582
- assert_equal high_id_jamis, projects(:active_record).developers.merge(:where => "name = 'Jamis'").first
583
- assert_equal high_id_jamis, projects(:active_record).developers.find_by_name('Jamis')
584
- end
585
-
586
- def test_find_should_append_to_association_order
587
- ordered_developers = projects(:active_record).developers.order('projects.id')
588
- assert_equal ['developers.name desc, developers.id desc', 'projects.id'], ordered_developers.order_values
589
- end
590
-
591
- def test_dynamic_find_all_should_respect_readonly_access
592
- projects(:active_record).readonly_developers.each { |d| assert_raise(ActiveRecord::ReadOnlyRecord) { d.save! } if d.valid?}
593
- projects(:active_record).readonly_developers.each(&:readonly?)
594
- end
595
-
596
- def test_new_with_values_in_collection
597
- jamis = DeveloperForProjectWithAfterCreateHook.find_by_name('Jamis')
598
- david = DeveloperForProjectWithAfterCreateHook.find_by_name('David')
599
- project = ProjectWithAfterCreateHook.new(:name => "Cooking with Bertie")
600
- project.developers << jamis
601
- project.save!
602
- project.reload
603
-
604
- assert project.developers.include?(jamis)
605
- assert project.developers.include?(david)
606
- end
607
-
608
- def test_find_in_association_with_options
609
- developers = projects(:active_record).developers.to_a
610
- assert_equal 3, developers.size
611
-
612
- assert_equal developers(:poor_jamis), projects(:active_record).developers.where("salary < 10000").first
613
- end
614
-
615
- def test_association_with_extend_option
616
- eponine = DeveloperWithExtendOption.create(name: 'Eponine')
617
- assert_equal 'sns', eponine.projects.category
618
- end
619
-
620
- def test_replace_with_less
621
- david = developers(:david)
622
- david.projects = [projects(:action_controller)]
623
- assert david.save
624
- assert_equal 1, david.projects.length
625
- end
626
-
627
- def test_replace_with_new
628
- david = developers(:david)
629
- david.projects = [projects(:action_controller), Project.new("name" => "ActionWebSearch")]
630
- david.save
631
- assert_equal 2, david.projects.length
632
- assert !david.projects.include?(projects(:active_record))
633
- end
634
-
635
- def test_replace_on_new_object
636
- new_developer = Developer.new("name" => "Matz")
637
- new_developer.projects = [projects(:action_controller), Project.new("name" => "ActionWebSearch")]
638
- new_developer.save
639
- assert_equal 2, new_developer.projects.length
640
- end
641
-
642
- def test_consider_type
643
- developer = Developer.first
644
- special_project = SpecialProject.create("name" => "Special Project")
645
-
646
- other_project = developer.projects.first
647
- developer.special_projects << special_project
648
- developer.reload
649
-
650
- assert developer.projects.include?(special_project)
651
- assert developer.special_projects.include?(special_project)
652
- assert !developer.special_projects.include?(other_project)
653
- end
654
-
655
- def test_symbol_join_table
656
- developer = Developer.first
657
- sp = developer.sym_special_projects.create("name" => "omg")
658
- developer.reload
659
- assert_includes developer.sym_special_projects, sp
660
- end
661
-
662
- def test_update_attributes_after_push_without_duplicate_join_table_rows
663
- developer = Developer.new("name" => "Kano")
664
- project = SpecialProject.create("name" => "Special Project")
665
- assert developer.save
666
- developer.projects << project
667
- developer.update_columns("name" => "Bruza")
668
- assert_equal 1, Developer.connection.select_value(<<-end_sql).to_i
669
- SELECT count(*) FROM developers_projects
670
- WHERE project_id = #{project.id}
671
- AND developer_id = #{developer.id}
672
- end_sql
673
- end
674
-
675
- def test_updating_attributes_on_non_rich_associations
676
- welcome = categories(:technology).posts.first
677
- welcome.title = "Something else"
678
- assert welcome.save!
679
- end
680
-
681
- def test_habtm_respects_select
682
- categories(:technology).select_testing_posts.reload.each do |o|
683
- assert_respond_to o, :correctness_marker
684
- end
685
- assert_respond_to categories(:technology).select_testing_posts.first, :correctness_marker
686
- end
687
-
688
- def test_habtm_selects_all_columns_by_default
689
- assert_equal Project.column_names.sort, developers(:david).projects.first.attributes.keys.sort
690
- end
691
-
692
- def test_habtm_respects_select_query_method
693
- assert_equal ['id'], developers(:david).projects.select(:id).first.attributes.keys
694
- end
695
-
696
- def test_join_table_alias
697
- # FIXME: `references` has no impact on the aliases generated for the join
698
- # query. The fact that we pass `:developers_projects_join` to `references`
699
- # and that the SQL string contains `developers_projects_join` is merely a
700
- # coincidence.
701
- assert_equal(
702
- 3,
703
- Developer.references(:developers_projects_join).merge(
704
- :includes => {:projects => :developers},
705
- :where => 'projects_developers_projects_join.joined_on IS NOT NULL'
706
- ).to_a.size
707
- )
708
- end
709
-
710
- def test_join_with_group
711
- # FIXME: `references` has no impact on the aliases generated for the join
712
- # query. The fact that we pass `:developers_projects_join` to `references`
713
- # and that the SQL string contains `developers_projects_join` is merely a
714
- # coincidence.
715
- group = Developer.columns.inject([]) do |g, c|
716
- g << "developers.#{c.name}"
717
- g << "developers_projects_2.#{c.name}"
718
- end
719
- Project.columns.each { |c| group << "projects.#{c.name}" }
720
-
721
- assert_equal(
722
- 3,
723
- Developer.references(:developers_projects_join).merge(
724
- :includes => {:projects => :developers}, :where => 'projects_developers_projects_join.joined_on IS NOT NULL',
725
- :group => group.join(",")
726
- ).to_a.size
727
- )
728
- end
729
-
730
- def test_find_grouped
731
- all_posts_from_category1 = Post.all.merge!(:where => "category_id = 1", :joins => :categories).to_a
732
- grouped_posts_of_category1 = Post.all.merge!(:where => "category_id = 1", :group => "author_id", :select => 'count(posts.id) as posts_count', :joins => :categories).to_a
733
- assert_equal 5, all_posts_from_category1.size
734
- assert_equal 2, grouped_posts_of_category1.size
735
- end
736
-
737
- def test_find_scoped_grouped
738
- assert_equal 5, categories(:general).posts_grouped_by_title.to_a.size
739
- assert_equal 1, categories(:technology).posts_grouped_by_title.to_a.size
740
- end
741
-
742
- def test_find_scoped_grouped_having
743
- assert_equal 2, projects(:active_record).well_payed_salary_groups.to_a.size
744
- assert projects(:active_record).well_payed_salary_groups.all? { |g| g.salary > 10000 }
745
- end
746
-
747
- def test_get_ids
748
- assert_equal projects(:active_record, :action_controller).map(&:id).sort, developers(:david).project_ids.sort
749
- assert_equal [projects(:active_record).id], developers(:jamis).project_ids
750
- end
751
-
752
- def test_get_ids_for_loaded_associations
753
- developer = developers(:david)
754
- developer.projects.reload
755
- assert_queries(0) do
756
- developer.project_ids
757
- developer.project_ids
758
- end
759
- end
760
-
761
- def test_get_ids_for_unloaded_associations_does_not_load_them
762
- developer = developers(:david)
763
- assert !developer.projects.loaded?
764
- assert_equal projects(:active_record, :action_controller).map(&:id).sort, developer.project_ids.sort
765
- assert !developer.projects.loaded?
766
- end
767
-
768
- def test_assign_ids
769
- developer = Developer.new("name" => "Joe")
770
- developer.project_ids = projects(:active_record, :action_controller).map(&:id)
771
- developer.save
772
- developer.reload
773
- assert_equal 2, developer.projects.length
774
- assert_equal [projects(:active_record), projects(:action_controller)].map(&:id).sort, developer.project_ids.sort
775
- end
776
-
777
- def test_assign_ids_ignoring_blanks
778
- developer = Developer.new("name" => "Joe")
779
- developer.project_ids = [projects(:active_record).id, nil, projects(:action_controller).id, '']
780
- developer.save
781
- developer.reload
782
- assert_equal 2, developer.projects.length
783
- assert_equal [projects(:active_record), projects(:action_controller)].map(&:id).sort, developer.project_ids.sort
784
- end
785
-
786
- def test_scoped_find_on_through_association_doesnt_return_read_only_records
787
- tag = Post.find(1).tags.find_by_name("General")
788
-
789
- assert_nothing_raised do
790
- tag.save!
791
- end
792
- end
793
-
794
- def test_has_many_through_polymorphic_has_manys_works
795
- assert_equal [10, 20].to_set, pirates(:redbeard).treasure_estimates.map(&:price).to_set
796
- end
797
-
798
- def test_symbols_as_keys
799
- developer = DeveloperWithSymbolsForKeys.new(:name => 'David')
800
- project = ProjectWithSymbolsForKeys.new(:name => 'Rails Testing')
801
- project.developers << developer
802
- project.save!
803
-
804
- assert_equal 1, project.developers.size
805
- assert_equal 1, developer.projects.size
806
- assert_equal developer, project.developers.first
807
- assert_equal project, developer.projects.first
808
- end
809
-
810
- def test_dynamic_find_should_respect_association_include
811
- # SQL error in sort clause if :include is not included
812
- # due to Unknown column 'authors.id'
813
- assert Category.find(1).posts_with_authors_sorted_by_author_id.find_by_title('Welcome to the weblog')
814
- end
815
-
816
- def test_count
817
- david = Developer.find(1)
818
- assert_equal 2, david.projects.count
819
- end
820
-
821
- def test_association_proxy_transaction_method_starts_transaction_in_association_class
822
- assert_called(Post, :transaction) do
823
- Category.first.posts.transaction do
824
- # nothing
825
- end
826
- end
827
- end
828
-
829
- def test_caching_of_columns
830
- david = Developer.find(1)
831
- # clear cache possibly created by other tests
832
- david.projects.reset_column_information
833
-
834
- assert_queries(:any) { david.projects.columns }
835
- assert_no_queries { david.projects.columns }
836
-
837
- ## and again to verify that reset_column_information clears the cache correctly
838
- david.projects.reset_column_information
839
-
840
- assert_queries(:any) { david.projects.columns }
841
- assert_no_queries { david.projects.columns }
842
- end
843
-
844
- def test_attributes_are_being_set_when_initialized_from_habtm_association_with_where_clause
845
- new_developer = projects(:action_controller).developers.where(:name => "Marcelo").build
846
- assert_equal new_developer.name, "Marcelo"
847
- end
848
-
849
- def test_attributes_are_being_set_when_initialized_from_habtm_association_with_multiple_where_clauses
850
- new_developer = projects(:action_controller).developers.where(:name => "Marcelo").where(:salary => 90_000).build
851
- assert_equal new_developer.name, "Marcelo"
852
- assert_equal new_developer.salary, 90_000
853
- end
854
-
855
- def test_include_method_in_has_and_belongs_to_many_association_should_return_true_for_instance_added_with_build
856
- project = Project.new
857
- developer = project.developers.build
858
- assert project.developers.include?(developer)
859
- end
860
-
861
- def test_destruction_does_not_error_without_primary_key
862
- redbeard = pirates(:redbeard)
863
- george = parrots(:george)
864
- redbeard.parrots << george
865
- assert_equal 2, george.pirates.count
866
- Pirate.includes(:parrots).where(parrot: redbeard.parrot).find(redbeard.id).destroy
867
- assert_equal 1, george.pirates.count
868
- assert_equal [], Pirate.where(id: redbeard.id)
869
- end
870
-
871
- def test_has_and_belongs_to_many_associations_on_new_records_use_null_relations
872
- projects = Developer.new.projects
873
- assert_no_queries(ignore_none: false) do
874
- assert_equal [], projects
875
- assert_equal [], projects.where(title: 'omg')
876
- assert_equal [], projects.pluck(:title)
877
- assert_equal 0, projects.count
878
- end
879
- end
880
-
881
- def test_association_with_validate_false_does_not_run_associated_validation_callbacks_on_create
882
- rich_person = RichPerson.new
883
-
884
- treasure = Treasure.new
885
- treasure.rich_people << rich_person
886
- treasure.valid?
887
-
888
- assert_equal 1, treasure.rich_people.size
889
- assert_nil rich_person.first_name, 'should not run associated person validation on create when validate: false'
890
- end
891
-
892
- def test_association_with_validate_false_does_not_run_associated_validation_callbacks_on_update
893
- rich_person = RichPerson.create!
894
- person_first_name = rich_person.first_name
895
- assert_not_nil person_first_name
896
-
897
- treasure = Treasure.new
898
- treasure.rich_people << rich_person
899
- treasure.valid?
900
-
901
- assert_equal 1, treasure.rich_people.size
902
- assert_equal person_first_name, rich_person.first_name, 'should not run associated person validation on update when validate: false'
903
- end
904
-
905
- def test_custom_join_table
906
- assert_equal 'edges', Vertex.reflect_on_association(:sources).join_table
907
- end
908
-
909
- def test_has_and_belongs_to_many_in_a_namespaced_model_pointing_to_a_namespaced_model
910
- magazine = Publisher::Magazine.create
911
- article = Publisher::Article.create
912
- magazine.articles << article
913
- magazine.save
914
-
915
- assert_includes magazine.articles, article
916
- end
917
-
918
- def test_has_and_belongs_to_many_in_a_namespaced_model_pointing_to_a_non_namespaced_model
919
- article = Publisher::Article.create
920
- tag = Tag.create
921
- article.tags << tag
922
- article.save
923
-
924
- assert_includes article.tags, tag
925
- end
926
-
927
- def test_redefine_habtm
928
- child = SubDeveloper.new("name" => "Aredridel")
929
- child.special_projects << SpecialProject.new("name" => "Special Project")
930
- assert child.save, 'child object should be saved'
931
- end
932
-
933
- def test_habtm_with_reflection_using_class_name_and_fixtures
934
- assert_not_nil Developer._reflections['shared_computers']
935
- # Checking the fixture for named association is important here, because it's the only way
936
- # we've been able to reproduce this bug
937
- assert_not_nil File.read(File.expand_path("../../../fixtures/developers.yml", __FILE__)).index("shared_computers")
938
- assert_equal developers(:david).shared_computers.first, computers(:laptop)
939
- end
940
-
941
- def test_with_symbol_class_name
942
- assert_nothing_raised do
943
- DeveloperWithSymbolClassName.new
944
- end
945
- end
946
-
947
- def test_association_force_reload_with_only_true_is_deprecated
948
- developer = Developer.find(1)
949
-
950
- assert_deprecated { developer.projects(true) }
951
- end
952
-
953
- def test_alternate_database
954
- professor = Professor.create(name: "Plum")
955
- course = Course.create(name: "Forensics")
956
- assert_equal 0, professor.courses.count
957
- assert_nothing_raised do
958
- professor.courses << course
959
- end
960
- assert_equal 1, professor.courses.count
961
- end
962
-
963
- def test_habtm_scope_can_unscope
964
- project = ProjectUnscopingDavidDefaultScope.new
965
- project.save!
966
-
967
- developer = LazyBlockDeveloperCalledDavid.new(name: "Not David")
968
- developer.save!
969
- project.developers << developer
970
-
971
- projects = ProjectUnscopingDavidDefaultScope.includes(:developers).where(id: project.id)
972
- assert_equal 1, projects.first.developers.size
973
- end
974
-
975
- def test_preloaded_associations_size
976
- assert_equal Project.first.salaried_developers.size,
977
- Project.preload(:salaried_developers).first.salaried_developers.size
978
-
979
- assert_equal Project.includes(:salaried_developers).references(:salaried_developers).first.salaried_developers.size,
980
- Project.preload(:salaried_developers).first.salaried_developers.size
981
-
982
- # Nested HATBM
983
- first_project = Developer.first.projects.first
984
- preloaded_first_project =
985
- Developer.preload(projects: :salaried_developers).
986
- first.
987
- projects.
988
- detect { |p| p.id == first_project.id }
989
-
990
- assert preloaded_first_project.salaried_developers.loaded?, true
991
- assert_equal first_project.salaried_developers.size, preloaded_first_project.salaried_developers.size
992
- end
993
-
994
- def test_has_and_belongs_to_many_is_useable_with_belongs_to_required_by_default
995
- assert_difference "Project.first.developers_required_by_default.size", 1 do
996
- Project.first.developers_required_by_default.create!(name: "Sean", salary: 50000)
997
- end
998
- end
999
-
1000
- def test_association_name_is_the_same_as_join_table_name
1001
- user = User.create!
1002
- assert_nothing_raised { user.jobs_pool.clear }
1003
- end
1004
- end
1
+ require "cases/helper"
2
+ require 'models/developer'
3
+ require 'models/computer'
4
+ require 'models/project'
5
+ require 'models/company'
6
+ require 'models/course'
7
+ require 'models/customer'
8
+ require 'models/order'
9
+ require 'models/categorization'
10
+ require 'models/category'
11
+ require 'models/post'
12
+ require 'models/author'
13
+ require 'models/tag'
14
+ require 'models/tagging'
15
+ require 'models/parrot'
16
+ require 'models/person'
17
+ require 'models/pirate'
18
+ require 'models/professor'
19
+ require 'models/treasure'
20
+ require 'models/price_estimate'
21
+ require 'models/club'
22
+ require 'models/user'
23
+ require 'models/member'
24
+ require 'models/membership'
25
+ require 'models/sponsor'
26
+ require 'models/country'
27
+ require 'models/treaty'
28
+ require 'models/vertex'
29
+ require 'models/publisher'
30
+ require 'models/publisher/article'
31
+ require 'models/publisher/magazine'
32
+ require 'active_support/core_ext/string/conversions'
33
+
34
+ class ProjectWithAfterCreateHook < ActiveRecord::Base
35
+ self.table_name = 'projects'
36
+ has_and_belongs_to_many :developers,
37
+ :class_name => "DeveloperForProjectWithAfterCreateHook",
38
+ :join_table => "developers_projects",
39
+ :foreign_key => "project_id",
40
+ :association_foreign_key => "developer_id"
41
+
42
+ after_create :add_david
43
+
44
+ def add_david
45
+ david = DeveloperForProjectWithAfterCreateHook.find_by_name('David')
46
+ david.projects << self
47
+ end
48
+ end
49
+
50
+ class DeveloperForProjectWithAfterCreateHook < ActiveRecord::Base
51
+ self.table_name = 'developers'
52
+ has_and_belongs_to_many :projects,
53
+ :class_name => "ProjectWithAfterCreateHook",
54
+ :join_table => "developers_projects",
55
+ :association_foreign_key => "project_id",
56
+ :foreign_key => "developer_id"
57
+ end
58
+
59
+ class ProjectWithSymbolsForKeys < ActiveRecord::Base
60
+ self.table_name = 'projects'
61
+ has_and_belongs_to_many :developers,
62
+ :class_name => "DeveloperWithSymbolsForKeys",
63
+ :join_table => :developers_projects,
64
+ :foreign_key => :project_id,
65
+ :association_foreign_key => "developer_id"
66
+ end
67
+
68
+ class DeveloperWithSymbolsForKeys < ActiveRecord::Base
69
+ self.table_name = 'developers'
70
+ has_and_belongs_to_many :projects,
71
+ :class_name => "ProjectWithSymbolsForKeys",
72
+ :join_table => :developers_projects,
73
+ :association_foreign_key => :project_id,
74
+ :foreign_key => "developer_id"
75
+ end
76
+
77
+ class SubDeveloper < Developer
78
+ self.table_name = 'developers'
79
+ has_and_belongs_to_many :special_projects,
80
+ :join_table => 'developers_projects',
81
+ :foreign_key => "project_id",
82
+ :association_foreign_key => "developer_id"
83
+ end
84
+
85
+ class DeveloperWithSymbolClassName < Developer
86
+ has_and_belongs_to_many :projects, class_name: :ProjectWithSymbolsForKeys
87
+ end
88
+
89
+ class DeveloperWithExtendOption < Developer
90
+ module NamedExtension
91
+ def category
92
+ 'sns'
93
+ end
94
+ end
95
+
96
+ has_and_belongs_to_many :projects, extend: NamedExtension
97
+ end
98
+
99
+ class ProjectUnscopingDavidDefaultScope < ActiveRecord::Base
100
+ self.table_name = 'projects'
101
+ has_and_belongs_to_many :developers, -> { unscope(where: 'name') },
102
+ class_name: "LazyBlockDeveloperCalledDavid",
103
+ join_table: "developers_projects",
104
+ foreign_key: "project_id",
105
+ association_foreign_key: "developer_id"
106
+ end
107
+
108
+ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
109
+ fixtures :accounts, :companies, :categories, :posts, :categories_posts, :developers, :projects, :developers_projects,
110
+ :parrots, :pirates, :parrots_pirates, :treasures, :price_estimates, :tags, :taggings, :computers
111
+
112
+ def setup_data_for_habtm_case
113
+ ActiveRecord::Base.connection.execute('delete from countries_treaties')
114
+
115
+ country = Country.new(:name => 'India')
116
+ country.country_id = 'c1'
117
+ country.save!
118
+
119
+ treaty = Treaty.new(:name => 'peace')
120
+ treaty.treaty_id = 't1'
121
+ country.treaties << treaty
122
+ end
123
+
124
+ def test_marshal_dump
125
+ post = posts :welcome
126
+ preloaded = Post.includes(:categories).find post.id
127
+ assert_equal preloaded, Marshal.load(Marshal.dump(preloaded))
128
+ end
129
+
130
+ def test_should_property_quote_string_primary_keys
131
+ setup_data_for_habtm_case
132
+
133
+ con = ActiveRecord::Base.connection
134
+ sql = 'select * from countries_treaties'
135
+ record = con.select_rows(sql).last
136
+ assert_equal 'c1', record[0]
137
+ assert_equal 't1', record[1]
138
+ end
139
+
140
+ def test_proper_usage_of_primary_keys_and_join_table
141
+ setup_data_for_habtm_case
142
+
143
+ assert_equal 'country_id', Country.primary_key
144
+ assert_equal 'treaty_id', Treaty.primary_key
145
+
146
+ country = Country.first
147
+ assert_equal 1, country.treaties.count
148
+ end
149
+
150
+ def test_join_table_composite_primary_key_should_not_warn
151
+ country = Country.new(:name => 'India')
152
+ country.country_id = 'c1'
153
+ country.save!
154
+
155
+ treaty = Treaty.new(:name => 'peace')
156
+ treaty.treaty_id = 't1'
157
+ warning = capture(:stderr) do
158
+ country.treaties << treaty
159
+ end
160
+ assert_no_match(/WARNING: Active Record does not support composite primary key\./, warning)
161
+ end
162
+
163
+ def test_has_and_belongs_to_many
164
+ david = Developer.find(1)
165
+
166
+ assert !david.projects.empty?
167
+ assert_equal 2, david.projects.size
168
+
169
+ active_record = Project.find(1)
170
+ assert !active_record.developers.empty?
171
+ assert_equal 3, active_record.developers.size
172
+ assert active_record.developers.include?(david)
173
+ end
174
+
175
+ def test_adding_single
176
+ jamis = Developer.find(2)
177
+ jamis.projects.reload # causing the collection to load
178
+ action_controller = Project.find(2)
179
+ assert_equal 1, jamis.projects.size
180
+ assert_equal 1, action_controller.developers.size
181
+
182
+ jamis.projects << action_controller
183
+
184
+ assert_equal 2, jamis.projects.size
185
+ assert_equal 2, jamis.projects.reload.size
186
+ assert_equal 2, action_controller.developers.reload.size
187
+ end
188
+
189
+ def test_adding_type_mismatch
190
+ jamis = Developer.find(2)
191
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { jamis.projects << nil }
192
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { jamis.projects << 1 }
193
+ end
194
+
195
+ def test_adding_from_the_project
196
+ jamis = Developer.find(2)
197
+ action_controller = Project.find(2)
198
+ action_controller.developers.reload
199
+ assert_equal 1, jamis.projects.size
200
+ assert_equal 1, action_controller.developers.size
201
+
202
+ action_controller.developers << jamis
203
+
204
+ assert_equal 2, jamis.projects.reload.size
205
+ assert_equal 2, action_controller.developers.size
206
+ assert_equal 2, action_controller.developers.reload.size
207
+ end
208
+
209
+ def test_adding_from_the_project_fixed_timestamp
210
+ jamis = Developer.find(2)
211
+ action_controller = Project.find(2)
212
+ action_controller.developers.reload
213
+ assert_equal 1, jamis.projects.size
214
+ assert_equal 1, action_controller.developers.size
215
+ updated_at = jamis.updated_at
216
+
217
+ action_controller.developers << jamis
218
+
219
+ assert_equal updated_at, jamis.updated_at
220
+ assert_equal 2, jamis.projects.reload.size
221
+ assert_equal 2, action_controller.developers.size
222
+ assert_equal 2, action_controller.developers.reload.size
223
+ end
224
+
225
+ def test_adding_multiple
226
+ aredridel = Developer.new("name" => "Aredridel")
227
+ aredridel.save
228
+ aredridel.projects.reload
229
+ aredridel.projects.push(Project.find(1), Project.find(2))
230
+ assert_equal 2, aredridel.projects.size
231
+ assert_equal 2, aredridel.projects.reload.size
232
+ end
233
+
234
+ def test_adding_a_collection
235
+ aredridel = Developer.new("name" => "Aredridel")
236
+ aredridel.save
237
+ aredridel.projects.reload
238
+ aredridel.projects.concat([Project.find(1), Project.find(2)])
239
+ assert_equal 2, aredridel.projects.size
240
+ assert_equal 2, aredridel.projects.reload.size
241
+ end
242
+
243
+ def test_habtm_adding_before_save
244
+ no_of_devels = Developer.count
245
+ no_of_projects = Project.count
246
+ aredridel = Developer.new("name" => "Aredridel")
247
+ aredridel.projects.concat([Project.find(1), p = Project.new("name" => "Projekt")])
248
+ assert !aredridel.persisted?
249
+ assert !p.persisted?
250
+ assert aredridel.save
251
+ assert aredridel.persisted?
252
+ assert_equal no_of_devels+1, Developer.count
253
+ assert_equal no_of_projects+1, Project.count
254
+ assert_equal 2, aredridel.projects.size
255
+ assert_equal 2, aredridel.projects.reload.size
256
+ end
257
+
258
+ def test_habtm_saving_multiple_relationships
259
+ new_project = Project.new("name" => "Grimetime")
260
+ amount_of_developers = 4
261
+ developers = (0...amount_of_developers).collect {|i| Developer.create(:name => "JME #{i}") }.reverse
262
+
263
+ new_project.developer_ids = [developers[0].id, developers[1].id]
264
+ new_project.developers_with_callback_ids = [developers[2].id, developers[3].id]
265
+ assert new_project.save
266
+
267
+ new_project.reload
268
+ assert_equal amount_of_developers, new_project.developers.size
269
+ assert_equal developers, new_project.developers
270
+ end
271
+
272
+ def test_habtm_distinct_order_preserved
273
+ assert_equal developers(:poor_jamis, :jamis, :david), projects(:active_record).non_unique_developers
274
+ assert_equal developers(:poor_jamis, :jamis, :david), projects(:active_record).developers
275
+ end
276
+
277
+ def test_habtm_collection_size_from_build
278
+ devel = Developer.create("name" => "Fred Wu")
279
+ devel.projects << Project.create("name" => "Grimetime")
280
+ devel.projects.build
281
+
282
+ assert_equal 2, devel.projects.size
283
+ end
284
+
285
+ def test_habtm_collection_size_from_params
286
+ devel = Developer.new({
287
+ projects_attributes: {
288
+ '0' => {}
289
+ }
290
+ })
291
+
292
+ assert_equal 1, devel.projects.size
293
+ end
294
+
295
+ def test_build
296
+ devel = Developer.find(1)
297
+ proj = assert_no_queries(ignore_none: false) { devel.projects.build("name" => "Projekt") }
298
+ assert !devel.projects.loaded?
299
+
300
+ assert_equal devel.projects.last, proj
301
+ assert devel.projects.loaded?
302
+
303
+ assert !proj.persisted?
304
+ devel.save
305
+ assert proj.persisted?
306
+ assert_equal devel.projects.last, proj
307
+ assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
308
+ end
309
+
310
+ def test_new_aliased_to_build
311
+ devel = Developer.find(1)
312
+ proj = assert_no_queries(ignore_none: false) { devel.projects.new("name" => "Projekt") }
313
+ assert !devel.projects.loaded?
314
+
315
+ assert_equal devel.projects.last, proj
316
+ assert devel.projects.loaded?
317
+
318
+ assert !proj.persisted?
319
+ devel.save
320
+ assert proj.persisted?
321
+ assert_equal devel.projects.last, proj
322
+ assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
323
+ end
324
+
325
+ def test_build_by_new_record
326
+ devel = Developer.new(:name => "Marcel", :salary => 75000)
327
+ devel.projects.build(:name => "Make bed")
328
+ proj2 = devel.projects.build(:name => "Lie in it")
329
+ assert_equal devel.projects.last, proj2
330
+ assert !proj2.persisted?
331
+ devel.save
332
+ assert devel.persisted?
333
+ assert proj2.persisted?
334
+ assert_equal devel.projects.last, proj2
335
+ assert_equal Developer.find_by_name("Marcel").projects.last, proj2 # prove join table is updated
336
+ end
337
+
338
+ def test_create
339
+ devel = Developer.find(1)
340
+ proj = devel.projects.create("name" => "Projekt")
341
+ assert !devel.projects.loaded?
342
+
343
+ assert_equal devel.projects.last, proj
344
+ assert !devel.projects.loaded?
345
+
346
+ assert proj.persisted?
347
+ assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
348
+ end
349
+
350
+ def test_create_by_new_record
351
+ devel = Developer.new(:name => "Marcel", :salary => 75000)
352
+ devel.projects.build(:name => "Make bed")
353
+ proj2 = devel.projects.build(:name => "Lie in it")
354
+ assert_equal devel.projects.last, proj2
355
+ assert !proj2.persisted?
356
+ devel.save
357
+ assert devel.persisted?
358
+ assert proj2.persisted?
359
+ assert_equal devel.projects.last, proj2
360
+ assert_equal Developer.find_by_name("Marcel").projects.last, proj2 # prove join table is updated
361
+ end
362
+
363
+ def test_creation_respects_hash_condition
364
+ # in Oracle '' is saved as null therefore need to save ' ' in not null column
365
+ post = categories(:general).post_with_conditions.build(:body => ' ')
366
+
367
+ assert post.save
368
+ assert_equal 'Yet Another Testing Title', post.title
369
+
370
+ # in Oracle '' is saved as null therefore need to save ' ' in not null column
371
+ another_post = categories(:general).post_with_conditions.create(:body => ' ')
372
+
373
+ assert another_post.persisted?
374
+ assert_equal 'Yet Another Testing Title', another_post.title
375
+ end
376
+
377
+ def test_distinct_after_the_fact
378
+ dev = developers(:jamis)
379
+ dev.projects << projects(:active_record)
380
+ dev.projects << projects(:active_record)
381
+
382
+ assert_equal 3, dev.projects.size
383
+ assert_equal 1, dev.projects.distinct.size
384
+ end
385
+
386
+ def test_distinct_before_the_fact
387
+ projects(:active_record).developers << developers(:jamis)
388
+ projects(:active_record).developers << developers(:david)
389
+ assert_equal 3, projects(:active_record, :reload).developers.size
390
+ end
391
+
392
+ def test_distinct_option_prevents_duplicate_push
393
+ project = projects(:active_record)
394
+ project.developers << developers(:jamis)
395
+ project.developers << developers(:david)
396
+ assert_equal 3, project.developers.size
397
+
398
+ project.developers << developers(:david)
399
+ project.developers << developers(:jamis)
400
+ assert_equal 3, project.developers.size
401
+ end
402
+
403
+ def test_distinct_when_association_already_loaded
404
+ project = projects(:active_record)
405
+ project.developers << [ developers(:jamis), developers(:david), developers(:jamis), developers(:david) ]
406
+ assert_equal 3, Project.includes(:developers).find(project.id).developers.size
407
+ end
408
+
409
+ def test_deleting
410
+ david = Developer.find(1)
411
+ active_record = Project.find(1)
412
+ david.projects.reload
413
+ assert_equal 2, david.projects.size
414
+ assert_equal 3, active_record.developers.size
415
+
416
+ david.projects.delete(active_record)
417
+
418
+ assert_equal 1, david.projects.size
419
+ assert_equal 1, david.projects.reload.size
420
+ assert_equal 2, active_record.developers.reload.size
421
+ end
422
+
423
+ def test_deleting_array
424
+ david = Developer.find(1)
425
+ david.projects.reload
426
+ david.projects.delete(Project.all.to_a)
427
+ assert_equal 0, david.projects.size
428
+ assert_equal 0, david.projects.reload.size
429
+ end
430
+
431
+ def test_deleting_all
432
+ david = Developer.find(1)
433
+ david.projects.reload
434
+ david.projects.clear
435
+ assert_equal 0, david.projects.size
436
+ assert_equal 0, david.projects.reload.size
437
+ end
438
+
439
+ def test_removing_associations_on_destroy
440
+ david = DeveloperWithBeforeDestroyRaise.find(1)
441
+ assert !david.projects.empty?
442
+ david.destroy
443
+ assert david.projects.empty?
444
+ assert DeveloperWithBeforeDestroyRaise.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = 1").empty?
445
+ end
446
+
447
+ def test_destroying
448
+ david = Developer.find(1)
449
+ project = Project.find(1)
450
+ david.projects.reload
451
+ assert_equal 2, david.projects.size
452
+ assert_equal 3, project.developers.size
453
+
454
+ assert_no_difference "Project.count" do
455
+ david.projects.destroy(project)
456
+ end
457
+
458
+ join_records = Developer.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = #{david.id} AND project_id = #{project.id}")
459
+ assert join_records.empty?
460
+
461
+ assert_equal 1, david.reload.projects.size
462
+ assert_equal 1, david.projects.reload.size
463
+ end
464
+
465
+ def test_destroying_many
466
+ david = Developer.find(1)
467
+ david.projects.reload
468
+ projects = Project.all.to_a
469
+
470
+ assert_no_difference "Project.count" do
471
+ david.projects.destroy(*projects)
472
+ end
473
+
474
+ join_records = Developer.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = #{david.id}")
475
+ assert join_records.empty?
476
+
477
+ assert_equal 0, david.reload.projects.size
478
+ assert_equal 0, david.projects.reload.size
479
+ end
480
+
481
+ def test_destroy_all
482
+ david = Developer.find(1)
483
+ david.projects.reload
484
+ assert !david.projects.empty?
485
+
486
+ assert_no_difference "Project.count" do
487
+ david.projects.destroy_all
488
+ end
489
+
490
+ join_records = Developer.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = #{david.id}")
491
+ assert join_records.empty?
492
+
493
+ assert david.projects.empty?
494
+ assert david.projects.reload.empty?
495
+ end
496
+
497
+ def test_destroy_associations_destroys_multiple_associations
498
+ george = parrots(:george)
499
+ assert !george.pirates.empty?
500
+ assert !george.treasures.empty?
501
+
502
+ assert_no_difference "Pirate.count" do
503
+ assert_no_difference "Treasure.count" do
504
+ george.destroy_associations
505
+ end
506
+ end
507
+
508
+ join_records = Parrot.connection.select_all("SELECT * FROM parrots_pirates WHERE parrot_id = #{george.id}")
509
+ assert join_records.empty?
510
+ assert george.pirates.reload.empty?
511
+
512
+ join_records = Parrot.connection.select_all("SELECT * FROM parrots_treasures WHERE parrot_id = #{george.id}")
513
+ assert join_records.empty?
514
+ assert george.treasures.reload.empty?
515
+ end
516
+
517
+ def test_associations_with_conditions
518
+ assert_equal 3, projects(:active_record).developers.size
519
+ assert_equal 1, projects(:active_record).developers_named_david.size
520
+ assert_equal 1, projects(:active_record).developers_named_david_with_hash_conditions.size
521
+
522
+ assert_equal developers(:david), projects(:active_record).developers_named_david.find(developers(:david).id)
523
+ assert_equal developers(:david), projects(:active_record).developers_named_david_with_hash_conditions.find(developers(:david).id)
524
+ assert_equal developers(:david), projects(:active_record).salaried_developers.find(developers(:david).id)
525
+
526
+ projects(:active_record).developers_named_david.clear
527
+ assert_equal 2, projects(:active_record, :reload).developers.size
528
+ end
529
+
530
+ def test_find_in_association
531
+ # Using sql
532
+ assert_equal developers(:david), projects(:active_record).developers.find(developers(:david).id), "SQL find"
533
+
534
+ # Using ruby
535
+ active_record = projects(:active_record)
536
+ active_record.developers.reload
537
+ assert_equal developers(:david), active_record.developers.find(developers(:david).id), "Ruby find"
538
+ end
539
+
540
+ def test_include_uses_array_include_after_loaded
541
+ project = projects(:active_record)
542
+ project.developers.load_target
543
+
544
+ developer = project.developers.first
545
+
546
+ assert_no_queries(ignore_none: false) do
547
+ assert project.developers.loaded?
548
+ assert project.developers.include?(developer)
549
+ end
550
+ end
551
+
552
+ def test_include_checks_if_record_exists_if_target_not_loaded
553
+ project = projects(:active_record)
554
+ developer = project.developers.first
555
+
556
+ project.reload
557
+ assert ! project.developers.loaded?
558
+ assert_queries(1) do
559
+ assert project.developers.include?(developer)
560
+ end
561
+ assert ! project.developers.loaded?
562
+ end
563
+
564
+ def test_include_returns_false_for_non_matching_record_to_verify_scoping
565
+ project = projects(:active_record)
566
+ developer = Developer.create :name => "Bryan", :salary => 50_000
567
+
568
+ assert ! project.developers.loaded?
569
+ assert ! project.developers.include?(developer)
570
+ end
571
+
572
+ def test_find_with_merged_options
573
+ assert_equal 1, projects(:active_record).limited_developers.size
574
+ assert_equal 1, projects(:active_record).limited_developers.to_a.size
575
+ assert_equal 3, projects(:active_record).limited_developers.limit(nil).to_a.size
576
+ end
577
+
578
+ def test_dynamic_find_should_respect_association_order
579
+ # Developers are ordered 'name DESC, id DESC'
580
+ high_id_jamis = projects(:active_record).developers.create(:name => 'Jamis')
581
+
582
+ assert_equal high_id_jamis, projects(:active_record).developers.merge(:where => "name = 'Jamis'").first
583
+ assert_equal high_id_jamis, projects(:active_record).developers.find_by_name('Jamis')
584
+ end
585
+
586
+ def test_find_should_append_to_association_order
587
+ ordered_developers = projects(:active_record).developers.order('projects.id')
588
+ assert_equal ['developers.name desc, developers.id desc', 'projects.id'], ordered_developers.order_values
589
+ end
590
+
591
+ def test_dynamic_find_all_should_respect_readonly_access
592
+ projects(:active_record).readonly_developers.each { |d| assert_raise(ActiveRecord::ReadOnlyRecord) { d.save! } if d.valid?}
593
+ projects(:active_record).readonly_developers.each(&:readonly?)
594
+ end
595
+
596
+ def test_new_with_values_in_collection
597
+ jamis = DeveloperForProjectWithAfterCreateHook.find_by_name('Jamis')
598
+ david = DeveloperForProjectWithAfterCreateHook.find_by_name('David')
599
+ project = ProjectWithAfterCreateHook.new(:name => "Cooking with Bertie")
600
+ project.developers << jamis
601
+ project.save!
602
+ project.reload
603
+
604
+ assert project.developers.include?(jamis)
605
+ assert project.developers.include?(david)
606
+ end
607
+
608
+ def test_find_in_association_with_options
609
+ developers = projects(:active_record).developers.to_a
610
+ assert_equal 3, developers.size
611
+
612
+ assert_equal developers(:poor_jamis), projects(:active_record).developers.where("salary < 10000").first
613
+ end
614
+
615
+ def test_association_with_extend_option
616
+ eponine = DeveloperWithExtendOption.create(name: 'Eponine')
617
+ assert_equal 'sns', eponine.projects.category
618
+ end
619
+
620
+ def test_replace_with_less
621
+ david = developers(:david)
622
+ david.projects = [projects(:action_controller)]
623
+ assert david.save
624
+ assert_equal 1, david.projects.length
625
+ end
626
+
627
+ def test_replace_with_new
628
+ david = developers(:david)
629
+ david.projects = [projects(:action_controller), Project.new("name" => "ActionWebSearch")]
630
+ david.save
631
+ assert_equal 2, david.projects.length
632
+ assert !david.projects.include?(projects(:active_record))
633
+ end
634
+
635
+ def test_replace_on_new_object
636
+ new_developer = Developer.new("name" => "Matz")
637
+ new_developer.projects = [projects(:action_controller), Project.new("name" => "ActionWebSearch")]
638
+ new_developer.save
639
+ assert_equal 2, new_developer.projects.length
640
+ end
641
+
642
+ def test_consider_type
643
+ developer = Developer.first
644
+ special_project = SpecialProject.create("name" => "Special Project")
645
+
646
+ other_project = developer.projects.first
647
+ developer.special_projects << special_project
648
+ developer.reload
649
+
650
+ assert developer.projects.include?(special_project)
651
+ assert developer.special_projects.include?(special_project)
652
+ assert !developer.special_projects.include?(other_project)
653
+ end
654
+
655
+ def test_symbol_join_table
656
+ developer = Developer.first
657
+ sp = developer.sym_special_projects.create("name" => "omg")
658
+ developer.reload
659
+ assert_includes developer.sym_special_projects, sp
660
+ end
661
+
662
+ def test_update_attributes_after_push_without_duplicate_join_table_rows
663
+ developer = Developer.new("name" => "Kano")
664
+ project = SpecialProject.create("name" => "Special Project")
665
+ assert developer.save
666
+ developer.projects << project
667
+ developer.update_columns("name" => "Bruza")
668
+ assert_equal 1, Developer.connection.select_value(<<-end_sql).to_i
669
+ SELECT count(*) FROM developers_projects
670
+ WHERE project_id = #{project.id}
671
+ AND developer_id = #{developer.id}
672
+ end_sql
673
+ end
674
+
675
+ def test_updating_attributes_on_non_rich_associations
676
+ welcome = categories(:technology).posts.first
677
+ welcome.title = "Something else"
678
+ assert welcome.save!
679
+ end
680
+
681
+ def test_habtm_respects_select
682
+ categories(:technology).select_testing_posts.reload.each do |o|
683
+ assert_respond_to o, :correctness_marker
684
+ end
685
+ assert_respond_to categories(:technology).select_testing_posts.first, :correctness_marker
686
+ end
687
+
688
+ def test_habtm_selects_all_columns_by_default
689
+ assert_equal Project.column_names.sort, developers(:david).projects.first.attributes.keys.sort
690
+ end
691
+
692
+ def test_habtm_respects_select_query_method
693
+ assert_equal ['id'], developers(:david).projects.select(:id).first.attributes.keys
694
+ end
695
+
696
+ def test_join_table_alias
697
+ # FIXME: `references` has no impact on the aliases generated for the join
698
+ # query. The fact that we pass `:developers_projects_join` to `references`
699
+ # and that the SQL string contains `developers_projects_join` is merely a
700
+ # coincidence.
701
+ assert_equal(
702
+ 3,
703
+ Developer.references(:developers_projects_join).merge(
704
+ :includes => {:projects => :developers},
705
+ :where => 'projects_developers_projects_join.joined_on IS NOT NULL'
706
+ ).to_a.size
707
+ )
708
+ end
709
+
710
+ def test_join_with_group
711
+ # FIXME: `references` has no impact on the aliases generated for the join
712
+ # query. The fact that we pass `:developers_projects_join` to `references`
713
+ # and that the SQL string contains `developers_projects_join` is merely a
714
+ # coincidence.
715
+ group = Developer.columns.inject([]) do |g, c|
716
+ g << "developers.#{c.name}"
717
+ g << "developers_projects_2.#{c.name}"
718
+ end
719
+ Project.columns.each { |c| group << "projects.#{c.name}" }
720
+
721
+ assert_equal(
722
+ 3,
723
+ Developer.references(:developers_projects_join).merge(
724
+ :includes => {:projects => :developers}, :where => 'projects_developers_projects_join.joined_on IS NOT NULL',
725
+ :group => group.join(",")
726
+ ).to_a.size
727
+ )
728
+ end
729
+
730
+ def test_find_grouped
731
+ all_posts_from_category1 = Post.all.merge!(:where => "category_id = 1", :joins => :categories).to_a
732
+ grouped_posts_of_category1 = Post.all.merge!(:where => "category_id = 1", :group => "author_id", :select => 'count(posts.id) as posts_count', :joins => :categories).to_a
733
+ assert_equal 5, all_posts_from_category1.size
734
+ assert_equal 2, grouped_posts_of_category1.size
735
+ end
736
+
737
+ def test_find_scoped_grouped
738
+ assert_equal 5, categories(:general).posts_grouped_by_title.to_a.size
739
+ assert_equal 1, categories(:technology).posts_grouped_by_title.to_a.size
740
+ end
741
+
742
+ def test_find_scoped_grouped_having
743
+ assert_equal 2, projects(:active_record).well_payed_salary_groups.to_a.size
744
+ assert projects(:active_record).well_payed_salary_groups.all? { |g| g.salary > 10000 }
745
+ end
746
+
747
+ def test_get_ids
748
+ assert_equal projects(:active_record, :action_controller).map(&:id).sort, developers(:david).project_ids.sort
749
+ assert_equal [projects(:active_record).id], developers(:jamis).project_ids
750
+ end
751
+
752
+ def test_get_ids_for_loaded_associations
753
+ developer = developers(:david)
754
+ developer.projects.reload
755
+ assert_queries(0) do
756
+ developer.project_ids
757
+ developer.project_ids
758
+ end
759
+ end
760
+
761
+ def test_get_ids_for_unloaded_associations_does_not_load_them
762
+ developer = developers(:david)
763
+ assert !developer.projects.loaded?
764
+ assert_equal projects(:active_record, :action_controller).map(&:id).sort, developer.project_ids.sort
765
+ assert !developer.projects.loaded?
766
+ end
767
+
768
+ def test_assign_ids
769
+ developer = Developer.new("name" => "Joe")
770
+ developer.project_ids = projects(:active_record, :action_controller).map(&:id)
771
+ developer.save
772
+ developer.reload
773
+ assert_equal 2, developer.projects.length
774
+ assert_equal [projects(:active_record), projects(:action_controller)].map(&:id).sort, developer.project_ids.sort
775
+ end
776
+
777
+ def test_assign_ids_ignoring_blanks
778
+ developer = Developer.new("name" => "Joe")
779
+ developer.project_ids = [projects(:active_record).id, nil, projects(:action_controller).id, '']
780
+ developer.save
781
+ developer.reload
782
+ assert_equal 2, developer.projects.length
783
+ assert_equal [projects(:active_record), projects(:action_controller)].map(&:id).sort, developer.project_ids.sort
784
+ end
785
+
786
+ def test_scoped_find_on_through_association_doesnt_return_read_only_records
787
+ tag = Post.find(1).tags.find_by_name("General")
788
+
789
+ assert_nothing_raised do
790
+ tag.save!
791
+ end
792
+ end
793
+
794
+ def test_has_many_through_polymorphic_has_manys_works
795
+ assert_equal [10, 20].to_set, pirates(:redbeard).treasure_estimates.map(&:price).to_set
796
+ end
797
+
798
+ def test_symbols_as_keys
799
+ developer = DeveloperWithSymbolsForKeys.new(:name => 'David')
800
+ project = ProjectWithSymbolsForKeys.new(:name => 'Rails Testing')
801
+ project.developers << developer
802
+ project.save!
803
+
804
+ assert_equal 1, project.developers.size
805
+ assert_equal 1, developer.projects.size
806
+ assert_equal developer, project.developers.first
807
+ assert_equal project, developer.projects.first
808
+ end
809
+
810
+ def test_dynamic_find_should_respect_association_include
811
+ # SQL error in sort clause if :include is not included
812
+ # due to Unknown column 'authors.id'
813
+ assert Category.find(1).posts_with_authors_sorted_by_author_id.find_by_title('Welcome to the weblog')
814
+ end
815
+
816
+ def test_count
817
+ david = Developer.find(1)
818
+ assert_equal 2, david.projects.count
819
+ end
820
+
821
+ def test_association_proxy_transaction_method_starts_transaction_in_association_class
822
+ assert_called(Post, :transaction) do
823
+ Category.first.posts.transaction do
824
+ # nothing
825
+ end
826
+ end
827
+ end
828
+
829
+ def test_caching_of_columns
830
+ david = Developer.find(1)
831
+ # clear cache possibly created by other tests
832
+ david.projects.reset_column_information
833
+
834
+ assert_queries(:any) { david.projects.columns }
835
+ assert_no_queries { david.projects.columns }
836
+
837
+ ## and again to verify that reset_column_information clears the cache correctly
838
+ david.projects.reset_column_information
839
+
840
+ assert_queries(:any) { david.projects.columns }
841
+ assert_no_queries { david.projects.columns }
842
+ end
843
+
844
+ def test_attributes_are_being_set_when_initialized_from_habtm_association_with_where_clause
845
+ new_developer = projects(:action_controller).developers.where(:name => "Marcelo").build
846
+ assert_equal new_developer.name, "Marcelo"
847
+ end
848
+
849
+ def test_attributes_are_being_set_when_initialized_from_habtm_association_with_multiple_where_clauses
850
+ new_developer = projects(:action_controller).developers.where(:name => "Marcelo").where(:salary => 90_000).build
851
+ assert_equal new_developer.name, "Marcelo"
852
+ assert_equal new_developer.salary, 90_000
853
+ end
854
+
855
+ def test_include_method_in_has_and_belongs_to_many_association_should_return_true_for_instance_added_with_build
856
+ project = Project.new
857
+ developer = project.developers.build
858
+ assert project.developers.include?(developer)
859
+ end
860
+
861
+ def test_destruction_does_not_error_without_primary_key
862
+ redbeard = pirates(:redbeard)
863
+ george = parrots(:george)
864
+ redbeard.parrots << george
865
+ assert_equal 2, george.pirates.count
866
+ Pirate.includes(:parrots).where(parrot: redbeard.parrot).find(redbeard.id).destroy
867
+ assert_equal 1, george.pirates.count
868
+ assert_equal [], Pirate.where(id: redbeard.id)
869
+ end
870
+
871
+ def test_has_and_belongs_to_many_associations_on_new_records_use_null_relations
872
+ projects = Developer.new.projects
873
+ assert_no_queries(ignore_none: false) do
874
+ assert_equal [], projects
875
+ assert_equal [], projects.where(title: 'omg')
876
+ assert_equal [], projects.pluck(:title)
877
+ assert_equal 0, projects.count
878
+ end
879
+ end
880
+
881
+ def test_association_with_validate_false_does_not_run_associated_validation_callbacks_on_create
882
+ rich_person = RichPerson.new
883
+
884
+ treasure = Treasure.new
885
+ treasure.rich_people << rich_person
886
+ treasure.valid?
887
+
888
+ assert_equal 1, treasure.rich_people.size
889
+ assert_nil rich_person.first_name, 'should not run associated person validation on create when validate: false'
890
+ end
891
+
892
+ def test_association_with_validate_false_does_not_run_associated_validation_callbacks_on_update
893
+ rich_person = RichPerson.create!
894
+ person_first_name = rich_person.first_name
895
+ assert_not_nil person_first_name
896
+
897
+ treasure = Treasure.new
898
+ treasure.rich_people << rich_person
899
+ treasure.valid?
900
+
901
+ assert_equal 1, treasure.rich_people.size
902
+ assert_equal person_first_name, rich_person.first_name, 'should not run associated person validation on update when validate: false'
903
+ end
904
+
905
+ def test_custom_join_table
906
+ assert_equal 'edges', Vertex.reflect_on_association(:sources).join_table
907
+ end
908
+
909
+ def test_has_and_belongs_to_many_in_a_namespaced_model_pointing_to_a_namespaced_model
910
+ magazine = Publisher::Magazine.create
911
+ article = Publisher::Article.create
912
+ magazine.articles << article
913
+ magazine.save
914
+
915
+ assert_includes magazine.articles, article
916
+ end
917
+
918
+ def test_has_and_belongs_to_many_in_a_namespaced_model_pointing_to_a_non_namespaced_model
919
+ article = Publisher::Article.create
920
+ tag = Tag.create
921
+ article.tags << tag
922
+ article.save
923
+
924
+ assert_includes article.tags, tag
925
+ end
926
+
927
+ def test_redefine_habtm
928
+ child = SubDeveloper.new("name" => "Aredridel")
929
+ child.special_projects << SpecialProject.new("name" => "Special Project")
930
+ assert child.save, 'child object should be saved'
931
+ end
932
+
933
+ def test_habtm_with_reflection_using_class_name_and_fixtures
934
+ assert_not_nil Developer._reflections['shared_computers']
935
+ # Checking the fixture for named association is important here, because it's the only way
936
+ # we've been able to reproduce this bug
937
+ assert_not_nil File.read(File.expand_path("../../../fixtures/developers.yml", __FILE__)).index("shared_computers")
938
+ assert_equal developers(:david).shared_computers.first, computers(:laptop)
939
+ end
940
+
941
+ def test_with_symbol_class_name
942
+ assert_nothing_raised do
943
+ DeveloperWithSymbolClassName.new
944
+ end
945
+ end
946
+
947
+ def test_association_force_reload_with_only_true_is_deprecated
948
+ developer = Developer.find(1)
949
+
950
+ assert_deprecated { developer.projects(true) }
951
+ end
952
+
953
+ def test_alternate_database
954
+ professor = Professor.create(name: "Plum")
955
+ course = Course.create(name: "Forensics")
956
+ assert_equal 0, professor.courses.count
957
+ assert_nothing_raised do
958
+ professor.courses << course
959
+ end
960
+ assert_equal 1, professor.courses.count
961
+ end
962
+
963
+ def test_habtm_scope_can_unscope
964
+ project = ProjectUnscopingDavidDefaultScope.new
965
+ project.save!
966
+
967
+ developer = LazyBlockDeveloperCalledDavid.new(name: "Not David")
968
+ developer.save!
969
+ project.developers << developer
970
+
971
+ projects = ProjectUnscopingDavidDefaultScope.includes(:developers).where(id: project.id)
972
+ assert_equal 1, projects.first.developers.size
973
+ end
974
+
975
+ def test_preloaded_associations_size
976
+ assert_equal Project.first.salaried_developers.size,
977
+ Project.preload(:salaried_developers).first.salaried_developers.size
978
+
979
+ assert_equal Project.includes(:salaried_developers).references(:salaried_developers).first.salaried_developers.size,
980
+ Project.preload(:salaried_developers).first.salaried_developers.size
981
+
982
+ # Nested HATBM
983
+ first_project = Developer.first.projects.first
984
+ preloaded_first_project =
985
+ Developer.preload(projects: :salaried_developers).
986
+ first.
987
+ projects.
988
+ detect { |p| p.id == first_project.id }
989
+
990
+ assert preloaded_first_project.salaried_developers.loaded?, true
991
+ assert_equal first_project.salaried_developers.size, preloaded_first_project.salaried_developers.size
992
+ end
993
+
994
+ def test_has_and_belongs_to_many_is_useable_with_belongs_to_required_by_default
995
+ assert_difference "Project.first.developers_required_by_default.size", 1 do
996
+ Project.first.developers_required_by_default.create!(name: "Sean", salary: 50000)
997
+ end
998
+ end
999
+
1000
+ def test_association_name_is_the_same_as_join_table_name
1001
+ user = User.create!
1002
+ assert_nothing_raised { user.jobs_pool.clear }
1003
+ end
1004
+ end