ibm_db 4.0.0-x86-mingw32 → 5.1.0-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 (576) 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.h +3 -0
  9. data/ext/ibm_db-i386-mingw32.def +2 -0
  10. data/ext/ibm_db.c +11879 -11887
  11. data/ext/ibm_db.o +0 -0
  12. data/ext/ibm_db.so +0 -0
  13. data/ext/mkmf.log +110 -0
  14. data/ext/ruby_ibm_db.h +241 -241
  15. data/ext/ruby_ibm_db_cli.c +866 -866
  16. data/ext/ruby_ibm_db_cli.h +500 -500
  17. data/ext/ruby_ibm_db_cli.o +0 -0
  18. data/ext/unicode_support_version.h +3 -0
  19. data/init.rb +41 -41
  20. data/lib/IBM_DB.rb +27 -27
  21. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +3593 -3452
  22. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +5 -5
  23. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
  24. data/lib/mswin32/ibm_db.rb +94 -90
  25. data/lib/mswin32/rb2x/i386/ruby26/ibm_db.so +0 -0
  26. data/lib/mswin32/rb2x/i386/ruby27/ibm_db.so +0 -0
  27. data/test/active_record/connection_adapters/fake_adapter.rb +49 -49
  28. data/test/assets/example.log +1 -1
  29. data/test/assets/test.txt +1 -1
  30. data/test/cases/adapter_test.rb +351 -351
  31. data/test/cases/adapters/mysql2/active_schema_test.rb +193 -193
  32. data/test/cases/adapters/mysql2/bind_parameter_test.rb +50 -50
  33. data/test/cases/adapters/mysql2/boolean_test.rb +100 -100
  34. data/test/cases/adapters/mysql2/case_sensitivity_test.rb +63 -63
  35. data/test/cases/adapters/mysql2/charset_collation_test.rb +54 -54
  36. data/test/cases/adapters/mysql2/connection_test.rb +210 -210
  37. data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +45 -45
  38. data/test/cases/adapters/mysql2/enum_test.rb +26 -26
  39. data/test/cases/adapters/mysql2/explain_test.rb +21 -21
  40. data/test/cases/adapters/mysql2/json_test.rb +195 -195
  41. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +83 -83
  42. data/test/cases/adapters/mysql2/reserved_word_test.rb +152 -152
  43. data/test/cases/adapters/mysql2/schema_migrations_test.rb +59 -59
  44. data/test/cases/adapters/mysql2/schema_test.rb +126 -126
  45. data/test/cases/adapters/mysql2/sp_test.rb +36 -36
  46. data/test/cases/adapters/mysql2/sql_types_test.rb +14 -14
  47. data/test/cases/adapters/mysql2/table_options_test.rb +42 -42
  48. data/test/cases/adapters/mysql2/unsigned_type_test.rb +66 -66
  49. data/test/cases/adapters/postgresql/active_schema_test.rb +98 -98
  50. data/test/cases/adapters/postgresql/array_test.rb +339 -339
  51. data/test/cases/adapters/postgresql/bit_string_test.rb +82 -82
  52. data/test/cases/adapters/postgresql/bytea_test.rb +134 -134
  53. data/test/cases/adapters/postgresql/case_insensitive_test.rb +26 -26
  54. data/test/cases/adapters/postgresql/change_schema_test.rb +38 -38
  55. data/test/cases/adapters/postgresql/cidr_test.rb +25 -25
  56. data/test/cases/adapters/postgresql/citext_test.rb +78 -78
  57. data/test/cases/adapters/postgresql/collation_test.rb +53 -53
  58. data/test/cases/adapters/postgresql/composite_test.rb +132 -132
  59. data/test/cases/adapters/postgresql/connection_test.rb +257 -257
  60. data/test/cases/adapters/postgresql/datatype_test.rb +92 -92
  61. data/test/cases/adapters/postgresql/domain_test.rb +47 -47
  62. data/test/cases/adapters/postgresql/enum_test.rb +91 -91
  63. data/test/cases/adapters/postgresql/explain_test.rb +20 -20
  64. data/test/cases/adapters/postgresql/extension_migration_test.rb +63 -63
  65. data/test/cases/adapters/postgresql/full_text_test.rb +44 -44
  66. data/test/cases/adapters/postgresql/geometric_test.rb +378 -378
  67. data/test/cases/adapters/postgresql/hstore_test.rb +382 -382
  68. data/test/cases/adapters/postgresql/infinity_test.rb +69 -69
  69. data/test/cases/adapters/postgresql/integer_test.rb +25 -25
  70. data/test/cases/adapters/postgresql/json_test.rb +237 -237
  71. data/test/cases/adapters/postgresql/ltree_test.rb +53 -53
  72. data/test/cases/adapters/postgresql/money_test.rb +96 -96
  73. data/test/cases/adapters/postgresql/network_test.rb +94 -94
  74. data/test/cases/adapters/postgresql/numbers_test.rb +49 -49
  75. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +405 -405
  76. data/test/cases/adapters/postgresql/prepared_statements_test.rb +22 -22
  77. data/test/cases/adapters/postgresql/quoting_test.rb +44 -44
  78. data/test/cases/adapters/postgresql/range_test.rb +343 -343
  79. data/test/cases/adapters/postgresql/referential_integrity_test.rb +111 -111
  80. data/test/cases/adapters/postgresql/rename_table_test.rb +34 -34
  81. data/test/cases/adapters/postgresql/schema_authorization_test.rb +119 -119
  82. data/test/cases/adapters/postgresql/schema_test.rb +597 -597
  83. data/test/cases/adapters/postgresql/serial_test.rb +154 -154
  84. data/test/cases/adapters/postgresql/statement_pool_test.rb +41 -41
  85. data/test/cases/adapters/postgresql/timestamp_test.rb +90 -90
  86. data/test/cases/adapters/postgresql/type_lookup_test.rb +33 -33
  87. data/test/cases/adapters/postgresql/utils_test.rb +62 -62
  88. data/test/cases/adapters/postgresql/uuid_test.rb +294 -294
  89. data/test/cases/adapters/postgresql/xml_test.rb +54 -54
  90. data/test/cases/adapters/sqlite3/collation_test.rb +53 -53
  91. data/test/cases/adapters/sqlite3/copy_table_test.rb +98 -98
  92. data/test/cases/adapters/sqlite3/explain_test.rb +21 -21
  93. data/test/cases/adapters/sqlite3/quoting_test.rb +101 -101
  94. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +441 -441
  95. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +24 -24
  96. data/test/cases/adapters/sqlite3/statement_pool_test.rb +20 -20
  97. data/test/cases/aggregations_test.rb +168 -168
  98. data/test/cases/ar_schema_test.rb +146 -146
  99. data/test/cases/associations/association_scope_test.rb +16 -16
  100. data/test/cases/associations/belongs_to_associations_test.rb +1141 -1141
  101. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +41 -41
  102. data/test/cases/associations/callbacks_test.rb +190 -190
  103. data/test/cases/associations/cascaded_eager_loading_test.rb +188 -188
  104. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -36
  105. data/test/cases/associations/eager_load_nested_include_test.rb +126 -126
  106. data/test/cases/associations/eager_singularization_test.rb +148 -148
  107. data/test/cases/associations/eager_test.rb +1514 -1514
  108. data/test/cases/associations/extension_test.rb +87 -87
  109. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +1004 -1004
  110. data/test/cases/associations/has_many_associations_test.rb +2501 -2501
  111. data/test/cases/associations/has_many_through_associations_test.rb +1271 -1271
  112. data/test/cases/associations/has_one_associations_test.rb +707 -707
  113. data/test/cases/associations/has_one_through_associations_test.rb +383 -383
  114. data/test/cases/associations/inner_join_association_test.rb +139 -139
  115. data/test/cases/associations/inverse_associations_test.rb +733 -733
  116. data/test/cases/associations/join_model_test.rb +777 -777
  117. data/test/cases/associations/left_outer_join_association_test.rb +88 -88
  118. data/test/cases/associations/nested_through_associations_test.rb +579 -579
  119. data/test/cases/associations/required_test.rb +102 -102
  120. data/test/cases/associations_test.rb +385 -385
  121. data/test/cases/attribute_decorators_test.rb +126 -125
  122. data/test/cases/attribute_methods/read_test.rb +60 -60
  123. data/test/cases/attribute_methods_test.rb +1009 -1009
  124. data/test/cases/attribute_set_test.rb +270 -270
  125. data/test/cases/attribute_test.rb +246 -246
  126. data/test/cases/attributes_test.rb +253 -253
  127. data/test/cases/autosave_association_test.rb +1708 -1708
  128. data/test/cases/base_test.rb +1713 -1713
  129. data/test/cases/batches_test.rb +489 -489
  130. data/test/cases/binary_test.rb +44 -44
  131. data/test/cases/bind_parameter_test.rb +110 -110
  132. data/test/cases/cache_key_test.rb +26 -25
  133. data/test/cases/calculations_test.rb +798 -798
  134. data/test/cases/callbacks_test.rb +636 -636
  135. data/test/cases/clone_test.rb +40 -40
  136. data/test/cases/coders/json_test.rb +15 -15
  137. data/test/cases/coders/yaml_column_test.rb +63 -63
  138. data/test/cases/collection_cache_key_test.rb +115 -115
  139. data/test/cases/column_alias_test.rb +17 -17
  140. data/test/cases/column_definition_test.rb +92 -92
  141. data/test/cases/comment_test.rb +145 -143
  142. data/test/cases/connection_adapters/adapter_leasing_test.rb +56 -56
  143. data/test/cases/connection_adapters/connection_handler_test.rb +160 -160
  144. data/test/cases/connection_adapters/connection_specification_test.rb +12 -12
  145. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +255 -255
  146. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +69 -69
  147. data/test/cases/connection_adapters/quoting_test.rb +13 -13
  148. data/test/cases/connection_adapters/schema_cache_test.rb +61 -61
  149. data/test/cases/connection_adapters/type_lookup_test.rb +118 -118
  150. data/test/cases/connection_management_test.rb +112 -112
  151. data/test/cases/connection_pool_test.rb +521 -521
  152. data/test/cases/connection_specification/resolver_test.rb +131 -131
  153. data/test/cases/core_test.rb +112 -112
  154. data/test/cases/counter_cache_test.rb +214 -214
  155. data/test/cases/custom_locking_test.rb +17 -17
  156. data/test/cases/database_statements_test.rb +34 -34
  157. data/test/cases/date_test.rb +44 -44
  158. data/test/cases/date_time_precision_test.rb +107 -106
  159. data/test/cases/date_time_test.rb +61 -61
  160. data/test/cases/defaults_test.rb +219 -218
  161. data/test/cases/dirty_test.rb +763 -763
  162. data/test/cases/disconnected_test.rb +30 -30
  163. data/test/cases/dup_test.rb +157 -157
  164. data/test/cases/enum_test.rb +444 -444
  165. data/test/cases/errors_test.rb +16 -16
  166. data/test/cases/explain_subscriber_test.rb +64 -64
  167. data/test/cases/explain_test.rb +87 -87
  168. data/test/cases/finder_respond_to_test.rb +60 -60
  169. data/test/cases/finder_test.rb +1294 -1294
  170. data/test/cases/fixture_set/file_test.rb +156 -156
  171. data/test/cases/fixtures_test.rb +988 -988
  172. data/test/cases/forbidden_attributes_protection_test.rb +165 -165
  173. data/test/cases/habtm_destroy_order_test.rb +61 -61
  174. data/test/cases/helper.rb +204 -204
  175. data/test/cases/hot_compatibility_test.rb +142 -142
  176. data/test/cases/i18n_test.rb +45 -45
  177. data/test/cases/inheritance_test.rb +606 -606
  178. data/test/cases/integration_test.rb +155 -155
  179. data/test/cases/invalid_connection_test.rb +24 -24
  180. data/test/cases/invertible_migration_test.rb +387 -387
  181. data/test/cases/json_serialization_test.rb +311 -311
  182. data/test/cases/locking_test.rb +493 -493
  183. data/test/cases/log_subscriber_test.rb +225 -225
  184. data/test/cases/migration/change_schema_test.rb +458 -458
  185. data/test/cases/migration/change_table_test.rb +256 -256
  186. data/test/cases/migration/column_attributes_test.rb +176 -176
  187. data/test/cases/migration/column_positioning_test.rb +56 -56
  188. data/test/cases/migration/columns_test.rb +310 -310
  189. data/test/cases/migration/command_recorder_test.rb +350 -350
  190. data/test/cases/migration/compatibility_test.rb +118 -118
  191. data/test/cases/migration/create_join_table_test.rb +157 -157
  192. data/test/cases/migration/foreign_key_test.rb +362 -360
  193. data/test/cases/migration/helper.rb +39 -39
  194. data/test/cases/migration/index_test.rb +218 -218
  195. data/test/cases/migration/logger_test.rb +36 -36
  196. data/test/cases/migration/pending_migrations_test.rb +52 -52
  197. data/test/cases/migration/references_foreign_key_test.rb +221 -216
  198. data/test/cases/migration/references_index_test.rb +101 -101
  199. data/test/cases/migration/references_statements_test.rb +136 -136
  200. data/test/cases/migration/rename_table_test.rb +93 -93
  201. data/test/cases/migration_test.rb +1157 -1157
  202. data/test/cases/migrator_test.rb +471 -470
  203. data/test/cases/mixin_test.rb +68 -68
  204. data/test/cases/modules_test.rb +172 -172
  205. data/test/cases/multiparameter_attributes_test.rb +372 -372
  206. data/test/cases/multiple_db_test.rb +122 -122
  207. data/test/cases/nested_attributes_test.rb +1098 -1098
  208. data/test/cases/nested_attributes_with_callbacks_test.rb +144 -144
  209. data/test/cases/persistence_test.rb +1001 -1001
  210. data/test/cases/pooled_connections_test.rb +81 -81
  211. data/test/cases/primary_keys_test.rb +376 -376
  212. data/test/cases/query_cache_test.rb +446 -446
  213. data/test/cases/quoting_test.rb +202 -202
  214. data/test/cases/readonly_test.rb +119 -119
  215. data/test/cases/reaper_test.rb +85 -85
  216. data/test/cases/reflection_test.rb +509 -509
  217. data/test/cases/relation/delegation_test.rb +63 -63
  218. data/test/cases/relation/merging_test.rb +157 -157
  219. data/test/cases/relation/mutation_test.rb +183 -183
  220. data/test/cases/relation/or_test.rb +92 -92
  221. data/test/cases/relation/predicate_builder_test.rb +16 -16
  222. data/test/cases/relation/record_fetch_warning_test.rb +40 -40
  223. data/test/cases/relation/where_chain_test.rb +105 -105
  224. data/test/cases/relation/where_clause_test.rb +182 -182
  225. data/test/cases/relation/where_test.rb +322 -322
  226. data/test/cases/relation_test.rb +328 -328
  227. data/test/cases/relations_test.rb +2026 -2026
  228. data/test/cases/reload_models_test.rb +22 -22
  229. data/test/cases/result_test.rb +90 -90
  230. data/test/cases/sanitize_test.rb +176 -176
  231. data/test/cases/schema_dumper_test.rb +457 -457
  232. data/test/cases/schema_loading_test.rb +52 -52
  233. data/test/cases/scoping/default_scoping_test.rb +528 -528
  234. data/test/cases/scoping/named_scoping_test.rb +561 -561
  235. data/test/cases/scoping/relation_scoping_test.rb +400 -400
  236. data/test/cases/secure_token_test.rb +32 -32
  237. data/test/cases/serialization_test.rb +104 -104
  238. data/test/cases/serialized_attribute_test.rb +364 -364
  239. data/test/cases/statement_cache_test.rb +136 -136
  240. data/test/cases/store_test.rb +195 -195
  241. data/test/cases/suppressor_test.rb +63 -63
  242. data/test/cases/tasks/database_tasks_test.rb +462 -462
  243. data/test/cases/tasks/mysql_rake_test.rb +345 -345
  244. data/test/cases/tasks/postgresql_rake_test.rb +304 -304
  245. data/test/cases/tasks/sqlite_rake_test.rb +220 -220
  246. data/test/cases/test_case.rb +131 -131
  247. data/test/cases/test_fixtures_test.rb +36 -36
  248. data/test/cases/time_precision_test.rb +103 -102
  249. data/test/cases/timestamp_test.rb +501 -501
  250. data/test/cases/touch_later_test.rb +121 -121
  251. data/test/cases/transaction_callbacks_test.rb +518 -518
  252. data/test/cases/transaction_isolation_test.rb +106 -106
  253. data/test/cases/transactions_test.rb +835 -834
  254. data/test/cases/type/adapter_specific_registry_test.rb +133 -133
  255. data/test/cases/type/date_time_test.rb +14 -14
  256. data/test/cases/type/integer_test.rb +27 -27
  257. data/test/cases/type/string_test.rb +22 -22
  258. data/test/cases/type/type_map_test.rb +177 -177
  259. data/test/cases/type_test.rb +39 -39
  260. data/test/cases/types_test.rb +24 -24
  261. data/test/cases/unconnected_test.rb +33 -33
  262. data/test/cases/validations/absence_validation_test.rb +73 -73
  263. data/test/cases/validations/association_validation_test.rb +97 -97
  264. data/test/cases/validations/i18n_generate_message_validation_test.rb +84 -84
  265. data/test/cases/validations/i18n_validation_test.rb +86 -86
  266. data/test/cases/validations/length_validation_test.rb +79 -79
  267. data/test/cases/validations/presence_validation_test.rb +103 -103
  268. data/test/cases/validations/uniqueness_validation_test.rb +548 -548
  269. data/test/cases/validations_repair_helper.rb +19 -19
  270. data/test/cases/validations_test.rb +194 -194
  271. data/test/cases/view_test.rb +216 -216
  272. data/test/cases/yaml_serialization_test.rb +121 -121
  273. data/test/config.example.yml +97 -97
  274. data/test/config.rb +5 -5
  275. data/test/connections/native_ibm_db/connection.rb +44 -0
  276. data/test/fixtures/accounts.yml +29 -29
  277. data/test/fixtures/admin/accounts.yml +2 -2
  278. data/test/fixtures/admin/users.yml +10 -10
  279. data/test/fixtures/author_addresses.yml +17 -17
  280. data/test/fixtures/author_favorites.yml +3 -3
  281. data/test/fixtures/authors.yml +23 -23
  282. data/test/fixtures/bad_posts.yml +9 -9
  283. data/test/fixtures/binaries.yml +133 -133
  284. data/test/fixtures/books.yml +31 -31
  285. data/test/fixtures/bulbs.yml +5 -5
  286. data/test/fixtures/cars.yml +9 -9
  287. data/test/fixtures/categories.yml +19 -19
  288. data/test/fixtures/categories/special_categories.yml +9 -9
  289. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -4
  290. data/test/fixtures/categories_ordered.yml +7 -7
  291. data/test/fixtures/categories_posts.yml +31 -31
  292. data/test/fixtures/categorizations.yml +23 -23
  293. data/test/fixtures/clubs.yml +8 -8
  294. data/test/fixtures/collections.yml +3 -3
  295. data/test/fixtures/colleges.yml +3 -3
  296. data/test/fixtures/comments.yml +65 -65
  297. data/test/fixtures/companies.yml +67 -67
  298. data/test/fixtures/computers.yml +10 -10
  299. data/test/fixtures/content.yml +3 -3
  300. data/test/fixtures/content_positions.yml +3 -3
  301. data/test/fixtures/courses.yml +8 -8
  302. data/test/fixtures/customers.yml +25 -25
  303. data/test/fixtures/dashboards.yml +6 -6
  304. data/test/fixtures/dead_parrots.yml +5 -5
  305. data/test/fixtures/developers.yml +22 -22
  306. data/test/fixtures/developers_projects.yml +16 -16
  307. data/test/fixtures/dog_lovers.yml +7 -7
  308. data/test/fixtures/dogs.yml +4 -4
  309. data/test/fixtures/doubloons.yml +3 -3
  310. data/test/fixtures/edges.yml +5 -5
  311. data/test/fixtures/entrants.yml +14 -14
  312. data/test/fixtures/essays.yml +6 -6
  313. data/test/fixtures/faces.yml +11 -11
  314. data/test/fixtures/fk_test_has_fk.yml +3 -3
  315. data/test/fixtures/fk_test_has_pk.yml +1 -1
  316. data/test/fixtures/friendships.yml +4 -4
  317. data/test/fixtures/funny_jokes.yml +10 -10
  318. data/test/fixtures/interests.yml +33 -33
  319. data/test/fixtures/items.yml +3 -3
  320. data/test/fixtures/jobs.yml +7 -7
  321. data/test/fixtures/legacy_things.yml +3 -3
  322. data/test/fixtures/live_parrots.yml +4 -4
  323. data/test/fixtures/mateys.yml +4 -4
  324. data/test/fixtures/member_details.yml +8 -8
  325. data/test/fixtures/member_types.yml +6 -6
  326. data/test/fixtures/members.yml +11 -11
  327. data/test/fixtures/memberships.yml +34 -34
  328. data/test/fixtures/men.yml +5 -5
  329. data/test/fixtures/minimalistics.yml +2 -2
  330. data/test/fixtures/minivans.yml +5 -5
  331. data/test/fixtures/mixed_case_monkeys.yml +6 -6
  332. data/test/fixtures/mixins.yml +29 -29
  333. data/test/fixtures/movies.yml +7 -7
  334. data/test/fixtures/naked/yml/accounts.yml +1 -1
  335. data/test/fixtures/naked/yml/companies.yml +1 -1
  336. data/test/fixtures/naked/yml/courses.yml +1 -1
  337. data/test/fixtures/naked/yml/parrots.yml +2 -2
  338. data/test/fixtures/naked/yml/trees.yml +3 -3
  339. data/test/fixtures/nodes.yml +29 -29
  340. data/test/fixtures/organizations.yml +5 -5
  341. data/test/fixtures/other_comments.yml +6 -6
  342. data/test/fixtures/other_dogs.yml +2 -2
  343. data/test/fixtures/other_posts.yml +7 -7
  344. data/test/fixtures/other_topics.yml +42 -42
  345. data/test/fixtures/owners.yml +9 -9
  346. data/test/fixtures/parrots.yml +27 -27
  347. data/test/fixtures/parrots_pirates.yml +7 -7
  348. data/test/fixtures/people.yml +24 -24
  349. data/test/fixtures/peoples_treasures.yml +3 -3
  350. data/test/fixtures/pets.yml +19 -19
  351. data/test/fixtures/pirates.yml +12 -15
  352. data/test/fixtures/posts.yml +80 -80
  353. data/test/fixtures/price_estimates.yml +16 -16
  354. data/test/fixtures/products.yml +4 -4
  355. data/test/fixtures/projects.yml +7 -7
  356. data/test/fixtures/ratings.yml +14 -14
  357. data/test/fixtures/readers.yml +11 -11
  358. data/test/fixtures/references.yml +17 -17
  359. data/test/fixtures/reserved_words/distinct.yml +5 -5
  360. data/test/fixtures/reserved_words/distinct_select.yml +11 -11
  361. data/test/fixtures/reserved_words/group.yml +14 -14
  362. data/test/fixtures/reserved_words/select.yml +8 -8
  363. data/test/fixtures/reserved_words/values.yml +7 -7
  364. data/test/fixtures/ships.yml +6 -6
  365. data/test/fixtures/speedometers.yml +8 -8
  366. data/test/fixtures/sponsors.yml +12 -12
  367. data/test/fixtures/string_key_objects.yml +7 -7
  368. data/test/fixtures/subscribers.yml +10 -10
  369. data/test/fixtures/subscriptions.yml +12 -12
  370. data/test/fixtures/taggings.yml +78 -78
  371. data/test/fixtures/tags.yml +11 -11
  372. data/test/fixtures/tasks.yml +7 -7
  373. data/test/fixtures/teapots.yml +3 -3
  374. data/test/fixtures/to_be_linked/accounts.yml +2 -2
  375. data/test/fixtures/to_be_linked/users.yml +10 -10
  376. data/test/fixtures/topics.yml +49 -49
  377. data/test/fixtures/toys.yml +14 -14
  378. data/test/fixtures/traffic_lights.yml +9 -9
  379. data/test/fixtures/treasures.yml +10 -10
  380. data/test/fixtures/trees.yml +3 -3
  381. data/test/fixtures/uuid_children.yml +3 -3
  382. data/test/fixtures/uuid_parents.yml +2 -2
  383. data/test/fixtures/variants.yml +4 -4
  384. data/test/fixtures/vegetables.yml +19 -19
  385. data/test/fixtures/vertices.yml +3 -3
  386. data/test/fixtures/warehouse_things.yml +2 -2
  387. data/test/fixtures/zines.yml +5 -5
  388. data/test/migrations/10_urban/9_add_expressions.rb +11 -11
  389. data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -15
  390. data/test/migrations/magic/1_currencies_have_symbols.rb +12 -12
  391. data/test/migrations/missing/1000_people_have_middle_names.rb +9 -9
  392. data/test/migrations/missing/1_people_have_last_names.rb +9 -9
  393. data/test/migrations/missing/3_we_need_reminders.rb +12 -12
  394. data/test/migrations/missing/4_innocent_jointable.rb +12 -12
  395. data/test/migrations/rename/1_we_need_things.rb +11 -11
  396. data/test/migrations/rename/2_rename_things.rb +9 -9
  397. data/test/migrations/to_copy/1_people_have_hobbies.rb +9 -9
  398. data/test/migrations/to_copy/2_people_have_descriptions.rb +9 -9
  399. data/test/migrations/to_copy2/1_create_articles.rb +7 -7
  400. data/test/migrations/to_copy2/2_create_comments.rb +7 -7
  401. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +9 -9
  402. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +9 -9
  403. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +9 -9
  404. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +7 -7
  405. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +7 -7
  406. data/test/migrations/valid/1_valid_people_have_last_names.rb +9 -9
  407. data/test/migrations/valid/2_we_need_reminders.rb +12 -12
  408. data/test/migrations/valid/3_innocent_jointable.rb +12 -12
  409. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +9 -9
  410. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +12 -12
  411. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +12 -12
  412. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +9 -9
  413. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +12 -12
  414. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +12 -12
  415. data/test/migrations/version_check/20131219224947_migration_version_check.rb +8 -8
  416. data/test/models/admin.rb +5 -5
  417. data/test/models/admin/account.rb +3 -3
  418. data/test/models/admin/user.rb +40 -40
  419. data/test/models/aircraft.rb +5 -5
  420. data/test/models/arunit2_model.rb +3 -3
  421. data/test/models/author.rb +209 -209
  422. data/test/models/auto_id.rb +4 -4
  423. data/test/models/autoloadable/extra_firm.rb +2 -2
  424. data/test/models/binary.rb +2 -2
  425. data/test/models/bird.rb +12 -12
  426. data/test/models/book.rb +23 -23
  427. data/test/models/boolean.rb +2 -2
  428. data/test/models/bulb.rb +52 -52
  429. data/test/models/cake_designer.rb +3 -3
  430. data/test/models/car.rb +29 -29
  431. data/test/models/carrier.rb +2 -2
  432. data/test/models/cat.rb +10 -10
  433. data/test/models/categorization.rb +19 -19
  434. data/test/models/category.rb +35 -35
  435. data/test/models/chef.rb +8 -8
  436. data/test/models/citation.rb +3 -3
  437. data/test/models/club.rb +25 -25
  438. data/test/models/college.rb +10 -10
  439. data/test/models/column.rb +3 -3
  440. data/test/models/column_name.rb +3 -3
  441. data/test/models/comment.rb +76 -76
  442. data/test/models/company.rb +230 -230
  443. data/test/models/company_in_module.rb +98 -98
  444. data/test/models/computer.rb +3 -3
  445. data/test/models/contact.rb +41 -41
  446. data/test/models/content.rb +40 -40
  447. data/test/models/contract.rb +20 -20
  448. data/test/models/country.rb +7 -7
  449. data/test/models/course.rb +6 -6
  450. data/test/models/customer.rb +83 -83
  451. data/test/models/customer_carrier.rb +14 -14
  452. data/test/models/dashboard.rb +3 -3
  453. data/test/models/default.rb +2 -2
  454. data/test/models/department.rb +4 -4
  455. data/test/models/developer.rb +274 -274
  456. data/test/models/dog.rb +5 -5
  457. data/test/models/dog_lover.rb +5 -5
  458. data/test/models/doubloon.rb +12 -12
  459. data/test/models/drink_designer.rb +3 -3
  460. data/test/models/edge.rb +5 -5
  461. data/test/models/electron.rb +5 -5
  462. data/test/models/engine.rb +4 -4
  463. data/test/models/entrant.rb +3 -3
  464. data/test/models/essay.rb +5 -5
  465. data/test/models/event.rb +3 -3
  466. data/test/models/eye.rb +37 -37
  467. data/test/models/face.rb +9 -9
  468. data/test/models/friendship.rb +6 -6
  469. data/test/models/guid.rb +2 -2
  470. data/test/models/guitar.rb +4 -4
  471. data/test/models/hotel.rb +11 -11
  472. data/test/models/image.rb +3 -3
  473. data/test/models/interest.rb +5 -5
  474. data/test/models/invoice.rb +4 -4
  475. data/test/models/item.rb +7 -7
  476. data/test/models/job.rb +7 -7
  477. data/test/models/joke.rb +7 -7
  478. data/test/models/keyboard.rb +3 -3
  479. data/test/models/legacy_thing.rb +3 -3
  480. data/test/models/lesson.rb +11 -11
  481. data/test/models/line_item.rb +3 -3
  482. data/test/models/liquid.rb +4 -4
  483. data/test/models/man.rb +11 -11
  484. data/test/models/matey.rb +4 -4
  485. data/test/models/member.rb +42 -42
  486. data/test/models/member_detail.rb +8 -8
  487. data/test/models/member_type.rb +3 -3
  488. data/test/models/membership.rb +35 -35
  489. data/test/models/mentor.rb +2 -2
  490. data/test/models/minimalistic.rb +2 -2
  491. data/test/models/minivan.rb +9 -9
  492. data/test/models/mixed_case_monkey.rb +3 -3
  493. data/test/models/mocktail_designer.rb +2 -2
  494. data/test/models/molecule.rb +6 -6
  495. data/test/models/movie.rb +5 -5
  496. data/test/models/node.rb +5 -5
  497. data/test/models/non_primary_key.rb +2 -2
  498. data/test/models/notification.rb +3 -3
  499. data/test/models/order.rb +4 -4
  500. data/test/models/organization.rb +14 -14
  501. data/test/models/other_dog.rb +5 -5
  502. data/test/models/owner.rb +37 -37
  503. data/test/models/parrot.rb +28 -28
  504. data/test/models/person.rb +142 -142
  505. data/test/models/personal_legacy_thing.rb +4 -4
  506. data/test/models/pet.rb +18 -18
  507. data/test/models/pet_treasure.rb +6 -6
  508. data/test/models/pirate.rb +92 -92
  509. data/test/models/possession.rb +3 -3
  510. data/test/models/post.rb +273 -273
  511. data/test/models/price_estimate.rb +4 -4
  512. data/test/models/professor.rb +5 -5
  513. data/test/models/project.rb +40 -40
  514. data/test/models/publisher.rb +2 -2
  515. data/test/models/publisher/article.rb +4 -4
  516. data/test/models/publisher/magazine.rb +3 -3
  517. data/test/models/rating.rb +4 -4
  518. data/test/models/reader.rb +23 -23
  519. data/test/models/recipe.rb +3 -3
  520. data/test/models/record.rb +2 -2
  521. data/test/models/reference.rb +22 -22
  522. data/test/models/reply.rb +61 -61
  523. data/test/models/ship.rb +39 -39
  524. data/test/models/ship_part.rb +8 -8
  525. data/test/models/shop.rb +17 -17
  526. data/test/models/shop_account.rb +6 -6
  527. data/test/models/speedometer.rb +6 -6
  528. data/test/models/sponsor.rb +7 -7
  529. data/test/models/string_key_object.rb +3 -3
  530. data/test/models/student.rb +4 -4
  531. data/test/models/subject.rb +16 -16
  532. data/test/models/subscriber.rb +8 -8
  533. data/test/models/subscription.rb +4 -4
  534. data/test/models/tag.rb +13 -13
  535. data/test/models/tagging.rb +13 -13
  536. data/test/models/task.rb +5 -5
  537. data/test/models/topic.rb +118 -118
  538. data/test/models/toy.rb +6 -6
  539. data/test/models/traffic_light.rb +4 -4
  540. data/test/models/treasure.rb +14 -14
  541. data/test/models/treaty.rb +7 -7
  542. data/test/models/tree.rb +3 -3
  543. data/test/models/tuning_peg.rb +4 -4
  544. data/test/models/tyre.rb +11 -11
  545. data/test/models/user.rb +14 -14
  546. data/test/models/uuid_child.rb +3 -3
  547. data/test/models/uuid_item.rb +6 -6
  548. data/test/models/uuid_parent.rb +3 -3
  549. data/test/models/vegetables.rb +24 -24
  550. data/test/models/vehicle.rb +6 -6
  551. data/test/models/vertex.rb +9 -9
  552. data/test/models/warehouse_thing.rb +5 -5
  553. data/test/models/wheel.rb +3 -3
  554. data/test/models/without_table.rb +3 -3
  555. data/test/models/zine.rb +3 -3
  556. data/test/schema/i5/ibm_db_specific_schema.rb +137 -0
  557. data/test/schema/ids/ibm_db_specific_schema.rb +140 -0
  558. data/test/schema/luw/ibm_db_specific_schema.rb +137 -0
  559. data/test/schema/mysql2_specific_schema.rb +68 -68
  560. data/test/schema/oracle_specific_schema.rb +40 -40
  561. data/test/schema/postgresql_specific_schema.rb +114 -114
  562. data/test/schema/schema.rb +1057 -1057
  563. data/test/schema/schema.rb.original +1057 -1057
  564. data/test/schema/sqlite_specific_schema.rb +18 -18
  565. data/test/schema/zOS/ibm_db_specific_schema.rb +208 -0
  566. data/test/support/config.rb +43 -43
  567. data/test/support/connection.rb +23 -23
  568. data/test/support/connection_helper.rb +14 -14
  569. data/test/support/ddl_helper.rb +8 -8
  570. data/test/support/schema_dumping_helper.rb +20 -20
  571. data/test/support/yaml_compatibility_fixtures/rails_4_1.yml +22 -22
  572. data/test/support/yaml_compatibility_fixtures/rails_4_2_0.yml +182 -182
  573. metadata +30 -14
  574. data/lib/mswin32/rb2x/i386/ibm_db.so +0 -0
  575. data/test/fixtures/author_addresses.original +0 -11
  576. 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