ibm_db 3.0.5-x86-mingw32 → 4.0.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 (586) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +4 -0
  3. data/LICENSE +1 -1
  4. data/MANIFEST +14 -14
  5. data/ParameterizedQueries README +6 -6
  6. data/README +208 -225
  7. data/ext/Makefile.nt32 +181 -181
  8. data/ext/Makefile.nt32.191 +212 -212
  9. data/ext/extconf.rb +291 -291
  10. data/ext/ibm_db.c +11887 -11887
  11. data/ext/ruby_ibm_db.h +241 -241
  12. data/ext/ruby_ibm_db_cli.c +866 -866
  13. data/ext/ruby_ibm_db_cli.h +500 -500
  14. data/init.rb +41 -41
  15. data/lib/IBM_DB.rb +27 -27
  16. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +3452 -3177
  17. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +5 -2
  18. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
  19. data/lib/mswin32/ibm_db.rb +91 -123
  20. data/lib/mswin32/rb2x/i386/ibm_db.so +0 -0
  21. data/test/active_record/connection_adapters/fake_adapter.rb +49 -46
  22. data/test/assets/example.log +1 -1
  23. data/test/assets/test.txt +1 -1
  24. data/test/cases/adapter_test.rb +351 -276
  25. data/test/cases/adapters/mysql2/active_schema_test.rb +193 -0
  26. data/test/cases/adapters/mysql2/bind_parameter_test.rb +50 -0
  27. data/test/cases/adapters/mysql2/boolean_test.rb +100 -0
  28. data/test/cases/adapters/mysql2/case_sensitivity_test.rb +63 -0
  29. data/test/cases/adapters/mysql2/charset_collation_test.rb +54 -0
  30. data/test/cases/adapters/mysql2/connection_test.rb +210 -0
  31. data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +45 -0
  32. data/test/cases/adapters/mysql2/enum_test.rb +26 -0
  33. data/test/cases/adapters/mysql2/explain_test.rb +21 -0
  34. data/test/cases/adapters/mysql2/json_test.rb +195 -0
  35. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +83 -0
  36. data/test/cases/adapters/mysql2/reserved_word_test.rb +152 -0
  37. data/test/cases/adapters/mysql2/schema_migrations_test.rb +59 -0
  38. data/test/cases/adapters/mysql2/schema_test.rb +126 -0
  39. data/test/cases/adapters/mysql2/sp_test.rb +36 -0
  40. data/test/cases/adapters/mysql2/sql_types_test.rb +14 -0
  41. data/test/cases/adapters/mysql2/table_options_test.rb +42 -0
  42. data/test/cases/adapters/mysql2/unsigned_type_test.rb +66 -0
  43. data/test/cases/adapters/postgresql/active_schema_test.rb +98 -0
  44. data/test/cases/adapters/postgresql/array_test.rb +339 -0
  45. data/test/cases/adapters/postgresql/bit_string_test.rb +82 -0
  46. data/test/cases/adapters/postgresql/bytea_test.rb +134 -0
  47. data/test/cases/adapters/postgresql/case_insensitive_test.rb +26 -0
  48. data/test/cases/adapters/postgresql/change_schema_test.rb +38 -0
  49. data/test/cases/adapters/postgresql/cidr_test.rb +25 -0
  50. data/test/cases/adapters/postgresql/citext_test.rb +78 -0
  51. data/test/cases/adapters/postgresql/collation_test.rb +53 -0
  52. data/test/cases/adapters/postgresql/composite_test.rb +132 -0
  53. data/test/cases/adapters/postgresql/connection_test.rb +257 -0
  54. data/test/cases/adapters/postgresql/datatype_test.rb +92 -0
  55. data/test/cases/adapters/postgresql/domain_test.rb +47 -0
  56. data/test/cases/adapters/postgresql/enum_test.rb +91 -0
  57. data/test/cases/adapters/postgresql/explain_test.rb +20 -0
  58. data/test/cases/adapters/postgresql/extension_migration_test.rb +63 -0
  59. data/test/cases/adapters/postgresql/full_text_test.rb +44 -0
  60. data/test/cases/adapters/postgresql/geometric_test.rb +378 -0
  61. data/test/cases/adapters/postgresql/hstore_test.rb +382 -0
  62. data/test/cases/adapters/postgresql/infinity_test.rb +69 -0
  63. data/test/cases/adapters/postgresql/integer_test.rb +25 -0
  64. data/test/cases/adapters/postgresql/json_test.rb +237 -0
  65. data/test/cases/adapters/postgresql/ltree_test.rb +53 -0
  66. data/test/cases/adapters/postgresql/money_test.rb +96 -0
  67. data/test/cases/adapters/postgresql/network_test.rb +94 -0
  68. data/test/cases/adapters/postgresql/numbers_test.rb +49 -0
  69. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +405 -0
  70. data/test/cases/adapters/postgresql/prepared_statements_test.rb +22 -0
  71. data/test/cases/adapters/postgresql/quoting_test.rb +44 -0
  72. data/test/cases/adapters/postgresql/range_test.rb +343 -0
  73. data/test/cases/adapters/postgresql/referential_integrity_test.rb +111 -0
  74. data/test/cases/adapters/postgresql/rename_table_test.rb +34 -0
  75. data/test/cases/adapters/postgresql/schema_authorization_test.rb +119 -0
  76. data/test/cases/adapters/postgresql/schema_test.rb +597 -0
  77. data/test/cases/adapters/postgresql/serial_test.rb +154 -0
  78. data/test/cases/adapters/postgresql/statement_pool_test.rb +41 -0
  79. data/test/cases/adapters/postgresql/timestamp_test.rb +90 -0
  80. data/test/cases/adapters/postgresql/type_lookup_test.rb +33 -0
  81. data/test/cases/adapters/postgresql/utils_test.rb +62 -0
  82. data/test/cases/adapters/postgresql/uuid_test.rb +294 -0
  83. data/test/cases/adapters/postgresql/xml_test.rb +54 -0
  84. data/test/cases/adapters/sqlite3/collation_test.rb +53 -0
  85. data/test/cases/adapters/sqlite3/copy_table_test.rb +98 -0
  86. data/test/cases/adapters/sqlite3/explain_test.rb +21 -0
  87. data/test/cases/adapters/sqlite3/quoting_test.rb +101 -0
  88. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +441 -0
  89. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +24 -0
  90. data/test/cases/adapters/sqlite3/statement_pool_test.rb +20 -0
  91. data/test/cases/aggregations_test.rb +168 -158
  92. data/test/cases/ar_schema_test.rb +146 -161
  93. data/test/cases/associations/association_scope_test.rb +16 -21
  94. data/test/cases/associations/belongs_to_associations_test.rb +1141 -1029
  95. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +41 -0
  96. data/test/cases/associations/callbacks_test.rb +190 -192
  97. data/test/cases/associations/cascaded_eager_loading_test.rb +188 -188
  98. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -36
  99. data/test/cases/associations/eager_load_nested_include_test.rb +126 -128
  100. data/test/cases/associations/eager_singularization_test.rb +148 -148
  101. data/test/cases/associations/eager_test.rb +1514 -1429
  102. data/test/cases/associations/extension_test.rb +87 -82
  103. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +1004 -972
  104. data/test/cases/associations/has_many_associations_test.rb +2501 -2182
  105. data/test/cases/associations/has_many_through_associations_test.rb +1271 -1204
  106. data/test/cases/associations/has_one_associations_test.rb +707 -610
  107. data/test/cases/associations/has_one_through_associations_test.rb +383 -380
  108. data/test/cases/associations/inner_join_association_test.rb +139 -139
  109. data/test/cases/associations/inverse_associations_test.rb +733 -706
  110. data/test/cases/associations/join_model_test.rb +777 -754
  111. data/test/cases/associations/left_outer_join_association_test.rb +88 -0
  112. data/test/cases/associations/nested_through_associations_test.rb +579 -579
  113. data/test/cases/associations/required_test.rb +102 -82
  114. data/test/cases/associations_test.rb +385 -380
  115. data/test/cases/attribute_decorators_test.rb +125 -125
  116. data/test/cases/attribute_methods/read_test.rb +60 -60
  117. data/test/cases/attribute_methods_test.rb +1009 -952
  118. data/test/cases/attribute_set_test.rb +270 -210
  119. data/test/cases/attribute_test.rb +246 -180
  120. data/test/cases/attributes_test.rb +253 -136
  121. data/test/cases/autosave_association_test.rb +1708 -1595
  122. data/test/cases/base_test.rb +1713 -1664
  123. data/test/cases/batches_test.rb +489 -212
  124. data/test/cases/binary_test.rb +44 -52
  125. data/test/cases/bind_parameter_test.rb +110 -100
  126. data/test/cases/cache_key_test.rb +25 -0
  127. data/test/cases/calculations_test.rb +798 -646
  128. data/test/cases/callbacks_test.rb +636 -543
  129. data/test/cases/clone_test.rb +40 -40
  130. data/test/cases/coders/json_test.rb +15 -0
  131. data/test/cases/coders/yaml_column_test.rb +63 -63
  132. data/test/cases/collection_cache_key_test.rb +115 -0
  133. data/test/cases/column_alias_test.rb +17 -17
  134. data/test/cases/column_definition_test.rb +92 -123
  135. data/test/cases/comment_test.rb +143 -0
  136. data/test/cases/connection_adapters/adapter_leasing_test.rb +56 -54
  137. data/test/cases/connection_adapters/connection_handler_test.rb +160 -53
  138. data/test/cases/connection_adapters/connection_specification_test.rb +12 -12
  139. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +255 -293
  140. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +69 -65
  141. data/test/cases/connection_adapters/quoting_test.rb +13 -13
  142. data/test/cases/connection_adapters/schema_cache_test.rb +61 -56
  143. data/test/cases/connection_adapters/type_lookup_test.rb +118 -110
  144. data/test/cases/connection_management_test.rb +112 -122
  145. data/test/cases/connection_pool_test.rb +521 -346
  146. data/test/cases/connection_specification/resolver_test.rb +131 -116
  147. data/test/cases/core_test.rb +112 -112
  148. data/test/cases/counter_cache_test.rb +214 -209
  149. data/test/cases/custom_locking_test.rb +17 -17
  150. data/test/cases/database_statements_test.rb +34 -19
  151. data/test/cases/{invalid_date_test.rb → date_test.rb} +44 -32
  152. data/test/cases/date_time_precision_test.rb +106 -0
  153. data/test/cases/date_time_test.rb +61 -61
  154. data/test/cases/defaults_test.rb +218 -223
  155. data/test/cases/dirty_test.rb +763 -785
  156. data/test/cases/disconnected_test.rb +30 -28
  157. data/test/cases/dup_test.rb +157 -157
  158. data/test/cases/enum_test.rb +444 -290
  159. data/test/cases/errors_test.rb +16 -0
  160. data/test/cases/explain_subscriber_test.rb +64 -64
  161. data/test/cases/explain_test.rb +87 -76
  162. data/test/cases/finder_respond_to_test.rb +60 -60
  163. data/test/cases/finder_test.rb +1294 -1169
  164. data/test/cases/fixture_set/file_test.rb +156 -138
  165. data/test/cases/fixtures_test.rb +988 -908
  166. data/test/cases/forbidden_attributes_protection_test.rb +165 -99
  167. data/test/cases/habtm_destroy_order_test.rb +61 -61
  168. data/test/cases/helper.rb +204 -210
  169. data/test/cases/hot_compatibility_test.rb +142 -54
  170. data/test/cases/i18n_test.rb +45 -45
  171. data/test/cases/inheritance_test.rb +606 -375
  172. data/test/cases/integration_test.rb +155 -139
  173. data/test/cases/invalid_connection_test.rb +24 -22
  174. data/test/cases/invertible_migration_test.rb +387 -295
  175. data/test/cases/json_serialization_test.rb +311 -302
  176. data/test/cases/locking_test.rb +493 -477
  177. data/test/cases/log_subscriber_test.rb +225 -136
  178. data/test/cases/migration/change_schema_test.rb +458 -512
  179. data/test/cases/migration/change_table_test.rb +256 -224
  180. data/test/cases/migration/column_attributes_test.rb +176 -192
  181. data/test/cases/migration/column_positioning_test.rb +56 -56
  182. data/test/cases/migration/columns_test.rb +310 -304
  183. data/test/cases/migration/command_recorder_test.rb +350 -305
  184. data/test/cases/migration/compatibility_test.rb +118 -0
  185. data/test/cases/migration/create_join_table_test.rb +157 -148
  186. data/test/cases/migration/foreign_key_test.rb +360 -328
  187. data/test/cases/migration/helper.rb +39 -39
  188. data/test/cases/migration/index_test.rb +218 -216
  189. data/test/cases/migration/logger_test.rb +36 -36
  190. data/test/cases/migration/pending_migrations_test.rb +52 -53
  191. data/test/cases/migration/references_foreign_key_test.rb +216 -169
  192. data/test/cases/migration/references_index_test.rb +101 -101
  193. data/test/cases/migration/references_statements_test.rb +136 -116
  194. data/test/cases/migration/rename_table_test.rb +93 -93
  195. data/test/cases/migration_test.rb +1157 -959
  196. data/test/cases/migrator_test.rb +470 -388
  197. data/test/cases/mixin_test.rb +68 -70
  198. data/test/cases/modules_test.rb +172 -173
  199. data/test/cases/multiparameter_attributes_test.rb +372 -350
  200. data/test/cases/multiple_db_test.rb +122 -115
  201. data/test/cases/nested_attributes_test.rb +1098 -1070
  202. data/test/cases/nested_attributes_with_callbacks_test.rb +144 -144
  203. data/test/cases/persistence_test.rb +1001 -909
  204. data/test/cases/pooled_connections_test.rb +81 -81
  205. data/test/cases/primary_keys_test.rb +376 -237
  206. data/test/cases/query_cache_test.rb +446 -326
  207. data/test/cases/quoting_test.rb +202 -156
  208. data/test/cases/readonly_test.rb +119 -118
  209. data/test/cases/reaper_test.rb +85 -85
  210. data/test/cases/reflection_test.rb +509 -463
  211. data/test/cases/relation/delegation_test.rb +63 -68
  212. data/test/cases/relation/merging_test.rb +157 -161
  213. data/test/cases/relation/mutation_test.rb +183 -165
  214. data/test/cases/relation/or_test.rb +92 -0
  215. data/test/cases/relation/predicate_builder_test.rb +16 -14
  216. data/test/cases/relation/record_fetch_warning_test.rb +40 -0
  217. data/test/cases/relation/where_chain_test.rb +105 -181
  218. data/test/cases/relation/where_clause_test.rb +182 -0
  219. data/test/cases/relation/where_test.rb +322 -300
  220. data/test/cases/relation_test.rb +328 -319
  221. data/test/cases/relations_test.rb +2026 -1815
  222. data/test/cases/reload_models_test.rb +22 -22
  223. data/test/cases/result_test.rb +90 -80
  224. data/test/cases/sanitize_test.rb +176 -83
  225. data/test/cases/schema_dumper_test.rb +457 -463
  226. data/test/cases/schema_loading_test.rb +52 -0
  227. data/test/cases/scoping/default_scoping_test.rb +528 -454
  228. data/test/cases/scoping/named_scoping_test.rb +561 -524
  229. data/test/cases/scoping/relation_scoping_test.rb +400 -357
  230. data/test/cases/secure_token_test.rb +32 -0
  231. data/test/cases/serialization_test.rb +104 -104
  232. data/test/cases/serialized_attribute_test.rb +364 -277
  233. data/test/cases/statement_cache_test.rb +136 -98
  234. data/test/cases/store_test.rb +195 -194
  235. data/test/cases/suppressor_test.rb +63 -0
  236. data/test/cases/tasks/database_tasks_test.rb +462 -398
  237. data/test/cases/tasks/mysql_rake_test.rb +345 -324
  238. data/test/cases/tasks/postgresql_rake_test.rb +304 -250
  239. data/test/cases/tasks/sqlite_rake_test.rb +220 -193
  240. data/test/cases/test_case.rb +131 -123
  241. data/test/cases/test_fixtures_test.rb +36 -0
  242. data/test/cases/time_precision_test.rb +102 -0
  243. data/test/cases/timestamp_test.rb +501 -467
  244. data/test/cases/touch_later_test.rb +121 -0
  245. data/test/cases/transaction_callbacks_test.rb +518 -452
  246. data/test/cases/transaction_isolation_test.rb +106 -106
  247. data/test/cases/transactions_test.rb +834 -817
  248. data/test/cases/type/adapter_specific_registry_test.rb +133 -0
  249. data/test/cases/type/date_time_test.rb +14 -0
  250. data/test/cases/type/integer_test.rb +27 -121
  251. data/test/cases/type/string_test.rb +22 -36
  252. data/test/cases/type/type_map_test.rb +177 -177
  253. data/test/cases/type_test.rb +39 -0
  254. data/test/cases/types_test.rb +24 -141
  255. data/test/cases/unconnected_test.rb +33 -33
  256. data/test/cases/validations/absence_validation_test.rb +73 -0
  257. data/test/cases/validations/association_validation_test.rb +97 -86
  258. data/test/cases/validations/i18n_generate_message_validation_test.rb +84 -84
  259. data/test/cases/validations/i18n_validation_test.rb +86 -90
  260. data/test/cases/validations/length_validation_test.rb +79 -47
  261. data/test/cases/validations/presence_validation_test.rb +103 -68
  262. data/test/cases/validations/uniqueness_validation_test.rb +548 -457
  263. data/test/cases/validations_repair_helper.rb +19 -23
  264. data/test/cases/validations_test.rb +194 -165
  265. data/test/cases/view_test.rb +216 -119
  266. data/test/cases/yaml_serialization_test.rb +121 -126
  267. data/test/config.example.yml +97 -0
  268. data/test/config.rb +5 -5
  269. data/test/fixtures/accounts.yml +29 -29
  270. data/test/fixtures/admin/accounts.yml +2 -2
  271. data/test/fixtures/admin/users.yml +10 -10
  272. data/test/fixtures/author_addresses.original +11 -0
  273. data/test/fixtures/author_addresses.yml +17 -17
  274. data/test/fixtures/author_favorites.yml +3 -3
  275. data/test/fixtures/authors.original +17 -0
  276. data/test/fixtures/authors.yml +23 -23
  277. data/test/fixtures/bad_posts.yml +9 -0
  278. data/test/fixtures/binaries.yml +133 -133
  279. data/test/fixtures/books.yml +31 -11
  280. data/test/fixtures/bulbs.yml +5 -5
  281. data/test/fixtures/cars.yml +9 -9
  282. data/test/fixtures/categories.yml +19 -19
  283. data/test/fixtures/categories/special_categories.yml +9 -9
  284. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -4
  285. data/test/fixtures/categories_ordered.yml +7 -7
  286. data/test/fixtures/categories_posts.yml +31 -31
  287. data/test/fixtures/categorizations.yml +23 -23
  288. data/test/fixtures/clubs.yml +8 -8
  289. data/test/fixtures/collections.yml +3 -3
  290. data/test/fixtures/colleges.yml +3 -3
  291. data/test/fixtures/comments.yml +65 -65
  292. data/test/fixtures/companies.yml +67 -67
  293. data/test/fixtures/computers.yml +10 -10
  294. data/test/fixtures/content.yml +3 -0
  295. data/test/fixtures/content_positions.yml +3 -0
  296. data/test/fixtures/courses.yml +8 -8
  297. data/test/fixtures/customers.yml +25 -25
  298. data/test/fixtures/dashboards.yml +6 -6
  299. data/test/fixtures/dead_parrots.yml +5 -0
  300. data/test/fixtures/developers.yml +22 -22
  301. data/test/fixtures/developers_projects.yml +16 -16
  302. data/test/fixtures/dog_lovers.yml +7 -7
  303. data/test/fixtures/dogs.yml +4 -4
  304. data/test/fixtures/doubloons.yml +3 -3
  305. data/test/fixtures/edges.yml +5 -5
  306. data/test/fixtures/entrants.yml +14 -14
  307. data/test/fixtures/essays.yml +6 -6
  308. data/test/fixtures/faces.yml +11 -11
  309. data/test/fixtures/fk_test_has_fk.yml +3 -3
  310. data/test/fixtures/fk_test_has_pk.yml +1 -1
  311. data/test/fixtures/friendships.yml +4 -4
  312. data/test/fixtures/funny_jokes.yml +10 -10
  313. data/test/fixtures/interests.yml +33 -33
  314. data/test/fixtures/items.yml +3 -3
  315. data/test/fixtures/jobs.yml +7 -7
  316. data/test/fixtures/legacy_things.yml +3 -3
  317. data/test/fixtures/live_parrots.yml +4 -0
  318. data/test/fixtures/mateys.yml +4 -4
  319. data/test/fixtures/member_details.yml +8 -8
  320. data/test/fixtures/member_types.yml +6 -6
  321. data/test/fixtures/members.yml +11 -11
  322. data/test/fixtures/memberships.yml +34 -34
  323. data/test/fixtures/men.yml +5 -5
  324. data/test/fixtures/minimalistics.yml +2 -2
  325. data/test/fixtures/minivans.yml +5 -5
  326. data/test/fixtures/mixed_case_monkeys.yml +6 -6
  327. data/test/fixtures/mixins.yml +29 -29
  328. data/test/fixtures/movies.yml +7 -7
  329. data/test/fixtures/naked/yml/accounts.yml +1 -1
  330. data/test/fixtures/naked/yml/companies.yml +1 -1
  331. data/test/fixtures/naked/yml/courses.yml +1 -1
  332. data/test/fixtures/naked/yml/parrots.yml +2 -0
  333. data/test/fixtures/naked/yml/trees.yml +3 -0
  334. data/test/fixtures/nodes.yml +29 -0
  335. data/test/fixtures/organizations.yml +5 -5
  336. data/test/fixtures/other_comments.yml +6 -0
  337. data/test/fixtures/other_dogs.yml +2 -0
  338. data/test/fixtures/other_posts.yml +7 -0
  339. data/test/fixtures/other_topics.yml +42 -42
  340. data/test/fixtures/owners.yml +9 -9
  341. data/test/fixtures/parrots.yml +27 -27
  342. data/test/fixtures/parrots_pirates.yml +7 -7
  343. data/test/fixtures/people.yml +24 -24
  344. data/test/fixtures/peoples_treasures.yml +3 -3
  345. data/test/fixtures/pets.yml +19 -19
  346. data/test/fixtures/pirates.yml +15 -12
  347. data/test/fixtures/posts.yml +80 -80
  348. data/test/fixtures/price_estimates.yml +16 -7
  349. data/test/fixtures/products.yml +4 -4
  350. data/test/fixtures/projects.yml +7 -7
  351. data/test/fixtures/ratings.yml +14 -14
  352. data/test/fixtures/readers.yml +11 -11
  353. data/test/fixtures/references.yml +17 -17
  354. data/test/fixtures/reserved_words/distinct.yml +5 -5
  355. data/test/fixtures/reserved_words/distinct_select.yml +11 -11
  356. data/test/fixtures/reserved_words/group.yml +14 -14
  357. data/test/fixtures/reserved_words/select.yml +8 -8
  358. data/test/fixtures/reserved_words/values.yml +7 -7
  359. data/test/fixtures/ships.yml +6 -6
  360. data/test/fixtures/speedometers.yml +8 -8
  361. data/test/fixtures/sponsors.yml +12 -12
  362. data/test/fixtures/string_key_objects.yml +7 -7
  363. data/test/fixtures/subscribers.yml +10 -10
  364. data/test/fixtures/subscriptions.yml +12 -12
  365. data/test/fixtures/taggings.yml +78 -78
  366. data/test/fixtures/tags.yml +11 -11
  367. data/test/fixtures/tasks.yml +7 -7
  368. data/test/fixtures/teapots.yml +3 -3
  369. data/test/fixtures/to_be_linked/accounts.yml +2 -2
  370. data/test/fixtures/to_be_linked/users.yml +10 -10
  371. data/test/fixtures/topics.yml +49 -49
  372. data/test/fixtures/toys.yml +14 -14
  373. data/test/fixtures/traffic_lights.yml +9 -9
  374. data/test/fixtures/treasures.yml +10 -10
  375. data/test/fixtures/trees.yml +3 -0
  376. data/test/fixtures/uuid_children.yml +3 -3
  377. data/test/fixtures/uuid_parents.yml +2 -2
  378. data/test/fixtures/variants.yml +4 -4
  379. data/test/fixtures/vegetables.yml +19 -19
  380. data/test/fixtures/vertices.yml +3 -3
  381. data/test/fixtures/warehouse_things.yml +2 -2
  382. data/test/fixtures/zines.yml +5 -5
  383. data/test/migrations/10_urban/9_add_expressions.rb +11 -11
  384. data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -15
  385. data/test/migrations/magic/1_currencies_have_symbols.rb +12 -12
  386. data/test/migrations/missing/1000_people_have_middle_names.rb +9 -9
  387. data/test/migrations/missing/1_people_have_last_names.rb +9 -9
  388. data/test/migrations/missing/3_we_need_reminders.rb +12 -12
  389. data/test/migrations/missing/4_innocent_jointable.rb +12 -12
  390. data/test/migrations/rename/1_we_need_things.rb +11 -11
  391. data/test/migrations/rename/2_rename_things.rb +9 -9
  392. data/test/migrations/to_copy/1_people_have_hobbies.rb +9 -9
  393. data/test/migrations/to_copy/2_people_have_descriptions.rb +9 -9
  394. data/test/migrations/to_copy2/1_create_articles.rb +7 -7
  395. data/test/migrations/to_copy2/2_create_comments.rb +7 -7
  396. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +9 -9
  397. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +9 -9
  398. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +9 -9
  399. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +7 -7
  400. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +7 -7
  401. data/test/migrations/valid/1_valid_people_have_last_names.rb +9 -9
  402. data/test/migrations/valid/2_we_need_reminders.rb +12 -12
  403. data/test/migrations/valid/3_innocent_jointable.rb +12 -12
  404. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +9 -9
  405. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +12 -12
  406. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +12 -12
  407. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +9 -9
  408. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +12 -12
  409. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +12 -12
  410. data/test/migrations/version_check/20131219224947_migration_version_check.rb +8 -8
  411. data/test/models/admin.rb +5 -5
  412. data/test/models/admin/account.rb +3 -3
  413. data/test/models/admin/randomly_named_c1.rb +6 -2
  414. data/test/models/admin/user.rb +40 -40
  415. data/test/models/aircraft.rb +5 -4
  416. data/test/models/arunit2_model.rb +3 -3
  417. data/test/models/author.rb +209 -212
  418. data/test/models/auto_id.rb +4 -4
  419. data/test/models/autoloadable/extra_firm.rb +2 -2
  420. data/test/models/binary.rb +2 -2
  421. data/test/models/bird.rb +12 -12
  422. data/test/models/book.rb +23 -18
  423. data/test/models/boolean.rb +2 -2
  424. data/test/models/bulb.rb +52 -51
  425. data/test/models/cake_designer.rb +3 -3
  426. data/test/models/car.rb +29 -26
  427. data/test/models/carrier.rb +2 -2
  428. data/test/models/cat.rb +10 -0
  429. data/test/models/categorization.rb +19 -19
  430. data/test/models/category.rb +35 -35
  431. data/test/models/chef.rb +8 -7
  432. data/test/models/citation.rb +3 -3
  433. data/test/models/club.rb +25 -23
  434. data/test/models/college.rb +10 -10
  435. data/test/models/column.rb +3 -3
  436. data/test/models/column_name.rb +3 -3
  437. data/test/models/comment.rb +76 -64
  438. data/test/models/company.rb +230 -228
  439. data/test/models/company_in_module.rb +98 -98
  440. data/test/models/computer.rb +3 -3
  441. data/test/models/contact.rb +41 -41
  442. data/test/models/content.rb +40 -0
  443. data/test/models/contract.rb +20 -20
  444. data/test/models/country.rb +7 -7
  445. data/test/models/course.rb +6 -6
  446. data/test/models/customer.rb +83 -77
  447. data/test/models/customer_carrier.rb +14 -14
  448. data/test/models/dashboard.rb +3 -3
  449. data/test/models/default.rb +2 -2
  450. data/test/models/department.rb +4 -4
  451. data/test/models/developer.rb +274 -255
  452. data/test/models/dog.rb +5 -5
  453. data/test/models/dog_lover.rb +5 -5
  454. data/test/models/doubloon.rb +12 -12
  455. data/test/models/drink_designer.rb +3 -3
  456. data/test/models/edge.rb +5 -5
  457. data/test/models/electron.rb +5 -5
  458. data/test/models/engine.rb +4 -4
  459. data/test/models/entrant.rb +3 -3
  460. data/test/models/essay.rb +5 -5
  461. data/test/models/event.rb +3 -3
  462. data/test/models/eye.rb +37 -37
  463. data/test/models/face.rb +9 -9
  464. data/test/models/friendship.rb +6 -6
  465. data/test/models/guid.rb +2 -2
  466. data/test/models/guitar.rb +4 -0
  467. data/test/models/hotel.rb +11 -9
  468. data/test/models/image.rb +3 -3
  469. data/test/models/interest.rb +5 -5
  470. data/test/models/invoice.rb +4 -4
  471. data/test/models/item.rb +7 -7
  472. data/test/models/job.rb +7 -7
  473. data/test/models/joke.rb +7 -7
  474. data/test/models/keyboard.rb +3 -3
  475. data/test/models/legacy_thing.rb +3 -3
  476. data/test/models/lesson.rb +11 -11
  477. data/test/models/line_item.rb +3 -3
  478. data/test/models/liquid.rb +4 -4
  479. data/test/models/man.rb +11 -11
  480. data/test/models/matey.rb +4 -4
  481. data/test/models/member.rb +42 -41
  482. data/test/models/member_detail.rb +8 -7
  483. data/test/models/member_type.rb +3 -3
  484. data/test/models/membership.rb +35 -35
  485. data/test/models/mentor.rb +3 -0
  486. data/test/models/minimalistic.rb +2 -2
  487. data/test/models/minivan.rb +9 -9
  488. data/test/models/mixed_case_monkey.rb +3 -3
  489. data/test/models/mocktail_designer.rb +2 -0
  490. data/test/models/molecule.rb +6 -6
  491. data/test/models/movie.rb +5 -5
  492. data/test/models/node.rb +5 -0
  493. data/test/models/non_primary_key.rb +2 -0
  494. data/test/models/notification.rb +3 -0
  495. data/test/models/order.rb +4 -4
  496. data/test/models/organization.rb +14 -14
  497. data/test/models/other_dog.rb +5 -0
  498. data/test/models/owner.rb +37 -34
  499. data/test/models/parrot.rb +28 -29
  500. data/test/models/person.rb +142 -143
  501. data/test/models/personal_legacy_thing.rb +4 -4
  502. data/test/models/pet.rb +18 -15
  503. data/test/models/pet_treasure.rb +6 -0
  504. data/test/models/pirate.rb +92 -92
  505. data/test/models/possession.rb +3 -3
  506. data/test/models/post.rb +273 -264
  507. data/test/models/price_estimate.rb +4 -4
  508. data/test/models/professor.rb +5 -5
  509. data/test/models/project.rb +40 -31
  510. data/test/models/publisher.rb +2 -2
  511. data/test/models/publisher/article.rb +4 -4
  512. data/test/models/publisher/magazine.rb +3 -3
  513. data/test/models/randomly_named_c1.rb +1 -1
  514. data/test/models/rating.rb +4 -4
  515. data/test/models/reader.rb +23 -23
  516. data/test/models/recipe.rb +3 -0
  517. data/test/models/record.rb +2 -2
  518. data/test/models/reference.rb +22 -22
  519. data/test/models/reply.rb +61 -61
  520. data/test/models/ship.rb +39 -33
  521. data/test/models/ship_part.rb +8 -8
  522. data/test/models/shop.rb +17 -17
  523. data/test/models/shop_account.rb +6 -6
  524. data/test/models/speedometer.rb +6 -6
  525. data/test/models/sponsor.rb +7 -7
  526. data/test/models/string_key_object.rb +3 -3
  527. data/test/models/student.rb +4 -4
  528. data/test/models/subject.rb +16 -16
  529. data/test/models/subscriber.rb +8 -8
  530. data/test/models/subscription.rb +4 -4
  531. data/test/models/tag.rb +13 -7
  532. data/test/models/tagging.rb +13 -13
  533. data/test/models/task.rb +5 -5
  534. data/test/models/topic.rb +118 -124
  535. data/test/models/toy.rb +6 -6
  536. data/test/models/traffic_light.rb +4 -4
  537. data/test/models/treasure.rb +14 -14
  538. data/test/models/treaty.rb +7 -7
  539. data/test/models/tree.rb +3 -0
  540. data/test/models/tuning_peg.rb +4 -0
  541. data/test/models/tyre.rb +11 -11
  542. data/test/models/user.rb +14 -0
  543. data/test/models/uuid_child.rb +3 -3
  544. data/test/models/uuid_item.rb +6 -0
  545. data/test/models/uuid_parent.rb +3 -3
  546. data/test/models/vegetables.rb +24 -24
  547. data/test/models/vehicle.rb +6 -6
  548. data/test/models/vertex.rb +9 -9
  549. data/test/models/warehouse_thing.rb +5 -5
  550. data/test/models/wheel.rb +3 -3
  551. data/test/models/without_table.rb +3 -3
  552. data/test/models/zine.rb +3 -3
  553. data/test/schema/mysql2_specific_schema.rb +68 -58
  554. data/test/schema/oracle_specific_schema.rb +40 -43
  555. data/test/schema/postgresql_specific_schema.rb +114 -202
  556. data/test/schema/schema.rb +1057 -952
  557. data/test/schema/schema.rb.original +1057 -0
  558. data/test/schema/sqlite_specific_schema.rb +18 -22
  559. data/test/support/config.rb +43 -43
  560. data/test/support/connection.rb +23 -22
  561. data/test/support/connection_helper.rb +14 -14
  562. data/test/support/ddl_helper.rb +8 -8
  563. data/test/support/schema_dumping_helper.rb +20 -20
  564. data/test/support/yaml_compatibility_fixtures/rails_4_1.yml +22 -0
  565. data/test/support/yaml_compatibility_fixtures/rails_4_2_0.yml +182 -0
  566. metadata +129 -28
  567. data/lib/mswin32/rb19x/ibm_db.so +0 -0
  568. data/lib/mswin32/rb21x/i386/ibm_db.so +0 -0
  569. data/lib/mswin32/rb22x/i386/ibm_db.so +0 -0
  570. data/lib/mswin32/rb23x/i386/ibm_db.so +0 -0
  571. data/test/cases/associations/deprecated_counter_cache_on_has_many_through_test.rb +0 -26
  572. data/test/cases/attribute_methods/serialization_test.rb +0 -29
  573. data/test/cases/migration/change_schema_test - Copy.rb +0 -448
  574. data/test/cases/migration/foreign_key_test - Changed.rb +0 -325
  575. data/test/cases/migration/table_and_index_test.rb +0 -24
  576. data/test/cases/relation/where_test2.rb +0 -36
  577. data/test/cases/type/decimal_test.rb +0 -56
  578. data/test/cases/type/unsigned_integer_test.rb +0 -18
  579. data/test/cases/xml_serialization_test.rb +0 -457
  580. data/test/connections/native_ibm_db/connection.rb +0 -44
  581. data/test/fixtures/naked/csv/accounts.csv +0 -1
  582. data/test/schema/i5/ibm_db_specific_schema.rb +0 -137
  583. data/test/schema/ids/ibm_db_specific_schema.rb +0 -140
  584. data/test/schema/luw/ibm_db_specific_schema.rb +0 -137
  585. data/test/schema/mysql_specific_schema.rb +0 -70
  586. data/test/schema/zOS/ibm_db_specific_schema.rb +0 -208
@@ -1,1664 +1,1713 @@
1
- # encoding: utf-8
2
-
3
- require "cases/helper"
4
- require 'active_support/concurrency/latch'
5
- require 'models/post'
6
- require 'models/author'
7
- require 'models/topic'
8
- require 'models/reply'
9
- require 'models/category'
10
- require 'models/company'
11
- require 'models/customer'
12
- require 'models/developer'
13
- require 'models/computer'
14
- require 'models/project'
15
- require 'models/default'
16
- require 'models/auto_id'
17
- require 'models/boolean'
18
- require 'models/column_name'
19
- require 'models/subscriber'
20
- require 'models/keyboard'
21
- require 'models/comment'
22
- require 'models/minimalistic'
23
- require 'models/warehouse_thing'
24
- require 'models/parrot'
25
- require 'models/person'
26
- require 'models/edge'
27
- require 'models/joke'
28
- require 'models/bird'
29
- require 'models/car'
30
- require 'models/bulb'
31
- require 'rexml/document'
32
-
33
- class FirstAbstractClass < ActiveRecord::Base
34
- self.abstract_class = true
35
- end
36
- class SecondAbstractClass < FirstAbstractClass
37
- self.abstract_class = true
38
- end
39
- class Photo < SecondAbstractClass; end
40
- class Category < ActiveRecord::Base; end
41
- class Categorization < ActiveRecord::Base; end
42
- class Smarts < ActiveRecord::Base; end
43
- class CreditCard < ActiveRecord::Base
44
- class PinNumber < ActiveRecord::Base
45
- class CvvCode < ActiveRecord::Base; end
46
- class SubCvvCode < CvvCode; end
47
- end
48
- class SubPinNumber < PinNumber; end
49
- class Brand < Category; end
50
- end
51
- class MasterCreditCard < ActiveRecord::Base; end
52
- class Post < ActiveRecord::Base; end
53
- class Computer < ActiveRecord::Base; end
54
- class NonExistentTable < ActiveRecord::Base; end
55
- class TestOracleDefault < ActiveRecord::Base; end
56
-
57
- class ReadonlyTitlePost < Post
58
- attr_readonly :title
59
- end
60
-
61
- class Weird < ActiveRecord::Base; end
62
-
63
- class Boolean < ActiveRecord::Base
64
- def has_fun
65
- super
66
- end
67
- end
68
-
69
- class LintTest < ActiveRecord::TestCase
70
- include ActiveModel::Lint::Tests
71
-
72
- class LintModel < ActiveRecord::Base; end
73
-
74
- def setup
75
- @model = LintModel.new
76
- end
77
- end
78
-
79
- class BasicsTest < ActiveRecord::TestCase
80
- fixtures :topics, :companies, :developers, :projects, :computers, :accounts, :minimalistics, 'warehouse_things', :authors, :categorizations, :categories, :posts, :author_addresses
81
-
82
- def test_column_names_are_escaped
83
- conn = ActiveRecord::Base.connection
84
- classname = conn.class.name[/[^:]*$/]
85
- badchar = {
86
- 'SQLite3Adapter' => '"',
87
- 'MysqlAdapter' => '`',
88
- 'Mysql2Adapter' => '`',
89
- 'PostgreSQLAdapter' => '"',
90
- 'OracleAdapter' => '"',
91
- 'IBM_DBAdapter' => '"',
92
- }.fetch(classname) {
93
- raise "need a bad char for #{classname}"
94
- }
95
-
96
- quoted = conn.quote_column_name "foo#{badchar}bar"
97
- if current_adapter?(:OracleAdapter)
98
- # Oracle does not allow double quotes in table and column names at all
99
- # therefore quoting removes them
100
- assert_equal("#{badchar}foobar#{badchar}", quoted)
101
- elsif current_adapter?(:IBM_DBAdapter)
102
- assert_equal("foo#{badchar}bar", quoted)
103
- else
104
- assert_equal("#{badchar}foo#{badchar * 2}bar#{badchar}", quoted)
105
- end
106
- end
107
-
108
- def test_columns_should_obey_set_primary_key
109
- pk = Subscriber.columns_hash[Subscriber.primary_key]
110
- assert_equal 'nick', pk.name, 'nick should be primary key'
111
- end
112
-
113
- def test_primary_key_with_no_id
114
- assert_nil Edge.primary_key
115
- end
116
-
117
- unless current_adapter?(:PostgreSQLAdapter, :OracleAdapter, :SQLServerAdapter, :IBM_DBAdapter)
118
- def test_limit_with_comma
119
- assert Topic.limit("1,2").to_a
120
- end
121
- end
122
-
123
- def test_limit_without_comma
124
- assert_equal 1, Topic.limit("1").to_a.length
125
- assert_equal 1, Topic.limit(1).to_a.length
126
- end
127
-
128
- def test_limit_should_take_value_from_latest_limit
129
- assert_equal 1, Topic.limit(2).limit(1).to_a.length
130
- end
131
-
132
- def test_invalid_limit
133
- assert_raises(ArgumentError) do
134
- Topic.limit("asdfadf").to_a
135
- end
136
- end
137
-
138
- def test_limit_should_sanitize_sql_injection_for_limit_without_commas
139
- assert_raises(ArgumentError) do
140
- Topic.limit("1 select * from schema").to_a
141
- end
142
- end
143
-
144
- def test_limit_should_sanitize_sql_injection_for_limit_with_commas
145
- assert_raises(ArgumentError) do
146
- Topic.limit("1, 7 procedure help()").to_a
147
- end
148
- end
149
-
150
- unless current_adapter?(:MysqlAdapter, :Mysql2Adapter, :IBM_DBAdapter)
151
- def test_limit_should_allow_sql_literal
152
- assert_equal 1, Topic.limit(Arel.sql('2-1')).to_a.length
153
- end
154
- end
155
-
156
- def test_select_symbol
157
- topic_ids = Topic.select(:id).map(&:id).sort
158
- assert_equal Topic.pluck(:id).sort, topic_ids
159
- end
160
-
161
- def test_table_exists
162
- assert !NonExistentTable.table_exists?
163
- assert Topic.table_exists?
164
- end
165
-
166
- def test_preserving_date_objects
167
- # Oracle enhanced adapter allows to define Date attributes in model class (see topic.rb)
168
- assert_kind_of(
169
- Date, Topic.find(1).last_read,
170
- "The last_read attribute should be of the Date class"
171
- )
172
- end
173
-
174
- def test_previously_changed
175
- topic = Topic.first
176
- topic.title = '<3<3<3'
177
- assert_equal({}, topic.previous_changes)
178
-
179
- topic.save!
180
- expected = ["The First Topic", "<3<3<3"]
181
- assert_equal(expected, topic.previous_changes['title'])
182
- end
183
-
184
- def test_previously_changed_dup
185
- topic = Topic.first
186
- topic.title = '<3<3<3'
187
- topic.save!
188
-
189
- t2 = topic.dup
190
-
191
- assert_equal(topic.previous_changes, t2.previous_changes)
192
-
193
- topic.title = "lolwut"
194
- topic.save!
195
-
196
- assert_not_equal(topic.previous_changes, t2.previous_changes)
197
- end
198
-
199
- def test_preserving_time_objects
200
- assert_kind_of(
201
- Time, Topic.find(1).bonus_time,
202
- "The bonus_time attribute should be of the Time class"
203
- )
204
-
205
- assert_kind_of(
206
- Time, Topic.find(1).written_on,
207
- "The written_on attribute should be of the Time class"
208
- )
209
-
210
- # For adapters which support microsecond resolution.
211
- if current_adapter?(:PostgreSQLAdapter, :SQLite3Adapter) || mysql_56?
212
- assert_equal 11, Topic.find(1).written_on.sec
213
- assert_equal 223300, Topic.find(1).written_on.usec
214
- assert_equal 9900, Topic.find(2).written_on.usec
215
- assert_equal 129346, Topic.find(3).written_on.usec
216
- end
217
- end
218
-
219
- def test_preserving_time_objects_with_local_time_conversion_to_default_timezone_utc
220
- with_env_tz 'America/New_York' do
221
- with_timezone_config default: :utc do
222
- time = Time.local(2000)
223
- topic = Topic.create('written_on' => time)
224
- saved_time = Topic.find(topic.id).reload.written_on
225
- assert_equal time, saved_time
226
- assert_equal [0, 0, 0, 1, 1, 2000, 6, 1, false, "EST"], time.to_a
227
- assert_equal [0, 0, 5, 1, 1, 2000, 6, 1, false, "UTC"], saved_time.to_a
228
- end
229
- end
230
- end
231
-
232
- def test_preserving_time_objects_with_time_with_zone_conversion_to_default_timezone_utc
233
- with_env_tz 'America/New_York' do
234
- with_timezone_config default: :utc do
235
- Time.use_zone 'Central Time (US & Canada)' do
236
- time = Time.zone.local(2000)
237
- topic = Topic.create('written_on' => time)
238
- saved_time = Topic.find(topic.id).reload.written_on
239
- assert_equal time, saved_time
240
- assert_equal [0, 0, 0, 1, 1, 2000, 6, 1, false, "CST"], time.to_a
241
- assert_equal [0, 0, 6, 1, 1, 2000, 6, 1, false, "UTC"], saved_time.to_a
242
- end
243
- end
244
- end
245
- end
246
-
247
- def test_preserving_time_objects_with_utc_time_conversion_to_default_timezone_local
248
- with_env_tz 'America/New_York' do
249
- with_timezone_config default: :local do
250
- time = Time.utc(2000)
251
- topic = Topic.create('written_on' => time)
252
- saved_time = Topic.find(topic.id).reload.written_on
253
- assert_equal time, saved_time
254
- assert_equal [0, 0, 0, 1, 1, 2000, 6, 1, false, "UTC"], time.to_a
255
- assert_equal [0, 0, 19, 31, 12, 1999, 5, 365, false, "EST"], saved_time.to_a
256
- end
257
- end
258
- end
259
-
260
- def test_preserving_time_objects_with_time_with_zone_conversion_to_default_timezone_local
261
- with_env_tz 'America/New_York' do
262
- with_timezone_config default: :local do
263
- Time.use_zone 'Central Time (US & Canada)' do
264
- time = Time.zone.local(2000)
265
- topic = Topic.create('written_on' => time)
266
- saved_time = Topic.find(topic.id).reload.written_on
267
- assert_equal time, saved_time
268
- assert_equal [0, 0, 0, 1, 1, 2000, 6, 1, false, "CST"], time.to_a
269
- assert_equal [0, 0, 1, 1, 1, 2000, 6, 1, false, "EST"], saved_time.to_a
270
- end
271
- end
272
- end
273
- end
274
-
275
- def test_custom_mutator
276
- topic = Topic.find(1)
277
- # This mutator is protected in the class definition
278
- topic.send(:approved=, true)
279
- assert topic.instance_variable_get("@custom_approved")
280
- end
281
-
282
- def test_initialize_with_attributes
283
- topic = Topic.new({
284
- "title" => "initialized from attributes", "written_on" => "2003-12-12 23:23"
285
- })
286
-
287
- assert_equal("initialized from attributes", topic.title)
288
- end
289
-
290
- def test_initialize_with_invalid_attribute
291
- Topic.new({ "title" => "test",
292
- "last_read(1i)" => "2005", "last_read(2i)" => "2", "last_read(3i)" => "31"})
293
- rescue ActiveRecord::MultiparameterAssignmentErrors => ex
294
- assert_equal(1, ex.errors.size)
295
- assert_equal("last_read", ex.errors[0].attribute)
296
- end
297
-
298
- def test_create_after_initialize_without_block
299
- cb = CustomBulb.create(:name => 'Dude')
300
- assert_equal('Dude', cb.name)
301
- assert_equal(true, cb.frickinawesome)
302
- end
303
-
304
- def test_create_after_initialize_with_block
305
- cb = CustomBulb.create {|c| c.name = 'Dude' }
306
- assert_equal('Dude', cb.name)
307
- assert_equal(true, cb.frickinawesome)
308
- end
309
-
310
- def test_create_after_initialize_with_array_param
311
- cbs = CustomBulb.create([{ name: 'Dude' }, { name: 'Bob' }])
312
- assert_equal 'Dude', cbs[0].name
313
- assert_equal 'Bob', cbs[1].name
314
- assert cbs[0].frickinawesome
315
- assert !cbs[1].frickinawesome
316
- end
317
-
318
- def test_load
319
- topics = Topic.all.merge!(:order => 'id').to_a
320
- assert_equal(5, topics.size)
321
- assert_equal(topics(:first).title, topics.first.title)
322
- end
323
-
324
- def test_load_with_condition
325
- topics = Topic.all.merge!(:where => "author_name = 'Mary'").to_a
326
-
327
- assert_equal(1, topics.size)
328
- assert_equal(topics(:second).title, topics.first.title)
329
- end
330
-
331
- GUESSED_CLASSES = [Category, Smarts, CreditCard, CreditCard::PinNumber, CreditCard::PinNumber::CvvCode, CreditCard::SubPinNumber, CreditCard::Brand, MasterCreditCard]
332
-
333
- def test_table_name_guesses
334
- assert_equal "topics", Topic.table_name
335
-
336
- assert_equal "categories", Category.table_name
337
- assert_equal "smarts", Smarts.table_name
338
- assert_equal "credit_cards", CreditCard.table_name
339
- assert_equal "credit_card_pin_numbers", CreditCard::PinNumber.table_name
340
- assert_equal "credit_card_pin_number_cvv_codes", CreditCard::PinNumber::CvvCode.table_name
341
- assert_equal "credit_card_pin_numbers", CreditCard::SubPinNumber.table_name
342
- assert_equal "categories", CreditCard::Brand.table_name
343
- assert_equal "master_credit_cards", MasterCreditCard.table_name
344
- ensure
345
- GUESSED_CLASSES.each(&:reset_table_name)
346
- end
347
-
348
- def test_singular_table_name_guesses
349
- ActiveRecord::Base.pluralize_table_names = false
350
- GUESSED_CLASSES.each(&:reset_table_name)
351
-
352
- assert_equal "category", Category.table_name
353
- assert_equal "smarts", Smarts.table_name
354
- assert_equal "credit_card", CreditCard.table_name
355
- assert_equal "credit_card_pin_number", CreditCard::PinNumber.table_name
356
- assert_equal "credit_card_pin_number_cvv_code", CreditCard::PinNumber::CvvCode.table_name
357
- assert_equal "credit_card_pin_number", CreditCard::SubPinNumber.table_name
358
- assert_equal "category", CreditCard::Brand.table_name
359
- assert_equal "master_credit_card", MasterCreditCard.table_name
360
- ensure
361
- ActiveRecord::Base.pluralize_table_names = true
362
- GUESSED_CLASSES.each(&:reset_table_name)
363
- end
364
-
365
- def test_table_name_guesses_with_prefixes_and_suffixes
366
- ActiveRecord::Base.table_name_prefix = "test_"
367
- Category.reset_table_name
368
- assert_equal "test_categories", Category.table_name
369
- ActiveRecord::Base.table_name_suffix = "_test"
370
- Category.reset_table_name
371
- assert_equal "test_categories_test", Category.table_name
372
- ActiveRecord::Base.table_name_prefix = ""
373
- Category.reset_table_name
374
- assert_equal "categories_test", Category.table_name
375
- ActiveRecord::Base.table_name_suffix = ""
376
- Category.reset_table_name
377
- assert_equal "categories", Category.table_name
378
- ensure
379
- ActiveRecord::Base.table_name_prefix = ""
380
- ActiveRecord::Base.table_name_suffix = ""
381
- GUESSED_CLASSES.each(&:reset_table_name)
382
- end
383
-
384
- def test_singular_table_name_guesses_with_prefixes_and_suffixes
385
- ActiveRecord::Base.pluralize_table_names = false
386
-
387
- ActiveRecord::Base.table_name_prefix = "test_"
388
- Category.reset_table_name
389
- assert_equal "test_category", Category.table_name
390
- ActiveRecord::Base.table_name_suffix = "_test"
391
- Category.reset_table_name
392
- assert_equal "test_category_test", Category.table_name
393
- ActiveRecord::Base.table_name_prefix = ""
394
- Category.reset_table_name
395
- assert_equal "category_test", Category.table_name
396
- ActiveRecord::Base.table_name_suffix = ""
397
- Category.reset_table_name
398
- assert_equal "category", Category.table_name
399
- ensure
400
- ActiveRecord::Base.pluralize_table_names = true
401
- ActiveRecord::Base.table_name_prefix = ""
402
- ActiveRecord::Base.table_name_suffix = ""
403
- GUESSED_CLASSES.each(&:reset_table_name)
404
- end
405
-
406
- def test_table_name_guesses_with_inherited_prefixes_and_suffixes
407
- GUESSED_CLASSES.each(&:reset_table_name)
408
-
409
- CreditCard.table_name_prefix = "test_"
410
- CreditCard.reset_table_name
411
- Category.reset_table_name
412
- assert_equal "test_credit_cards", CreditCard.table_name
413
- assert_equal "categories", Category.table_name
414
- CreditCard.table_name_suffix = "_test"
415
- CreditCard.reset_table_name
416
- Category.reset_table_name
417
- assert_equal "test_credit_cards_test", CreditCard.table_name
418
- assert_equal "categories", Category.table_name
419
- CreditCard.table_name_prefix = ""
420
- CreditCard.reset_table_name
421
- Category.reset_table_name
422
- assert_equal "credit_cards_test", CreditCard.table_name
423
- assert_equal "categories", Category.table_name
424
- CreditCard.table_name_suffix = ""
425
- CreditCard.reset_table_name
426
- Category.reset_table_name
427
- assert_equal "credit_cards", CreditCard.table_name
428
- assert_equal "categories", Category.table_name
429
- ensure
430
- CreditCard.table_name_prefix = ""
431
- CreditCard.table_name_suffix = ""
432
- GUESSED_CLASSES.each(&:reset_table_name)
433
- end
434
-
435
- def test_singular_table_name_guesses_for_individual_table
436
- Post.pluralize_table_names = false
437
- Post.reset_table_name
438
- assert_equal "post", Post.table_name
439
- assert_equal "categories", Category.table_name
440
- ensure
441
- Post.pluralize_table_names = true
442
- Post.reset_table_name
443
- end
444
-
445
- if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
446
- def test_update_all_with_order_and_limit
447
- assert_equal 1, Topic.limit(1).order('id DESC').update_all(:content => 'bulk updated!')
448
- end
449
- end
450
-
451
- def test_null_fields
452
- assert_nil Topic.find(1).parent_id
453
- assert_nil Topic.create("title" => "Hey you").parent_id
454
- end
455
-
456
- def test_default_values
457
- topic = Topic.new
458
- assert topic.approved?
459
- assert_nil topic.written_on
460
- assert_nil topic.bonus_time
461
- assert_nil topic.last_read
462
-
463
- topic.save
464
-
465
- topic = Topic.find(topic.id)
466
- assert topic.approved?
467
- assert_nil topic.last_read
468
-
469
- # Oracle has some funky default handling, so it requires a bit of
470
- # extra testing. See ticket #2788.
471
- if current_adapter?(:OracleAdapter)
472
- test = TestOracleDefault.new
473
- assert_equal "X", test.test_char
474
- assert_equal "hello", test.test_string
475
- assert_equal 3, test.test_int
476
- end
477
- end
478
-
479
- # Oracle does not have a TIME datatype.
480
- unless current_adapter?(:OracleAdapter)
481
- def test_utc_as_time_zone
482
- with_timezone_config default: :utc do
483
- attributes = { "bonus_time" => "5:42:00AM" }
484
- topic = Topic.find(1)
485
- topic.attributes = attributes
486
- assert_equal Time.utc(2000, 1, 1, 5, 42, 0), topic.bonus_time
487
- end
488
- end
489
-
490
- def test_utc_as_time_zone_and_new
491
- with_timezone_config default: :utc do
492
- attributes = { "bonus_time(1i)"=>"2000",
493
- "bonus_time(2i)"=>"1",
494
- "bonus_time(3i)"=>"1",
495
- "bonus_time(4i)"=>"10",
496
- "bonus_time(5i)"=>"35",
497
- "bonus_time(6i)"=>"50" }
498
- topic = Topic.new(attributes)
499
- assert_equal Time.utc(2000, 1, 1, 10, 35, 50), topic.bonus_time
500
- end
501
- end
502
- end
503
-
504
- def test_default_values_on_empty_strings
505
- topic = Topic.new
506
- topic.approved = nil
507
- topic.last_read = nil
508
-
509
- topic.save
510
-
511
- topic = Topic.find(topic.id)
512
- assert_nil topic.last_read
513
-
514
- assert_nil topic.approved
515
- end
516
-
517
- def test_equality
518
- assert_equal Topic.find(1), Topic.find(2).topic
519
- end
520
-
521
- def test_find_by_slug
522
- assert_equal Topic.find('1-meowmeow'), Topic.find(1)
523
- end
524
-
525
- def test_find_by_slug_with_array
526
- assert_equal Topic.find(['1-meowmeow', '2-hello']), Topic.find([1, 2])
527
- end
528
-
529
- def test_find_by_slug_with_range
530
- assert_equal Topic.where(id: '1-meowmeow'..'2-hello'), Topic.where(id: 1..2)
531
- end
532
-
533
- def test_equality_of_new_records
534
- assert_not_equal Topic.new, Topic.new
535
- assert_equal false, Topic.new == Topic.new
536
- end
537
-
538
- def test_equality_of_destroyed_records
539
- topic_1 = Topic.new(:title => 'test_1')
540
- topic_1.save
541
- topic_2 = Topic.find(topic_1.id)
542
- topic_1.destroy
543
- assert_equal topic_1, topic_2
544
- assert_equal topic_2, topic_1
545
- end
546
-
547
- def test_equality_with_blank_ids
548
- one = Subscriber.new(:id => '')
549
- two = Subscriber.new(:id => '')
550
- assert_equal one, two
551
- end
552
-
553
- def test_equality_of_relation_and_collection_proxy
554
- car = Car.create!
555
- car.bulbs.build
556
- car.save
557
-
558
- assert car.bulbs == Bulb.where(car_id: car.id), 'CollectionProxy should be comparable with Relation'
559
- assert Bulb.where(car_id: car.id) == car.bulbs, 'Relation should be comparable with CollectionProxy'
560
- end
561
-
562
- def test_equality_of_relation_and_array
563
- car = Car.create!
564
- car.bulbs.build
565
- car.save
566
-
567
- assert Bulb.where(car_id: car.id) == car.bulbs.to_a, 'Relation should be comparable with Array'
568
- end
569
-
570
- def test_equality_of_relation_and_association_relation
571
- car = Car.create!
572
- car.bulbs.build
573
- car.save
574
-
575
- assert_equal Bulb.where(car_id: car.id), car.bulbs.includes(:car), 'Relation should be comparable with AssociationRelation'
576
- assert_equal car.bulbs.includes(:car), Bulb.where(car_id: car.id), 'AssociationRelation should be comparable with Relation'
577
- end
578
-
579
- def test_equality_of_collection_proxy_and_association_relation
580
- car = Car.create!
581
- car.bulbs.build
582
- car.save
583
-
584
- assert_equal car.bulbs, car.bulbs.includes(:car), 'CollectionProxy should be comparable with AssociationRelation'
585
- assert_equal car.bulbs.includes(:car), car.bulbs, 'AssociationRelation should be comparable with CollectionProxy'
586
- end
587
-
588
- def test_hashing
589
- assert_equal [ Topic.find(1) ], [ Topic.find(2).topic ] & [ Topic.find(1) ]
590
- end
591
-
592
- def test_successful_comparison_of_like_class_records
593
- topic_1 = Topic.create!
594
- topic_2 = Topic.create!
595
-
596
- assert_equal [topic_2, topic_1].sort, [topic_1, topic_2]
597
- end
598
-
599
- def test_failed_comparison_of_unlike_class_records
600
- assert_raises ArgumentError do
601
- [ topics(:first), posts(:welcome) ].sort
602
- end
603
- end
604
-
605
- def test_create_without_prepared_statement
606
- topic = Topic.connection.unprepared_statement do
607
- Topic.create(:title => 'foo')
608
- end
609
-
610
- assert_equal topic, Topic.find(topic.id)
611
- end
612
-
613
- def test_destroy_without_prepared_statement
614
- topic = Topic.create(title: 'foo')
615
- Topic.connection.unprepared_statement do
616
- Topic.find(topic.id).destroy
617
- end
618
-
619
- assert_equal nil, Topic.find_by_id(topic.id)
620
- end
621
-
622
- def test_comparison_with_different_objects
623
- topic = Topic.create
624
- category = Category.create(:name => "comparison")
625
- assert_nil topic <=> category
626
- end
627
-
628
- def test_comparison_with_different_objects_in_array
629
- topic = Topic.create
630
- assert_raises(ArgumentError) do
631
- [1, topic].sort
632
- end
633
- end
634
-
635
- def test_readonly_attributes
636
- assert_equal Set.new([ 'title' , 'comments_count' ]), ReadonlyTitlePost.readonly_attributes
637
-
638
- post = ReadonlyTitlePost.create(:title => "cannot change this", :body => "changeable")
639
- post.reload
640
- assert_equal "cannot change this", post.title
641
-
642
- post.update(title: "try to change", body: "changed")
643
- post.reload
644
- assert_equal "cannot change this", post.title
645
- assert_equal "changed", post.body
646
- end
647
-
648
- def test_unicode_column_name
649
- Weird.reset_column_information
650
- weird = Weird.create(:なまえ => 'たこ焼き仮面')
651
- assert_equal 'たこ焼き仮面', weird.なまえ
652
- end
653
-
654
- unless current_adapter?(:PostgreSQLAdapter)
655
- def test_respect_internal_encoding
656
- old_default_internal = Encoding.default_internal
657
- silence_warnings { Encoding.default_internal = "EUC-JP" }
658
-
659
- Weird.reset_column_information
660
-
661
- assert_equal ["EUC-JP"], Weird.columns.map {|c| c.name.encoding.name }.uniq
662
- ensure
663
- silence_warnings { Encoding.default_internal = old_default_internal }
664
- Weird.reset_column_information
665
- end
666
- end
667
-
668
- def test_non_valid_identifier_column_name
669
- weird = Weird.create('a$b' => 'value')
670
- weird.reload
671
- assert_equal 'value', weird.send('a$b')
672
- assert_equal 'value', weird.read_attribute('a$b')
673
-
674
- weird.update_columns('a$b' => 'value2')
675
- weird.reload
676
- assert_equal 'value2', weird.send('a$b')
677
- assert_equal 'value2', weird.read_attribute('a$b')
678
- end
679
-
680
- def test_group_weirds_by_from
681
- Weird.create('a$b' => 'value', :from => 'aaron')
682
- count = Weird.group(Weird.arel_table[:from]).count
683
- assert_equal 1, count['aaron']
684
- end
685
-
686
- def test_attributes_on_dummy_time
687
- # Oracle does not have a TIME datatype.
688
- return true if current_adapter?(:OracleAdapter)
689
-
690
- with_timezone_config default: :local do
691
- attributes = {
692
- "bonus_time" => "5:42:00AM"
693
- }
694
- topic = Topic.find(1)
695
- topic.attributes = attributes
696
- assert_equal Time.local(2000, 1, 1, 5, 42, 0), topic.bonus_time
697
- end
698
- end
699
-
700
- def test_attributes_on_dummy_time_with_invalid_time
701
- # Oracle does not have a TIME datatype.
702
- return true if current_adapter?(:OracleAdapter)
703
-
704
- attributes = {
705
- "bonus_time" => "not a time"
706
- }
707
- topic = Topic.find(1)
708
- topic.attributes = attributes
709
- assert_nil topic.bonus_time
710
- end
711
-
712
- def test_boolean
713
- b_nil = Boolean.create({ "value" => nil })
714
- nil_id = b_nil.id
715
- b_false = Boolean.create({ "value" => false })
716
- false_id = b_false.id
717
- b_true = Boolean.create({ "value" => true })
718
- true_id = b_true.id
719
-
720
- b_nil = Boolean.find(nil_id)
721
- assert_nil b_nil.value
722
- b_false = Boolean.find(false_id)
723
- assert !b_false.value?
724
- b_true = Boolean.find(true_id)
725
- assert b_true.value?
726
- end
727
-
728
- def test_boolean_without_questionmark
729
- b_true = Boolean.create({ "value" => true })
730
- true_id = b_true.id
731
-
732
- subclass = Class.new(Boolean).find true_id
733
- superclass = Boolean.find true_id
734
-
735
- assert_equal superclass.read_attribute(:has_fun), subclass.read_attribute(:has_fun)
736
- end
737
-
738
- def test_boolean_cast_from_string
739
- b_blank = Boolean.create({ "value" => "" })
740
- blank_id = b_blank.id
741
- b_false = Boolean.create({ "value" => "0" })
742
- false_id = b_false.id
743
- b_true = Boolean.create({ "value" => "1" })
744
- true_id = b_true.id
745
-
746
- b_blank = Boolean.find(blank_id)
747
- assert_nil b_blank.value
748
- b_false = Boolean.find(false_id)
749
- assert !b_false.value?
750
- b_true = Boolean.find(true_id)
751
- assert b_true.value?
752
- end
753
-
754
- def test_new_record_returns_boolean
755
- assert_equal false, Topic.new.persisted?
756
- assert_equal true, Topic.find(1).persisted?
757
- end
758
-
759
- def test_dup
760
- topic = Topic.find(1)
761
- duped_topic = nil
762
- assert_nothing_raised { duped_topic = topic.dup }
763
- assert_equal topic.title, duped_topic.title
764
- assert !duped_topic.persisted?
765
-
766
- # test if the attributes have been duped
767
- topic.title = "a"
768
- duped_topic.title = "b"
769
- assert_equal "a", topic.title
770
- assert_equal "b", duped_topic.title
771
-
772
- # test if the attribute values have been duped
773
- duped_topic = topic.dup
774
- duped_topic.title.replace "c"
775
- assert_equal "a", topic.title
776
-
777
- # test if attributes set as part of after_initialize are duped correctly
778
- assert_equal topic.author_email_address, duped_topic.author_email_address
779
-
780
- # test if saved clone object differs from original
781
- duped_topic.save
782
- assert duped_topic.persisted?
783
- assert_not_equal duped_topic.id, topic.id
784
-
785
- duped_topic.reload
786
- assert_equal("c", duped_topic.title)
787
- end
788
-
789
- DeveloperSalary = Struct.new(:amount)
790
- def test_dup_with_aggregate_of_same_name_as_attribute
791
- developer_with_aggregate = Class.new(ActiveRecord::Base) do
792
- self.table_name = 'developers'
793
- composed_of :salary, :class_name => 'BasicsTest::DeveloperSalary', :mapping => [%w(salary amount)]
794
- end
795
-
796
- dev = developer_with_aggregate.find(1)
797
- assert_kind_of DeveloperSalary, dev.salary
798
-
799
- dup = nil
800
- assert_nothing_raised { dup = dev.dup }
801
- assert_kind_of DeveloperSalary, dup.salary
802
- assert_equal dev.salary.amount, dup.salary.amount
803
- assert !dup.persisted?
804
-
805
- # test if the attributes have been dupd
806
- original_amount = dup.salary.amount
807
- dev.salary.amount = 1
808
- assert_equal original_amount, dup.salary.amount
809
-
810
- assert dup.save
811
- assert dup.persisted?
812
- assert_not_equal dup.id, dev.id
813
- end
814
-
815
- def test_dup_does_not_copy_associations
816
- author = authors(:david)
817
- assert_not_equal [], author.posts
818
- author.send(:clear_association_cache)
819
-
820
- author_dup = author.dup
821
- assert_equal [], author_dup.posts
822
- end
823
-
824
- def test_clone_preserves_subtype
825
- clone = nil
826
- assert_nothing_raised { clone = Company.find(3).clone }
827
- assert_kind_of Client, clone
828
- end
829
-
830
- def test_clone_of_new_object_with_defaults
831
- developer = Developer.new
832
- assert !developer.name_changed?
833
- assert !developer.salary_changed?
834
-
835
- cloned_developer = developer.clone
836
- assert !cloned_developer.name_changed?
837
- assert !cloned_developer.salary_changed?
838
- end
839
-
840
- def test_clone_of_new_object_marks_attributes_as_dirty
841
- developer = Developer.new :name => 'Bjorn', :salary => 100000
842
- assert developer.name_changed?
843
- assert developer.salary_changed?
844
-
845
- cloned_developer = developer.clone
846
- assert cloned_developer.name_changed?
847
- assert cloned_developer.salary_changed?
848
- end
849
-
850
- def test_clone_of_new_object_marks_as_dirty_only_changed_attributes
851
- developer = Developer.new :name => 'Bjorn'
852
- assert developer.name_changed? # obviously
853
- assert !developer.salary_changed? # attribute has non-nil default value, so treated as not changed
854
-
855
- cloned_developer = developer.clone
856
- assert cloned_developer.name_changed?
857
- assert !cloned_developer.salary_changed? # ... and cloned instance should behave same
858
- end
859
-
860
- def test_dup_of_saved_object_marks_attributes_as_dirty
861
- developer = Developer.create! :name => 'Bjorn', :salary => 100000
862
- assert !developer.name_changed?
863
- assert !developer.salary_changed?
864
-
865
- cloned_developer = developer.dup
866
- assert cloned_developer.name_changed? # both attributes differ from defaults
867
- assert cloned_developer.salary_changed?
868
- end
869
-
870
- def test_dup_of_saved_object_marks_as_dirty_only_changed_attributes
871
- developer = Developer.create! :name => 'Bjorn'
872
- assert !developer.name_changed? # both attributes of saved object should be treated as not changed
873
- assert !developer.salary_changed?
874
-
875
- cloned_developer = developer.dup
876
- assert cloned_developer.name_changed? # ... but on cloned object should be
877
- assert !cloned_developer.salary_changed? # ... BUT salary has non-nil default which should be treated as not changed on cloned instance
878
- end
879
-
880
- def test_bignum
881
- company = Company.find(1)
882
- company.rating = 2147483647
883
- company.save
884
- company = Company.find(1)
885
- assert_equal 2147483647, company.rating
886
- end
887
-
888
- # TODO: extend defaults tests to other databases!
889
- if current_adapter?(:PostgreSQLAdapter)
890
- def test_default
891
- with_timezone_config default: :local do
892
- default = Default.new
893
-
894
- # fixed dates / times
895
- assert_equal Date.new(2004, 1, 1), default.fixed_date
896
- assert_equal Time.local(2004, 1,1,0,0,0,0), default.fixed_time
897
-
898
- # char types
899
- assert_equal 'Y', default.char1
900
- assert_equal 'a varchar field', default.char2
901
- assert_equal 'a text field', default.char3
902
- end
903
- end
904
-
905
- class Geometric < ActiveRecord::Base; end
906
- def test_geometric_content
907
-
908
- # accepted format notes:
909
- # ()'s aren't required
910
- # values can be a mix of float or integer
911
-
912
- g = Geometric.new(
913
- :a_point => '(5.0, 6.1)',
914
- #:a_line => '((2.0, 3), (5.5, 7.0))' # line type is currently unsupported in postgresql
915
- :a_line_segment => '(2.0, 3), (5.5, 7.0)',
916
- :a_box => '2.0, 3, 5.5, 7.0',
917
- :a_path => '[(2.0, 3), (5.5, 7.0), (8.5, 11.0)]', # [ ] is an open path
918
- :a_polygon => '((2.0, 3), (5.5, 7.0), (8.5, 11.0))',
919
- :a_circle => '<(5.3, 10.4), 2>'
920
- )
921
-
922
- assert g.save
923
-
924
- # Reload and check that we have all the geometric attributes.
925
- h = Geometric.find(g.id)
926
-
927
- assert_equal [5.0, 6.1], h.a_point
928
- assert_equal '[(2,3),(5.5,7)]', h.a_line_segment
929
- assert_equal '(5.5,7),(2,3)', h.a_box # reordered to store upper right corner then bottom left corner
930
- assert_equal '[(2,3),(5.5,7),(8.5,11)]', h.a_path
931
- assert_equal '((2,3),(5.5,7),(8.5,11))', h.a_polygon
932
- assert_equal '<(5.3,10.4),2>', h.a_circle
933
-
934
- # use a geometric function to test for an open path
935
- objs = Geometric.find_by_sql ["select isopen(a_path) from geometrics where id = ?", g.id]
936
-
937
- assert_equal true, objs[0].isopen
938
-
939
- # test alternate formats when defining the geometric types
940
-
941
- g = Geometric.new(
942
- :a_point => '5.0, 6.1',
943
- #:a_line => '((2.0, 3), (5.5, 7.0))' # line type is currently unsupported in postgresql
944
- :a_line_segment => '((2.0, 3), (5.5, 7.0))',
945
- :a_box => '(2.0, 3), (5.5, 7.0)',
946
- :a_path => '((2.0, 3), (5.5, 7.0), (8.5, 11.0))', # ( ) is a closed path
947
- :a_polygon => '2.0, 3, 5.5, 7.0, 8.5, 11.0',
948
- :a_circle => '((5.3, 10.4), 2)'
949
- )
950
-
951
- assert g.save
952
-
953
- # Reload and check that we have all the geometric attributes.
954
- h = Geometric.find(g.id)
955
-
956
- assert_equal [5.0, 6.1], h.a_point
957
- assert_equal '[(2,3),(5.5,7)]', h.a_line_segment
958
- assert_equal '(5.5,7),(2,3)', h.a_box # reordered to store upper right corner then bottom left corner
959
- assert_equal '((2,3),(5.5,7),(8.5,11))', h.a_path
960
- assert_equal '((2,3),(5.5,7),(8.5,11))', h.a_polygon
961
- assert_equal '<(5.3,10.4),2>', h.a_circle
962
-
963
- # use a geometric function to test for an closed path
964
- objs = Geometric.find_by_sql ["select isclosed(a_path) from geometrics where id = ?", g.id]
965
-
966
- assert_equal true, objs[0].isclosed
967
-
968
- # test native ruby formats when defining the geometric types
969
- g = Geometric.new(
970
- :a_point => [5.0, 6.1],
971
- #:a_line => '((2.0, 3), (5.5, 7.0))' # line type is currently unsupported in postgresql
972
- :a_line_segment => '((2.0, 3), (5.5, 7.0))',
973
- :a_box => '(2.0, 3), (5.5, 7.0)',
974
- :a_path => '((2.0, 3), (5.5, 7.0), (8.5, 11.0))', # ( ) is a closed path
975
- :a_polygon => '2.0, 3, 5.5, 7.0, 8.5, 11.0',
976
- :a_circle => '((5.3, 10.4), 2)'
977
- )
978
-
979
- assert g.save
980
-
981
- # Reload and check that we have all the geometric attributes.
982
- h = Geometric.find(g.id)
983
-
984
- assert_equal [5.0, 6.1], h.a_point
985
- assert_equal '[(2,3),(5.5,7)]', h.a_line_segment
986
- assert_equal '(5.5,7),(2,3)', h.a_box # reordered to store upper right corner then bottom left corner
987
- assert_equal '((2,3),(5.5,7),(8.5,11))', h.a_path
988
- assert_equal '((2,3),(5.5,7),(8.5,11))', h.a_polygon
989
- assert_equal '<(5.3,10.4),2>', h.a_circle
990
- end
991
- end
992
-
993
- class NumericData < ActiveRecord::Base
994
- self.table_name = 'numeric_data'
995
-
996
- attribute :my_house_population, Type::Integer.new
997
- attribute :atoms_in_universe, Type::Integer.new
998
- end
999
-
1000
- def test_big_decimal_conditions
1001
- m = NumericData.new(
1002
- :bank_balance => 1586.43,
1003
- :big_bank_balance => BigDecimal("1000234000567.95"),
1004
- :world_population => 6000000000,
1005
- :my_house_population => 3
1006
- )
1007
- assert m.save
1008
- assert_equal 0, NumericData.where("bank_balance > ?", 2000.0).count
1009
- end
1010
-
1011
- def test_numeric_fields
1012
- m = NumericData.new(
1013
- :bank_balance => 1586.43,
1014
- :big_bank_balance => BigDecimal("1000234000567.95"),
1015
- :world_population => 6000000000,
1016
- :my_house_population => 3
1017
- )
1018
- assert m.save
1019
-
1020
- m1 = NumericData.find(m.id)
1021
- assert_not_nil m1
1022
-
1023
- # As with migration_test.rb, we should make world_population >= 2**62
1024
- # to cover 64-bit platforms and test it is a Bignum, but the main thing
1025
- # is that it's an Integer.
1026
- unless current_adapter?(:IBM_DBAdapter)
1027
- assert_kind_of Integer, m1.world_population
1028
- else
1029
- assert_equal 6000000000, m1.world_population
1030
-
1031
- assert_kind_of Fixnum, m1.my_house_population
1032
- assert_equal 3, m1.my_house_population
1033
-
1034
- assert_kind_of BigDecimal, m1.bank_balance
1035
- assert_equal BigDecimal("1586.43"), m1.bank_balance
1036
-
1037
- assert_kind_of BigDecimal, m1.big_bank_balance
1038
- assert_equal BigDecimal("1000234000567.95"), m1.big_bank_balance
1039
- end
1040
-
1041
- def test_numeric_fields_with_scale
1042
- m = NumericData.new(
1043
- :bank_balance => 1586.43122334,
1044
- :big_bank_balance => BigDecimal("234000567.952344"),
1045
- :world_population => 6000000000,
1046
- :my_house_population => 3
1047
- )
1048
- assert m.save
1049
-
1050
- m1 = NumericData.find(m.id)
1051
- assert_not_nil m1
1052
-
1053
- # As with migration_test.rb, we should make world_population >= 2**62
1054
- # to cover 64-bit platforms and test it is a Bignum, but the main thing
1055
- # is that it's an Integer.
1056
- assert_kind_of Integer, m1.world_population
1057
- assert_equal 6000000000, m1.world_population
1058
-
1059
- unless current_adapter?(:IBM_DBAdapter)
1060
- assert_kind_of Fixnum, m1.my_house_population
1061
- else
1062
- assert_kind_of BigDecimal, m1.my_house_population
1063
- end
1064
- assert_equal 3, m1.my_house_population
1065
-
1066
- assert_kind_of BigDecimal, m1.bank_balance
1067
- assert_equal BigDecimal("1586.43"), m1.bank_balance
1068
-
1069
- assert_kind_of BigDecimal, m1.big_bank_balance
1070
- assert_equal BigDecimal("234000567.95"), m1.big_bank_balance
1071
- end
1072
-
1073
- def test_auto_id
1074
- auto = AutoId.new
1075
- auto.save
1076
- assert(auto.id > 0)
1077
- end
1078
-
1079
- def test_sql_injection_via_find
1080
- assert_raise(ActiveRecord::RecordNotFound, ActiveRecord::StatementInvalid) do
1081
- Topic.find("123456 OR id > 0")
1082
- end
1083
- end
1084
-
1085
- def test_column_name_properly_quoted
1086
- col_record = ColumnName.new
1087
- col_record.references = 40
1088
- assert col_record.save
1089
- col_record.references = 41
1090
- assert col_record.save
1091
- assert_not_nil c2 = ColumnName.find(col_record.id)
1092
- assert_equal(41, c2.references)
1093
- end
1094
-
1095
- def test_quoting_arrays
1096
- replies = Reply.all.merge!(:where => [ "id IN (?)", topics(:first).replies.collect(&:id) ]).to_a
1097
- assert_equal topics(:first).replies.size, replies.size
1098
-
1099
- replies = Reply.all.merge!(:where => [ "id IN (?)", [] ]).to_a
1100
- assert_equal 0, replies.size
1101
- end
1102
-
1103
- def test_quote
1104
- author_name = "\\ \001 ' \n \\n \""
1105
- topic = Topic.create('author_name' => author_name)
1106
- assert_equal author_name, Topic.find(topic.id).author_name
1107
- end
1108
-
1109
- def test_toggle_attribute
1110
- assert !topics(:first).approved?
1111
- topics(:first).toggle!(:approved)
1112
- assert topics(:first).approved?
1113
- topic = topics(:first)
1114
- topic.toggle(:approved)
1115
- assert !topic.approved?
1116
- topic.reload
1117
- assert topic.approved?
1118
- end
1119
-
1120
- def test_reload
1121
- t1 = Topic.find(1)
1122
- t2 = Topic.find(1)
1123
- t1.title = "something else"
1124
- t1.save
1125
- t2.reload
1126
- assert_equal t1.title, t2.title
1127
- end
1128
-
1129
- def test_reload_with_exclusive_scope
1130
- dev = DeveloperCalledDavid.first
1131
- dev.update!(name: "NotDavid" )
1132
- assert_equal dev, dev.reload
1133
- end
1134
-
1135
- def test_switching_between_table_name
1136
- assert_difference("GoodJoke.count") do
1137
- Joke.table_name = "cold_jokes"
1138
- Joke.create
1139
-
1140
- Joke.table_name = "funny_jokes"
1141
- Joke.create
1142
- end
1143
- end
1144
-
1145
- def test_clear_cash_when_setting_table_name
1146
- Joke.table_name = "cold_jokes"
1147
- before_columns = Joke.columns
1148
- before_seq = Joke.sequence_name
1149
-
1150
- Joke.table_name = "funny_jokes"
1151
- after_columns = Joke.columns
1152
- after_seq = Joke.sequence_name
1153
-
1154
- assert_not_equal before_columns, after_columns
1155
- assert_not_equal before_seq, after_seq unless before_seq.nil? && after_seq.nil?
1156
- end
1157
-
1158
- def test_dont_clear_sequence_name_when_setting_explicitly
1159
- Joke.sequence_name = "black_jokes_seq"
1160
- Joke.table_name = "cold_jokes"
1161
- before_seq = Joke.sequence_name
1162
-
1163
- Joke.table_name = "funny_jokes"
1164
- after_seq = Joke.sequence_name
1165
-
1166
- assert_equal before_seq, after_seq unless before_seq.nil? && after_seq.nil?
1167
- ensure
1168
- Joke.reset_sequence_name
1169
- end
1170
-
1171
- def test_dont_clear_inheritance_column_when_setting_explicitly
1172
- Joke.inheritance_column = "my_type"
1173
- before_inherit = Joke.inheritance_column
1174
-
1175
- Joke.reset_column_information
1176
- after_inherit = Joke.inheritance_column
1177
-
1178
- assert_equal before_inherit, after_inherit unless before_inherit.blank? && after_inherit.blank?
1179
- end
1180
-
1181
- def test_set_table_name_symbol_converted_to_string
1182
- Joke.table_name = :cold_jokes
1183
- assert_equal 'cold_jokes', Joke.table_name
1184
- end
1185
-
1186
- def test_quoted_table_name_after_set_table_name
1187
- klass = Class.new(ActiveRecord::Base)
1188
-
1189
- klass.table_name = "foo"
1190
- assert_equal "foo", klass.table_name
1191
- assert_equal klass.connection.quote_table_name("foo"), klass.quoted_table_name
1192
-
1193
- klass.table_name = "bar"
1194
- assert_equal "bar", klass.table_name
1195
- assert_equal klass.connection.quote_table_name("bar"), klass.quoted_table_name
1196
- end
1197
-
1198
- def test_set_table_name_with_inheritance
1199
- k = Class.new( ActiveRecord::Base )
1200
- def k.name; "Foo"; end
1201
- def k.table_name; super + "ks"; end
1202
- assert_equal "foosks", k.table_name
1203
- end
1204
-
1205
- def test_sequence_name_with_abstract_class
1206
- ak = Class.new(ActiveRecord::Base)
1207
- ak.abstract_class = true
1208
- k = Class.new(ak)
1209
- k.table_name = "projects"
1210
- orig_name = k.sequence_name
1211
- skip "sequences not supported by db" unless orig_name
1212
- assert_equal k.reset_sequence_name, orig_name
1213
- end
1214
-
1215
- def test_count_with_join
1216
- res = Post.count_by_sql "SELECT COUNT(*) FROM posts LEFT JOIN comments ON posts.id=comments.post_id WHERE posts.#{QUOTED_TYPE} = 'Post'"
1217
-
1218
- res2 = Post.where("posts.#{QUOTED_TYPE} = 'Post'").joins("LEFT JOIN comments ON posts.id=comments.post_id").count
1219
- assert_equal res, res2
1220
-
1221
- res3 = nil
1222
- assert_nothing_raised do
1223
- res3 = Post.where("posts.#{QUOTED_TYPE} = 'Post'").joins("LEFT JOIN comments ON posts.id=comments.post_id").count
1224
- end
1225
- assert_equal res, res3
1226
-
1227
- res4 = Post.count_by_sql "SELECT COUNT(p.id) FROM posts p, comments co WHERE p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id"
1228
- res5 = nil
1229
- assert_nothing_raised do
1230
- res5 = Post.where("p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id").joins("p, comments co").select("p.id").count
1231
- end
1232
-
1233
- assert_equal res4, res5
1234
-
1235
- res6 = Post.count_by_sql "SELECT COUNT(DISTINCT p.id) FROM posts p, comments co WHERE p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id"
1236
- res7 = nil
1237
- assert_nothing_raised do
1238
- res7 = Post.where("p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id").joins("p, comments co").select("p.id").distinct.count
1239
- end
1240
- assert_equal res6, res7
1241
- end
1242
-
1243
- def test_no_limit_offset
1244
- assert_nothing_raised do
1245
- Developer.all.merge!(:offset => 2).to_a
1246
- end
1247
- end
1248
-
1249
- def test_find_last
1250
- last = Developer.last
1251
- assert_equal last, Developer.all.merge!(:order => 'id desc').first
1252
- end
1253
-
1254
- def test_last
1255
- assert_equal Developer.all.merge!(:order => 'id desc').first, Developer.last
1256
- end
1257
-
1258
- def test_all
1259
- developers = Developer.all
1260
- assert_kind_of ActiveRecord::Relation, developers
1261
- assert_equal Developer.all, developers
1262
- end
1263
-
1264
- def test_all_with_conditions
1265
- assert_equal Developer.all.merge!(:order => 'id desc').to_a, Developer.order('id desc').to_a
1266
- end
1267
-
1268
- def test_find_ordered_last
1269
- last = Developer.all.merge!(:order => 'developers.salary ASC').last
1270
- assert_equal last, Developer.all.merge!(:order => 'developers.salary ASC').to_a.last
1271
- end
1272
-
1273
- def test_find_reverse_ordered_last
1274
- last = Developer.all.merge!(:order => 'developers.salary DESC').last
1275
- assert_equal last, Developer.all.merge!(:order => 'developers.salary DESC').to_a.last
1276
- end
1277
-
1278
- def test_find_multiple_ordered_last
1279
- last = Developer.all.merge!(:order => 'developers.name, developers.salary DESC').last
1280
- assert_equal last, Developer.all.merge!(:order => 'developers.name, developers.salary DESC').to_a.last
1281
- end
1282
-
1283
- def test_find_keeps_multiple_order_values
1284
- combined = Developer.all.merge!(:order => 'developers.name, developers.salary').to_a
1285
- assert_equal combined, Developer.all.merge!(:order => ['developers.name', 'developers.salary']).to_a
1286
- end
1287
-
1288
- def test_find_keeps_multiple_group_values
1289
- combined = Developer.all.merge!(:group => 'developers.name, developers.salary, developers.id, developers.created_at, developers.updated_at, developers.created_on, developers.updated_on').to_a
1290
- assert_equal combined, Developer.all.merge!(:group => ['developers.name', 'developers.salary', 'developers.id', 'developers.created_at', 'developers.updated_at', 'developers.created_on', 'developers.updated_on']).to_a
1291
- end
1292
-
1293
- def test_find_symbol_ordered_last
1294
- last = Developer.all.merge!(:order => :salary).last
1295
- assert_equal last, Developer.all.merge!(:order => :salary).to_a.last
1296
- end
1297
-
1298
- def test_abstract_class
1299
- assert !ActiveRecord::Base.abstract_class?
1300
- assert LoosePerson.abstract_class?
1301
- assert !LooseDescendant.abstract_class?
1302
- end
1303
-
1304
- def test_abstract_class_table_name
1305
- assert_nil AbstractCompany.table_name
1306
- end
1307
-
1308
- def test_descends_from_active_record
1309
- assert !ActiveRecord::Base.descends_from_active_record?
1310
-
1311
- # Abstract subclass of AR::Base.
1312
- assert LoosePerson.descends_from_active_record?
1313
-
1314
- # Concrete subclass of an abstract class.
1315
- assert LooseDescendant.descends_from_active_record?
1316
-
1317
- # Concrete subclass of AR::Base.
1318
- assert TightPerson.descends_from_active_record?
1319
-
1320
- # Concrete subclass of a concrete class but has no type column.
1321
- assert TightDescendant.descends_from_active_record?
1322
-
1323
- # Concrete subclass of AR::Base.
1324
- assert Post.descends_from_active_record?
1325
-
1326
- # Abstract subclass of a concrete class which has a type column.
1327
- # This is pathological, as you'll never have Sub < Abstract < Concrete.
1328
- assert !StiPost.descends_from_active_record?
1329
-
1330
- # Concrete subclasses an abstract class which has a type column.
1331
- assert !SubStiPost.descends_from_active_record?
1332
- end
1333
-
1334
- def test_find_on_abstract_base_class_doesnt_use_type_condition
1335
- old_class = LooseDescendant
1336
- Object.send :remove_const, :LooseDescendant
1337
-
1338
- descendant = old_class.create! :first_name => 'bob'
1339
- assert_not_nil LoosePerson.find(descendant.id), "Should have found instance of LooseDescendant when finding abstract LoosePerson: #{descendant.inspect}"
1340
- ensure
1341
- unless Object.const_defined?(:LooseDescendant)
1342
- Object.const_set :LooseDescendant, old_class
1343
- end
1344
- end
1345
-
1346
- def test_assert_queries
1347
- query = lambda { ActiveRecord::Base.connection.execute 'select count(*) from developers' }
1348
- assert_queries(2) { 2.times { query.call } }
1349
- assert_queries 1, &query
1350
- assert_no_queries { assert true }
1351
- end
1352
-
1353
- def test_benchmark_with_log_level
1354
- original_logger = ActiveRecord::Base.logger
1355
- log = StringIO.new
1356
- ActiveRecord::Base.logger = ActiveSupport::Logger.new(log)
1357
- ActiveRecord::Base.logger.level = Logger::WARN
1358
- ActiveRecord::Base.benchmark("Debug Topic Count", :level => :debug) { Topic.count }
1359
- ActiveRecord::Base.benchmark("Warn Topic Count", :level => :warn) { Topic.count }
1360
- ActiveRecord::Base.benchmark("Error Topic Count", :level => :error) { Topic.count }
1361
- assert_no_match(/Debug Topic Count/, log.string)
1362
- assert_match(/Warn Topic Count/, log.string)
1363
- assert_match(/Error Topic Count/, log.string)
1364
- ensure
1365
- ActiveRecord::Base.logger = original_logger
1366
- end
1367
-
1368
- def test_benchmark_with_use_silence
1369
- original_logger = ActiveRecord::Base.logger
1370
- log = StringIO.new
1371
- ActiveRecord::Base.logger = ActiveSupport::Logger.new(log)
1372
- ActiveRecord::Base.benchmark("Logging", :level => :debug, :silence => false) { ActiveRecord::Base.logger.debug "Quiet" }
1373
- assert_match(/Quiet/, log.string)
1374
- ensure
1375
- ActiveRecord::Base.logger = original_logger
1376
- end
1377
-
1378
- def test_compute_type_success
1379
- assert_equal Author, ActiveRecord::Base.send(:compute_type, 'Author')
1380
- end
1381
-
1382
- def test_compute_type_nonexistent_constant
1383
- e = assert_raises NameError do
1384
- ActiveRecord::Base.send :compute_type, 'NonexistentModel'
1385
- end
1386
- assert_equal 'uninitialized constant ActiveRecord::Base::NonexistentModel', e.message
1387
- assert_equal 'ActiveRecord::Base::NonexistentModel', e.name
1388
- end
1389
-
1390
- def test_compute_type_no_method_error
1391
- ActiveSupport::Dependencies.stubs(:safe_constantize).raises(NoMethodError)
1392
- assert_raises NoMethodError do
1393
- ActiveRecord::Base.send :compute_type, 'InvalidModel'
1394
- end
1395
- end
1396
-
1397
- def test_compute_type_on_undefined_method
1398
- error = nil
1399
- begin
1400
- Class.new(Author) do
1401
- alias_method :foo, :bar
1402
- end
1403
- rescue => e
1404
- error = e
1405
- end
1406
-
1407
- ActiveSupport::Dependencies.stubs(:safe_constantize).raises(e)
1408
-
1409
- exception = assert_raises NameError do
1410
- ActiveRecord::Base.send :compute_type, 'InvalidModel'
1411
- end
1412
- assert_equal error.message, exception.message
1413
- end
1414
-
1415
- def test_compute_type_argument_error
1416
- ActiveSupport::Dependencies.stubs(:safe_constantize).raises(ArgumentError)
1417
- assert_raises ArgumentError do
1418
- ActiveRecord::Base.send :compute_type, 'InvalidModel'
1419
- end
1420
- end
1421
-
1422
- def test_clear_cache!
1423
- # preheat cache
1424
- c1 = Post.connection.schema_cache.columns('posts')
1425
- ActiveRecord::Base.clear_cache!
1426
- c2 = Post.connection.schema_cache.columns('posts')
1427
- c1.each_with_index do |v, i|
1428
- assert_not_same v, c2[i]
1429
- end
1430
- assert_equal c1, c2
1431
- end
1432
-
1433
- def test_current_scope_is_reset
1434
- Object.const_set :UnloadablePost, Class.new(ActiveRecord::Base)
1435
- UnloadablePost.send(:current_scope=, UnloadablePost.all)
1436
-
1437
- UnloadablePost.unloadable
1438
- assert_not_nil ActiveRecord::Scoping::ScopeRegistry.value_for(:current_scope, "UnloadablePost")
1439
- ActiveSupport::Dependencies.remove_unloadable_constants!
1440
- assert_nil ActiveRecord::Scoping::ScopeRegistry.value_for(:current_scope, "UnloadablePost")
1441
- ensure
1442
- Object.class_eval{ remove_const :UnloadablePost } if defined?(UnloadablePost)
1443
- end
1444
-
1445
- def test_marshal_round_trip
1446
- expected = posts(:welcome)
1447
- marshalled = Marshal.dump(expected)
1448
- actual = Marshal.load(marshalled)
1449
-
1450
- assert_equal expected.attributes, actual.attributes
1451
- end
1452
-
1453
- def test_marshal_new_record_round_trip
1454
- marshalled = Marshal.dump(Post.new)
1455
- post = Marshal.load(marshalled)
1456
-
1457
- assert post.new_record?, "should be a new record"
1458
- end
1459
-
1460
- def test_marshalling_with_associations
1461
- post = Post.new
1462
- post.comments.build
1463
-
1464
- marshalled = Marshal.dump(post)
1465
- post = Marshal.load(marshalled)
1466
-
1467
- assert_equal 1, post.comments.length
1468
- end
1469
-
1470
- if Process.respond_to?(:fork) && !in_memory_db?
1471
- def test_marshal_between_processes
1472
- # Define a new model to ensure there are no caches
1473
- if self.class.const_defined?("Post", false)
1474
- flunk "there should be no post constant"
1475
- end
1476
-
1477
- self.class.const_set("Post", Class.new(ActiveRecord::Base) {
1478
- has_many :comments
1479
- })
1480
-
1481
- rd, wr = IO.pipe
1482
- rd.binmode
1483
- wr.binmode
1484
-
1485
- ActiveRecord::Base.connection_handler.clear_all_connections!
1486
-
1487
- fork do
1488
- rd.close
1489
- post = Post.new
1490
- post.comments.build
1491
- wr.write Marshal.dump(post)
1492
- wr.close
1493
- end
1494
-
1495
- wr.close
1496
- assert Marshal.load rd.read
1497
- rd.close
1498
- end
1499
- end
1500
-
1501
- def test_marshalling_new_record_round_trip_with_associations
1502
- post = Post.new
1503
- post.comments.build
1504
-
1505
- post = Marshal.load(Marshal.dump(post))
1506
-
1507
- assert post.new_record?, "should be a new record"
1508
- end
1509
-
1510
- def test_attribute_names
1511
- assert_equal ["id", "type", "firm_id", "firm_name", "name", "client_of", "rating", "account_id", "description"],
1512
- Company.attribute_names
1513
- end
1514
-
1515
- def test_attribute_names_on_table_not_exists
1516
- assert_equal [], NonExistentTable.attribute_names
1517
- end
1518
-
1519
- def test_attribute_names_on_abstract_class
1520
- assert_equal [], AbstractCompany.attribute_names
1521
- end
1522
-
1523
- def test_touch_should_raise_error_on_a_new_object
1524
- company = Company.new(:rating => 1, :name => "37signals", :firm_name => "37signals")
1525
- assert_raises(ActiveRecord::ActiveRecordError) do
1526
- company.touch :updated_at
1527
- end
1528
- end
1529
-
1530
- def test_uniq_delegates_to_scoped
1531
- scope = stub
1532
- Bird.stubs(:all).returns(mock(:uniq => scope))
1533
- assert_equal scope, Bird.uniq
1534
- end
1535
-
1536
- def test_distinct_delegates_to_scoped
1537
- scope = stub
1538
- Bird.stubs(:all).returns(mock(:distinct => scope))
1539
- assert_equal scope, Bird.distinct
1540
- end
1541
-
1542
- def test_table_name_with_2_abstract_subclasses
1543
- assert_equal "photos", Photo.table_name
1544
- end
1545
-
1546
- def test_column_types_typecast
1547
- topic = Topic.first
1548
- assert_not_equal 't.lo', topic.author_name
1549
-
1550
- attrs = topic.attributes.dup
1551
- attrs.delete 'id'
1552
-
1553
- typecast = Class.new(ActiveRecord::Type::Value) {
1554
- def type_cast value
1555
- "t.lo"
1556
- end
1557
- }
1558
-
1559
- types = { 'author_name' => typecast.new }
1560
- topic = Topic.instantiate(attrs, types)
1561
-
1562
- assert_equal 't.lo', topic.author_name
1563
- end
1564
-
1565
- def test_typecasting_aliases
1566
- assert_equal 10, Topic.select('10 as tenderlove').first.tenderlove
1567
- end
1568
-
1569
- def test_slice
1570
- company = Company.new(:rating => 1, :name => "37signals", :firm_name => "37signals")
1571
- hash = company.slice(:name, :rating, "arbitrary_method")
1572
- assert_equal hash[:name], company.name
1573
- assert_equal hash['name'], company.name
1574
- assert_equal hash[:rating], company.rating
1575
- assert_equal hash['arbitrary_method'], company.arbitrary_method
1576
- assert_equal hash[:arbitrary_method], company.arbitrary_method
1577
- assert_nil hash[:firm_name]
1578
- assert_nil hash['firm_name']
1579
- end
1580
-
1581
- def test_default_values_are_deeply_dupped
1582
- company = Company.new
1583
- company.description << "foo"
1584
- assert_equal "", Company.new.description
1585
- end
1586
-
1587
- test "scoped can take a values hash" do
1588
- klass = Class.new(ActiveRecord::Base)
1589
- assert_equal ['foo'], klass.all.merge!(select: 'foo').select_values
1590
- end
1591
-
1592
- test "connection_handler can be overridden" do
1593
- klass = Class.new(ActiveRecord::Base)
1594
- orig_handler = klass.connection_handler
1595
- new_handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new
1596
- thread_connection_handler = nil
1597
-
1598
- t = Thread.new do
1599
- klass.connection_handler = new_handler
1600
- thread_connection_handler = klass.connection_handler
1601
- end
1602
- t.join
1603
-
1604
- assert_equal klass.connection_handler, orig_handler
1605
- assert_equal thread_connection_handler, new_handler
1606
- end
1607
-
1608
- test "new threads get default the default connection handler" do
1609
- klass = Class.new(ActiveRecord::Base)
1610
- orig_handler = klass.connection_handler
1611
- handler = nil
1612
-
1613
- t = Thread.new do
1614
- handler = klass.connection_handler
1615
- end
1616
- t.join
1617
-
1618
- assert_equal handler, orig_handler
1619
- assert_equal klass.connection_handler, orig_handler
1620
- assert_equal klass.default_connection_handler, orig_handler
1621
- end
1622
-
1623
- test "changing a connection handler in a main thread does not poison the other threads" do
1624
- klass = Class.new(ActiveRecord::Base)
1625
- orig_handler = klass.connection_handler
1626
- new_handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new
1627
- after_handler = nil
1628
- latch1 = ActiveSupport::Concurrency::Latch.new
1629
- latch2 = ActiveSupport::Concurrency::Latch.new
1630
-
1631
- t = Thread.new do
1632
- klass.connection_handler = new_handler
1633
- latch1.release
1634
- latch2.await
1635
- after_handler = klass.connection_handler
1636
- end
1637
-
1638
- latch1.await
1639
-
1640
- klass.connection_handler = orig_handler
1641
- latch2.release
1642
- t.join
1643
-
1644
- assert_equal after_handler, new_handler
1645
- assert_equal orig_handler, klass.connection_handler
1646
- end
1647
-
1648
- # Note: This is a performance optimization for Array#uniq and Hash#[] with
1649
- # AR::Base objects. If the future has made this irrelevant, feel free to
1650
- # delete this.
1651
- test "records without an id have unique hashes" do
1652
- assert_not_equal Post.new.hash, Post.new.hash
1653
- end
1654
-
1655
- test "resetting column information doesn't remove attribute methods" do
1656
- topic = topics(:first)
1657
-
1658
- assert_not topic.id_changed?
1659
-
1660
- Topic.reset_column_information
1661
-
1662
- assert_not topic.id_changed?
1663
- end
1664
- end
1
+ require "cases/helper"
2
+ require 'models/post'
3
+ require 'models/author'
4
+ require 'models/topic'
5
+ require 'models/reply'
6
+ require 'models/category'
7
+ require 'models/company'
8
+ require 'models/customer'
9
+ require 'models/developer'
10
+ require 'models/computer'
11
+ require 'models/project'
12
+ require 'models/default'
13
+ require 'models/auto_id'
14
+ require 'models/boolean'
15
+ require 'models/column_name'
16
+ require 'models/subscriber'
17
+ require 'models/keyboard'
18
+ require 'models/comment'
19
+ require 'models/minimalistic'
20
+ require 'models/warehouse_thing'
21
+ require 'models/parrot'
22
+ require 'models/person'
23
+ require 'models/edge'
24
+ require 'models/joke'
25
+ require 'models/bird'
26
+ require 'models/car'
27
+ require 'models/bulb'
28
+ require 'rexml/document'
29
+ require 'concurrent/atomic/count_down_latch'
30
+
31
+ class FirstAbstractClass < ActiveRecord::Base
32
+ self.abstract_class = true
33
+ end
34
+ class SecondAbstractClass < FirstAbstractClass
35
+ self.abstract_class = true
36
+ end
37
+ class Photo < SecondAbstractClass; end
38
+ class Category < ActiveRecord::Base; end
39
+ class Categorization < ActiveRecord::Base; end
40
+ class Smarts < ActiveRecord::Base; end
41
+ class CreditCard < ActiveRecord::Base
42
+ class PinNumber < ActiveRecord::Base
43
+ class CvvCode < ActiveRecord::Base; end
44
+ class SubCvvCode < CvvCode; end
45
+ end
46
+ class SubPinNumber < PinNumber; end
47
+ class Brand < Category; end
48
+ end
49
+ class MasterCreditCard < ActiveRecord::Base; end
50
+ class Post < ActiveRecord::Base; end
51
+ class Computer < ActiveRecord::Base; end
52
+ class NonExistentTable < ActiveRecord::Base; end
53
+ class TestOracleDefault < ActiveRecord::Base; end
54
+
55
+ class ReadonlyTitlePost < Post
56
+ attr_readonly :title
57
+ end
58
+
59
+ class Weird < ActiveRecord::Base; end
60
+
61
+ class Boolean < ActiveRecord::Base
62
+ def has_fun
63
+ super
64
+ end
65
+ end
66
+
67
+ class LintTest < ActiveRecord::TestCase
68
+ include ActiveModel::Lint::Tests
69
+
70
+ class LintModel < ActiveRecord::Base; end
71
+
72
+ def setup
73
+ @model = LintModel.new
74
+ end
75
+ end
76
+
77
+ class BasicsTest < ActiveRecord::TestCase
78
+ #fixtures :topics, :companies, :developers, :projects, :computers, :accounts, :minimalistics, 'warehouse_things', :authors, :categorizations, :categories, :posts
79
+ fixtures :topics, :companies, :developers, :projects, :computers, :accounts, :minimalistics, 'warehouse_things', :categorizations, :categories, :posts
80
+
81
+ def test_column_names_are_escaped
82
+ puts "In base_test test_column_names_are_escaped"
83
+ conn = ActiveRecord::Base.connection
84
+ classname = conn.class.name[/[^:]*$/]
85
+ badchar = {
86
+ 'SQLite3Adapter' => '"',
87
+ 'Mysql2Adapter' => '`',
88
+ 'PostgreSQLAdapter' => '"',
89
+ 'OracleAdapter' => '"',
90
+ 'IBM_DBAdapter' => '"',
91
+ 'FbAdapter' => '"'
92
+ }.fetch(classname) {
93
+ raise "need a bad char for #{classname}"
94
+ }
95
+
96
+ quoted = conn.quote_column_name "foo#{badchar}bar"
97
+ if current_adapter?(:OracleAdapter)
98
+ # Oracle does not allow double quotes in table and column names at all
99
+ # therefore quoting removes them
100
+ assert_equal("#{badchar}foobar#{badchar}", quoted)
101
+ elsif current_adapter?(:IBM_DBAdapter)
102
+ assert_equal("foo#{badchar}bar", quoted)
103
+ else
104
+ assert_equal("#{badchar}foo#{badchar * 2}bar#{badchar}", quoted)
105
+ end
106
+ end
107
+
108
+ def test_columns_should_obey_set_primary_key
109
+ puts "In base_test test_columns_should_obey_set_primary_key"
110
+ pk = Subscriber.columns_hash[Subscriber.primary_key]
111
+ assert_equal 'nick', pk.name, 'nick should be primary key'
112
+ end
113
+
114
+ def test_primary_key_with_no_id
115
+ puts "In base_test test_primary_key_with_no_id"
116
+ assert_nil Edge.primary_key
117
+ end
118
+
119
+ unless current_adapter?(:PostgreSQLAdapter, :OracleAdapter, :SQLServerAdapter, :IBM_DBAdapter, :FbAdapter)
120
+ def test_limit_with_comma
121
+ puts "In base_test test_limit_with_comma"
122
+ assert_deprecated do
123
+ assert Topic.limit("1,2").to_a
124
+ end
125
+ end
126
+ end
127
+
128
+ def test_many_mutations
129
+ puts "In base_test test_many_mutations"
130
+ car = Car.new name: "<3<3<3"
131
+ car.engines_count = 0
132
+ 20_000.times { car.engines_count += 1 }
133
+ assert car.save
134
+ end
135
+
136
+ def test_limit_without_comma
137
+ puts "In base_test test_limit_without_comma"
138
+ assert_equal 1, Topic.limit("1").to_a.length
139
+ assert_equal 1, Topic.limit(1).to_a.length
140
+ end
141
+
142
+ def test_limit_should_take_value_from_latest_limit
143
+ puts "In base_test test_limit_should_take_value_from_latest_limit"
144
+ assert_equal 1, Topic.limit(2).limit(1).to_a.length
145
+ end
146
+
147
+ def test_invalid_limit
148
+ puts "In base_test test_invalid_limit"
149
+ assert_raises(ArgumentError) do
150
+ Topic.limit("asdfadf").to_a
151
+ end
152
+ end
153
+
154
+ def test_limit_should_sanitize_sql_injection_for_limit_without_commas
155
+ puts "In base_test test_limit_should_sanitize_sql_injection_for_limit_without_commas"
156
+ assert_raises(ArgumentError) do
157
+ Topic.limit("1 select * from schema").to_a
158
+ end
159
+ end
160
+
161
+ def test_limit_should_sanitize_sql_injection_for_limit_with_commas
162
+ puts "In base_test test_limit_should_sanitize_sql_injection_for_limit_with_commas"
163
+ assert_deprecated do
164
+ assert_raises(ArgumentError) do
165
+ Topic.limit("1, 7 procedure help()").to_a
166
+ end
167
+ end
168
+ end
169
+
170
+ def test_select_symbol
171
+ puts "In base_test test_select_symbol"
172
+ topic_ids = Topic.select(:id).map(&:id).sort
173
+ assert_equal Topic.pluck(:id).sort, topic_ids
174
+ end
175
+
176
+ def test_table_exists
177
+ puts "In base_test test_table_exists"
178
+ assert !NonExistentTable.table_exists?
179
+ assert Topic.table_exists?
180
+ end
181
+
182
+ def test_preserving_date_objects
183
+ puts "In base_test test_preserving_date_objects"
184
+ # Oracle enhanced adapter allows to define Date attributes in model class (see topic.rb)
185
+ assert_kind_of(
186
+ Date, Topic.find(1).last_read,
187
+ "The last_read attribute should be of the Date class"
188
+ )
189
+ end
190
+
191
+ def test_previously_changed
192
+ puts "In base_test test_previously_changed"
193
+ topic = Topic.first
194
+ topic.title = '<3<3<3'
195
+ assert_equal({}, topic.previous_changes)
196
+
197
+ topic.save!
198
+ expected = ["The First Topic", "<3<3<3"]
199
+ assert_equal(expected, topic.previous_changes['title'])
200
+ end
201
+
202
+ def test_previously_changed_dup
203
+ puts "In base_test test_previously_changed_dup"
204
+ topic = Topic.first
205
+ topic.title = '<3<3<3'
206
+ topic.save!
207
+
208
+ t2 = topic.dup
209
+
210
+ assert_equal(topic.previous_changes, t2.previous_changes)
211
+
212
+ topic.title = "lolwut"
213
+ topic.save!
214
+
215
+ assert_not_equal(topic.previous_changes, t2.previous_changes)
216
+ end
217
+
218
+ def test_preserving_time_objects
219
+ puts "In base_test test_preserving_time_objects"
220
+ assert_kind_of(
221
+ Time, Topic.find(1).bonus_time,
222
+ "The bonus_time attribute should be of the Time class"
223
+ )
224
+
225
+ assert_kind_of(
226
+ Time, Topic.find(1).written_on,
227
+ "The written_on attribute should be of the Time class"
228
+ )
229
+
230
+ # For adapters which support microsecond resolution.
231
+ if subsecond_precision_supported?
232
+ assert_equal 11, Topic.find(1).written_on.sec
233
+ assert_equal 223300, Topic.find(1).written_on.usec
234
+ assert_equal 9900, Topic.find(2).written_on.usec
235
+ assert_equal 129346, Topic.find(3).written_on.usec
236
+ end
237
+ end
238
+
239
+ def test_preserving_time_objects_with_local_time_conversion_to_default_timezone_utc
240
+ puts "In base_test test_preserving_time_objects_with_local_time_conversion_to_default_timezone_utc"
241
+ with_env_tz eastern_time_zone do
242
+ with_timezone_config default: :utc do
243
+ time = Time.local(2000)
244
+ topic = Topic.create('written_on' => time)
245
+ saved_time = Topic.find(topic.id).reload.written_on
246
+ assert_equal time, saved_time
247
+ assert_equal [0, 0, 0, 1, 1, 2000, 6, 1, false, "EST"], time.to_a
248
+ assert_equal [0, 0, 5, 1, 1, 2000, 6, 1, false, "UTC"], saved_time.to_a
249
+ end
250
+ end
251
+ end
252
+
253
+ def test_preserving_time_objects_with_time_with_zone_conversion_to_default_timezone_utc
254
+ puts "In base_test test_preserving_time_objects_with_time_with_zone_conversion_to_default_timezone_utc"
255
+ with_env_tz eastern_time_zone do
256
+ with_timezone_config default: :utc do
257
+ Time.use_zone 'Central Time (US & Canada)' do
258
+ time = Time.zone.local(2000)
259
+ topic = Topic.create('written_on' => time)
260
+ saved_time = Topic.find(topic.id).reload.written_on
261
+ assert_equal time, saved_time
262
+ assert_equal [0, 0, 0, 1, 1, 2000, 6, 1, false, "CST"], time.to_a
263
+ assert_equal [0, 0, 6, 1, 1, 2000, 6, 1, false, "UTC"], saved_time.to_a
264
+ end
265
+ end
266
+ end
267
+ end
268
+
269
+ def test_preserving_time_objects_with_utc_time_conversion_to_default_timezone_local
270
+ puts "In base_test test_preserving_time_objects_with_utc_time_conversion_to_default_timezone_local"
271
+ with_env_tz eastern_time_zone do
272
+ with_timezone_config default: :local do
273
+ time = Time.utc(2000)
274
+ topic = Topic.create('written_on' => time)
275
+ saved_time = Topic.find(topic.id).reload.written_on
276
+ assert_equal time, saved_time
277
+ assert_equal [0, 0, 0, 1, 1, 2000, 6, 1, false, "UTC"], time.to_a
278
+ assert_equal [0, 0, 19, 31, 12, 1999, 5, 365, false, "EST"], saved_time.to_a
279
+ end
280
+ end
281
+ end
282
+
283
+ def test_preserving_time_objects_with_time_with_zone_conversion_to_default_timezone_local
284
+ puts "In base_test test_preserving_time_objects_with_time_with_zone_conversion_to_default_timezone_local"
285
+ with_env_tz eastern_time_zone do
286
+ with_timezone_config default: :local do
287
+ Time.use_zone 'Central Time (US & Canada)' do
288
+ time = Time.zone.local(2000)
289
+ topic = Topic.create('written_on' => time)
290
+ saved_time = Topic.find(topic.id).reload.written_on
291
+ assert_equal time, saved_time
292
+ assert_equal [0, 0, 0, 1, 1, 2000, 6, 1, false, "CST"], time.to_a
293
+ assert_equal [0, 0, 1, 1, 1, 2000, 6, 1, false, "EST"], saved_time.to_a
294
+ end
295
+ end
296
+ end
297
+ end
298
+
299
+ def eastern_time_zone
300
+ if Gem.win_platform?
301
+ "EST5EDT"
302
+ else
303
+ "America/New_York"
304
+ end
305
+ end
306
+
307
+ def test_custom_mutator
308
+ puts "In base_test test_custom_mutator"
309
+ topic = Topic.find(1)
310
+ # This mutator is protected in the class definition
311
+ topic.send(:approved=, true)
312
+ assert topic.instance_variable_get("@custom_approved")
313
+ end
314
+
315
+ def test_initialize_with_attributes
316
+ puts "In base_test test_initialize_with_attributes"
317
+ topic = Topic.new({
318
+ "title" => "initialized from attributes", "written_on" => "2003-12-12 23:23"
319
+ })
320
+
321
+ assert_equal("initialized from attributes", topic.title)
322
+ end
323
+
324
+ def test_initialize_with_invalid_attribute
325
+ puts "In base_test test_initialize_with_invalid_attribute"
326
+ Topic.new({ "title" => "test",
327
+ "last_read(1i)" => "2005", "last_read(2i)" => "2", "last_read(3i)" => "31"})
328
+ rescue ActiveRecord::MultiparameterAssignmentErrors => ex
329
+ assert_equal(1, ex.errors.size)
330
+ assert_equal("last_read", ex.errors[0].attribute)
331
+ end
332
+
333
+ def test_create_after_initialize_without_block
334
+ puts "In base_test test_create_after_initialize_without_block"
335
+ cb = CustomBulb.create(:name => 'Dude')
336
+ assert_equal('Dude', cb.name)
337
+ assert_equal(true, cb.frickinawesome)
338
+ end
339
+
340
+ def test_create_after_initialize_with_block
341
+ puts "In base_test test_create_after_initialize_with_block"
342
+ cb = CustomBulb.create {|c| c.name = 'Dude' }
343
+ assert_equal('Dude', cb.name)
344
+ assert_equal(true, cb.frickinawesome)
345
+ end
346
+
347
+ def test_create_after_initialize_with_array_param
348
+ puts "In base_test test_create_after_initialize_with_array_param"
349
+ cbs = CustomBulb.create([{ name: 'Dude' }, { name: 'Bob' }])
350
+ assert_equal 'Dude', cbs[0].name
351
+ assert_equal 'Bob', cbs[1].name
352
+ assert cbs[0].frickinawesome
353
+ assert !cbs[1].frickinawesome
354
+ end
355
+
356
+ def test_load
357
+ puts "In base_test test_load"
358
+ topics = Topic.all.merge!(:order => 'id').to_a
359
+ assert_equal(5, topics.size)
360
+ assert_equal(topics(:first).title, topics.first.title)
361
+ end
362
+
363
+ def test_load_with_condition
364
+ puts "In base_test test_load_with_condition"
365
+ topics = Topic.all.merge!(:where => "author_name = 'Mary'").to_a
366
+
367
+ assert_equal(1, topics.size)
368
+ assert_equal(topics(:second).title, topics.first.title)
369
+ end
370
+
371
+ GUESSED_CLASSES = [Category, Smarts, CreditCard, CreditCard::PinNumber, CreditCard::PinNumber::CvvCode, CreditCard::SubPinNumber, CreditCard::Brand, MasterCreditCard]
372
+
373
+ def test_table_name_guesses
374
+ puts "In base_test test_table_name_guesses"
375
+ assert_equal "topics", Topic.table_name
376
+
377
+ assert_equal "categories", Category.table_name
378
+ assert_equal "smarts", Smarts.table_name
379
+ assert_equal "credit_cards", CreditCard.table_name
380
+ assert_equal "credit_card_pin_numbers", CreditCard::PinNumber.table_name
381
+ assert_equal "credit_card_pin_number_cvv_codes", CreditCard::PinNumber::CvvCode.table_name
382
+ assert_equal "credit_card_pin_numbers", CreditCard::SubPinNumber.table_name
383
+ assert_equal "categories", CreditCard::Brand.table_name
384
+ assert_equal "master_credit_cards", MasterCreditCard.table_name
385
+ ensure
386
+ GUESSED_CLASSES.each(&:reset_table_name)
387
+ end
388
+
389
+ def test_singular_table_name_guesses
390
+ puts "In base_test test_singular_table_name_guesses"
391
+ ActiveRecord::Base.pluralize_table_names = false
392
+ GUESSED_CLASSES.each(&:reset_table_name)
393
+
394
+ assert_equal "category", Category.table_name
395
+ assert_equal "smarts", Smarts.table_name
396
+ assert_equal "credit_card", CreditCard.table_name
397
+ assert_equal "credit_card_pin_number", CreditCard::PinNumber.table_name
398
+ assert_equal "credit_card_pin_number_cvv_code", CreditCard::PinNumber::CvvCode.table_name
399
+ assert_equal "credit_card_pin_number", CreditCard::SubPinNumber.table_name
400
+ assert_equal "category", CreditCard::Brand.table_name
401
+ assert_equal "master_credit_card", MasterCreditCard.table_name
402
+ ensure
403
+ ActiveRecord::Base.pluralize_table_names = true
404
+ GUESSED_CLASSES.each(&:reset_table_name)
405
+ end
406
+
407
+ def test_table_name_guesses_with_prefixes_and_suffixes
408
+ puts "In base_test test_table_name_guesses_with_prefixes_and_suffixes"
409
+ ActiveRecord::Base.table_name_prefix = "test_"
410
+ Category.reset_table_name
411
+ assert_equal "test_categories", Category.table_name
412
+ ActiveRecord::Base.table_name_suffix = "_test"
413
+ Category.reset_table_name
414
+ assert_equal "test_categories_test", Category.table_name
415
+ ActiveRecord::Base.table_name_prefix = ""
416
+ Category.reset_table_name
417
+ assert_equal "categories_test", Category.table_name
418
+ ActiveRecord::Base.table_name_suffix = ""
419
+ Category.reset_table_name
420
+ assert_equal "categories", Category.table_name
421
+ ensure
422
+ ActiveRecord::Base.table_name_prefix = ""
423
+ ActiveRecord::Base.table_name_suffix = ""
424
+ GUESSED_CLASSES.each(&:reset_table_name)
425
+ end
426
+
427
+ def test_singular_table_name_guesses_with_prefixes_and_suffixes
428
+ puts "In base_test test_singular_table_name_guesses_with_prefixes_and_suffixes"
429
+ ActiveRecord::Base.pluralize_table_names = false
430
+
431
+ ActiveRecord::Base.table_name_prefix = "test_"
432
+ Category.reset_table_name
433
+ assert_equal "test_category", Category.table_name
434
+ ActiveRecord::Base.table_name_suffix = "_test"
435
+ Category.reset_table_name
436
+ assert_equal "test_category_test", Category.table_name
437
+ ActiveRecord::Base.table_name_prefix = ""
438
+ Category.reset_table_name
439
+ assert_equal "category_test", Category.table_name
440
+ ActiveRecord::Base.table_name_suffix = ""
441
+ Category.reset_table_name
442
+ assert_equal "category", Category.table_name
443
+ ensure
444
+ ActiveRecord::Base.pluralize_table_names = true
445
+ ActiveRecord::Base.table_name_prefix = ""
446
+ ActiveRecord::Base.table_name_suffix = ""
447
+ GUESSED_CLASSES.each(&:reset_table_name)
448
+ end
449
+
450
+ def test_table_name_guesses_with_inherited_prefixes_and_suffixes
451
+ puts "In base_test test_table_name_guesses_with_inherited_prefixes_and_suffixes"
452
+ GUESSED_CLASSES.each(&:reset_table_name)
453
+
454
+ CreditCard.table_name_prefix = "test_"
455
+ CreditCard.reset_table_name
456
+ Category.reset_table_name
457
+ assert_equal "test_credit_cards", CreditCard.table_name
458
+ assert_equal "categories", Category.table_name
459
+ CreditCard.table_name_suffix = "_test"
460
+ CreditCard.reset_table_name
461
+ Category.reset_table_name
462
+ assert_equal "test_credit_cards_test", CreditCard.table_name
463
+ assert_equal "categories", Category.table_name
464
+ CreditCard.table_name_prefix = ""
465
+ CreditCard.reset_table_name
466
+ Category.reset_table_name
467
+ assert_equal "credit_cards_test", CreditCard.table_name
468
+ assert_equal "categories", Category.table_name
469
+ CreditCard.table_name_suffix = ""
470
+ CreditCard.reset_table_name
471
+ Category.reset_table_name
472
+ assert_equal "credit_cards", CreditCard.table_name
473
+ assert_equal "categories", Category.table_name
474
+ ensure
475
+ CreditCard.table_name_prefix = ""
476
+ CreditCard.table_name_suffix = ""
477
+ GUESSED_CLASSES.each(&:reset_table_name)
478
+ end
479
+
480
+ def test_singular_table_name_guesses_for_individual_table
481
+ puts "In base_test test_singular_table_name_guesses_for_individual_table"
482
+ Post.pluralize_table_names = false
483
+ Post.reset_table_name
484
+ assert_equal "post", Post.table_name
485
+ assert_equal "categories", Category.table_name
486
+ ensure
487
+ Post.pluralize_table_names = true
488
+ Post.reset_table_name
489
+ end
490
+
491
+ if current_adapter?(:Mysql2Adapter)
492
+ puts "In base_test test_update_all_with_order_and_limit"
493
+ def test_update_all_with_order_and_limit
494
+ assert_equal 1, Topic.limit(1).order('id DESC').update_all(:content => 'bulk updated!')
495
+ end
496
+ end
497
+
498
+ def test_null_fields
499
+ puts "In base_test test_null_fields"
500
+ assert_nil Topic.find(1).parent_id
501
+ assert_nil Topic.create("title" => "Hey you").parent_id
502
+ end
503
+
504
+ def test_default_values
505
+ puts "In base_test test_default_values"
506
+ topic = Topic.new
507
+ assert topic.approved?
508
+ assert_nil topic.written_on
509
+ assert_nil topic.bonus_time
510
+ assert_nil topic.last_read
511
+
512
+ topic.save
513
+
514
+ topic = Topic.find(topic.id)
515
+ assert topic.approved?
516
+ assert_nil topic.last_read
517
+
518
+ # Oracle has some funky default handling, so it requires a bit of
519
+ # extra testing. See ticket #2788.
520
+ if current_adapter?(:OracleAdapter)
521
+ test = TestOracleDefault.new
522
+ assert_equal "X", test.test_char
523
+ assert_equal "hello", test.test_string
524
+ assert_equal 3, test.test_int
525
+ end
526
+ end
527
+
528
+ # Oracle does not have a TIME datatype.
529
+ unless current_adapter?(:OracleAdapter,:IBM_DBAdapter)
530
+ def test_utc_as_time_zone
531
+ puts "In base_test test_utc_as_time_zone"
532
+ with_timezone_config default: :utc do
533
+ attributes = { "bonus_time" => "5:42:00AM" }
534
+ topic = Topic.find(1)
535
+ topic.attributes = attributes
536
+ assert_equal Time.utc(2000, 1, 1, 5, 42, 0), topic.bonus_time
537
+ end
538
+ end
539
+ end
540
+
541
+ def test_utc_as_time_zone_and_new
542
+ puts "In base_test test_utc_as_time_zone_and_new"
543
+ with_timezone_config default: :utc do
544
+ attributes = { "bonus_time(1i)"=>"2000",
545
+ "bonus_time(2i)"=>"1",
546
+ "bonus_time(3i)"=>"1",
547
+ "bonus_time(4i)"=>"10",
548
+ "bonus_time(5i)"=>"35",
549
+ "bonus_time(6i)"=>"50" }
550
+ topic = Topic.new(attributes)
551
+ assert_equal Time.utc(2000, 1, 1, 10, 35, 50), topic.bonus_time
552
+ end
553
+ end
554
+ end
555
+
556
+ def test_default_values_on_empty_strings
557
+ puts "In base_test test_default_values_on_empty_strings"
558
+ topic = Topic.new
559
+ topic.approved = nil
560
+ topic.last_read = nil
561
+
562
+ topic.save
563
+
564
+ topic = Topic.find(topic.id)
565
+ assert_nil topic.last_read
566
+
567
+ assert_nil topic.approved
568
+ end
569
+
570
+ def test_equality
571
+ puts "In base_test test_equality"
572
+ assert_equal Topic.find(1), Topic.find(2).topic
573
+ end
574
+
575
+ def test_find_by_slug
576
+ puts "In base_test test_find_by_slug"
577
+ assert_equal Topic.find('1-meowmeow'), Topic.find(1)
578
+ end
579
+
580
+ def test_find_by_slug_with_array
581
+ puts "In base_test test_find_by_slug_with_array"
582
+ assert_equal Topic.find([1, 2]), Topic.find(['1-meowmeow', '2-hello'])
583
+ assert_equal 'The Second Topic of the day', Topic.find(['2-hello', '1-meowmeow']).first.title
584
+ end
585
+
586
+ def test_find_by_slug_with_range
587
+ puts "In base_test test_find_by_slug_with_range"
588
+ assert_equal Topic.where(id: '1-meowmeow'..'2-hello'), Topic.where(id: 1..2)
589
+ end
590
+
591
+ def test_equality_of_new_records
592
+ puts "In base_test test_equality_of_new_records"
593
+ assert_not_equal Topic.new, Topic.new
594
+ assert_equal false, Topic.new == Topic.new
595
+ end
596
+
597
+ def test_equality_of_destroyed_records
598
+ puts "In base_test test_equality_of_destroyed_records"
599
+ topic_1 = Topic.new(:title => 'test_1')
600
+ topic_1.save
601
+ topic_2 = Topic.find(topic_1.id)
602
+ topic_1.destroy
603
+ assert_equal topic_1, topic_2
604
+ assert_equal topic_2, topic_1
605
+ end
606
+
607
+ def test_equality_with_blank_ids
608
+ puts "In base_test test_equality_with_blank_ids"
609
+ one = Subscriber.new(:id => '')
610
+ two = Subscriber.new(:id => '')
611
+ assert_equal one, two
612
+ end
613
+
614
+ def test_equality_of_relation_and_collection_proxy
615
+ puts "In base_test test_equality_of_relation_and_collection_proxy"
616
+ car = Car.create!
617
+ car.bulbs.build
618
+ car.save
619
+
620
+ assert car.bulbs == Bulb.where(car_id: car.id), 'CollectionProxy should be comparable with Relation'
621
+ assert Bulb.where(car_id: car.id) == car.bulbs, 'Relation should be comparable with CollectionProxy'
622
+ end
623
+
624
+ def test_equality_of_relation_and_array
625
+ puts "In base_test test_equality_of_relation_and_array"
626
+ car = Car.create!
627
+ car.bulbs.build
628
+ car.save
629
+
630
+ assert Bulb.where(car_id: car.id) == car.bulbs.to_a, 'Relation should be comparable with Array'
631
+ end
632
+
633
+ def test_equality_of_relation_and_association_relation
634
+ puts "In base_test test_equality_of_relation_and_association_relation"
635
+ car = Car.create!
636
+ car.bulbs.build
637
+ car.save
638
+
639
+ assert_equal Bulb.where(car_id: car.id), car.bulbs.includes(:car), 'Relation should be comparable with AssociationRelation'
640
+ assert_equal car.bulbs.includes(:car), Bulb.where(car_id: car.id), 'AssociationRelation should be comparable with Relation'
641
+ end
642
+
643
+ def test_equality_of_collection_proxy_and_association_relation
644
+ puts "In base_test test_equality_of_collection_proxy_and_association_relation"
645
+ car = Car.create!
646
+ car.bulbs.build
647
+ car.save
648
+
649
+ assert_equal car.bulbs, car.bulbs.includes(:car), 'CollectionProxy should be comparable with AssociationRelation'
650
+ assert_equal car.bulbs.includes(:car), car.bulbs, 'AssociationRelation should be comparable with CollectionProxy'
651
+ end
652
+
653
+ def test_hashing
654
+ puts "In base_test test_hashing"
655
+ assert_equal [ Topic.find(1) ], [ Topic.find(2).topic ] & [ Topic.find(1) ]
656
+ end
657
+
658
+ def test_successful_comparison_of_like_class_records
659
+ puts "In base_test test_successful_comparison_of_like_class_records"
660
+ topic_1 = Topic.create!
661
+ topic_2 = Topic.create!
662
+
663
+ assert_equal [topic_2, topic_1].sort, [topic_1, topic_2]
664
+ end
665
+
666
+ def test_failed_comparison_of_unlike_class_records
667
+ puts "In base_test test_failed_comparison_of_unlike_class_records"
668
+ assert_raises ArgumentError do
669
+ [ topics(:first), posts(:welcome) ].sort
670
+ end
671
+ end
672
+
673
+ def test_create_without_prepared_statement
674
+ puts "In base_test test_create_without_prepared_statement"
675
+ topic = Topic.connection.unprepared_statement do
676
+ Topic.create(:title => 'foo')
677
+ end
678
+
679
+ assert_equal topic, Topic.find(topic.id)
680
+ end
681
+
682
+ def test_destroy_without_prepared_statement
683
+ puts "In base_test test_destroy_without_prepared_statement"
684
+ topic = Topic.create(title: 'foo')
685
+ Topic.connection.unprepared_statement do
686
+ Topic.find(topic.id).destroy
687
+ end
688
+
689
+ assert_equal nil, Topic.find_by_id(topic.id)
690
+ end
691
+
692
+ def test_comparison_with_different_objects
693
+ puts "In base_test test_comparison_with_different_objects"
694
+ topic = Topic.create
695
+ category = Category.create(:name => "comparison")
696
+ assert_nil topic <=> category
697
+ end
698
+
699
+ def test_comparison_with_different_objects_in_array
700
+ puts "In base_test test_comparison_with_different_objects_in_array"
701
+ topic = Topic.create
702
+ assert_raises(ArgumentError) do
703
+ [1, topic].sort
704
+ end
705
+ end
706
+
707
+ def test_readonly_attributes
708
+ puts "In base_test test_readonly_attributes"
709
+ assert_equal Set.new([ 'title' , 'comments_count' ]), ReadonlyTitlePost.readonly_attributes
710
+
711
+ post = ReadonlyTitlePost.create(:title => "cannot change this", :body => "changeable")
712
+ post.reload
713
+ assert_equal "cannot change this", post.title
714
+
715
+ post.update(title: "try to change", body: "changed")
716
+ post.reload
717
+ assert_equal "cannot change this", post.title
718
+ assert_equal "changed", post.body
719
+ end
720
+
721
+ def test_unicode_column_name
722
+ puts "In base_test test_unicode_column_name"
723
+ Weird.reset_column_information
724
+ weird = Weird.create(:なまえ => 'たこ焼き仮面')
725
+ assert_equal 'たこ焼き仮面', weird.なまえ
726
+ end
727
+
728
+ unless current_adapter?(:PostgreSQLAdapter)
729
+ def test_respect_internal_encoding
730
+ puts "In base_test test_respect_internal_encoding"
731
+ old_default_internal = Encoding.default_internal
732
+ silence_warnings { Encoding.default_internal = "EUC-JP" }
733
+
734
+ Weird.reset_column_information
735
+
736
+ assert_equal ["EUC-JP"], Weird.columns.map {|c| c.name.encoding.name }.uniq
737
+ ensure
738
+ silence_warnings { Encoding.default_internal = old_default_internal }
739
+ Weird.reset_column_information
740
+ end
741
+ end
742
+
743
+ def test_non_valid_identifier_column_name
744
+ puts "In base_test test_non_valid_identifier_column_name"
745
+ weird = Weird.create('a$b' => 'value')
746
+ weird.reload
747
+ assert_equal 'value', weird.send('a$b')
748
+ assert_equal 'value', weird.read_attribute('a$b')
749
+
750
+ weird.update_columns('a$b' => 'value2')
751
+ weird.reload
752
+ assert_equal 'value2', weird.send('a$b')
753
+ assert_equal 'value2', weird.read_attribute('a$b')
754
+ end
755
+
756
+ def test_group_weirds_by_from
757
+ puts "In base_test test_group_weirds_by_from"
758
+ Weird.create('a$b' => 'value', :from => 'aaron')
759
+ count = Weird.group(Weird.arel_table[:from]).count
760
+ assert_equal 1, count['aaron']
761
+ end
762
+
763
+ def test_attributes_on_dummy_time
764
+ puts "In base_test test_attributes_on_dummy_time"
765
+ # Oracle does not have a TIME datatype.
766
+ return true if current_adapter?(:OracleAdapter)
767
+
768
+ with_timezone_config default: :local do
769
+ attributes = {
770
+ "bonus_time" => "5:42:00AM"
771
+ }
772
+ topic = Topic.find(1)
773
+ topic.attributes = attributes
774
+ assert_equal Time.local(2000, 1, 1, 5, 42, 0), topic.bonus_time
775
+ end
776
+ end
777
+
778
+ def test_attributes_on_dummy_time_with_invalid_time
779
+ puts "In base_test test_attributes_on_dummy_time_with_invalid_time"
780
+ # Oracle does not have a TIME datatype.
781
+ return true if current_adapter?(:OracleAdapter)
782
+
783
+ attributes = {
784
+ "bonus_time" => "not a time"
785
+ }
786
+ topic = Topic.find(1)
787
+ topic.attributes = attributes
788
+ assert_nil topic.bonus_time
789
+ end
790
+
791
+ def test_boolean
792
+ puts "In base_test test_boolean"
793
+ b_nil = Boolean.create({ "value" => nil })
794
+ nil_id = b_nil.id
795
+ b_false = Boolean.create({ "value" => false })
796
+ false_id = b_false.id
797
+ b_true = Boolean.create({ "value" => true })
798
+ true_id = b_true.id
799
+
800
+ b_nil = Boolean.find(nil_id)
801
+ assert_nil b_nil.value
802
+ b_false = Boolean.find(false_id)
803
+ assert !b_false.value?
804
+ b_true = Boolean.find(true_id)
805
+ assert b_true.value?
806
+ end
807
+
808
+ def test_boolean_without_questionmark
809
+ puts "In base_test test_boolean_without_questionmark"
810
+ b_true = Boolean.create({ "value" => true })
811
+ true_id = b_true.id
812
+
813
+ subclass = Class.new(Boolean).find true_id
814
+ superclass = Boolean.find true_id
815
+
816
+ assert_equal superclass.read_attribute(:has_fun), subclass.read_attribute(:has_fun)
817
+ end
818
+
819
+ def test_boolean_cast_from_string
820
+ puts "In base_test test_boolean_cast_from_string"
821
+ b_blank = Boolean.create({ "value" => "" })
822
+ blank_id = b_blank.id
823
+ b_false = Boolean.create({ "value" => "0" })
824
+ false_id = b_false.id
825
+ b_true = Boolean.create({ "value" => "1" })
826
+ true_id = b_true.id
827
+
828
+ b_blank = Boolean.find(blank_id)
829
+ assert_nil b_blank.value
830
+ b_false = Boolean.find(false_id)
831
+ assert !b_false.value?
832
+ b_true = Boolean.find(true_id)
833
+ assert b_true.value?
834
+ end
835
+
836
+ def test_new_record_returns_boolean
837
+ puts "In base_test test_new_record_returns_boolean"
838
+ assert_equal false, Topic.new.persisted?
839
+ assert_equal true, Topic.find(1).persisted?
840
+ end
841
+
842
+ def test_dup
843
+ puts "In base_test test_dup"
844
+ topic = Topic.find(1)
845
+ duped_topic = nil
846
+ assert_nothing_raised { duped_topic = topic.dup }
847
+ assert_equal topic.title, duped_topic.title
848
+ assert !duped_topic.persisted?
849
+
850
+ # test if the attributes have been duped
851
+ topic.title = "a"
852
+ duped_topic.title = "b"
853
+ assert_equal "a", topic.title
854
+ assert_equal "b", duped_topic.title
855
+
856
+ # test if the attribute values have been duped
857
+ duped_topic = topic.dup
858
+ duped_topic.title.replace "c"
859
+ assert_equal "a", topic.title
860
+
861
+ # test if attributes set as part of after_initialize are duped correctly
862
+ assert_equal topic.author_email_address, duped_topic.author_email_address
863
+
864
+ # test if saved clone object differs from original
865
+ duped_topic.save
866
+ assert duped_topic.persisted?
867
+ assert_not_equal duped_topic.id, topic.id
868
+
869
+ duped_topic.reload
870
+ assert_equal("c", duped_topic.title)
871
+ end
872
+
873
+ DeveloperSalary = Struct.new(:amount)
874
+ def test_dup_with_aggregate_of_same_name_as_attribute
875
+ puts "In base_test test_dup_with_aggregate_of_same_name_as_attribute"
876
+ developer_with_aggregate = Class.new(ActiveRecord::Base) do
877
+ self.table_name = 'developers'
878
+ composed_of :salary, :class_name => 'BasicsTest::DeveloperSalary', :mapping => [%w(salary amount)]
879
+ end
880
+
881
+ dev = developer_with_aggregate.find(1)
882
+ assert_kind_of DeveloperSalary, dev.salary
883
+
884
+ dup = nil
885
+ assert_nothing_raised { dup = dev.dup }
886
+ assert_kind_of DeveloperSalary, dup.salary
887
+ assert_equal dev.salary.amount, dup.salary.amount
888
+ assert !dup.persisted?
889
+
890
+ # test if the attributes have been duped
891
+ original_amount = dup.salary.amount
892
+ dev.salary.amount = 1
893
+ assert_equal original_amount, dup.salary.amount
894
+
895
+ assert dup.save
896
+ assert dup.persisted?
897
+ assert_not_equal dup.id, dev.id
898
+ end
899
+
900
+ def test_dup_does_not_copy_associations
901
+ puts "In base_test test_dup_does_not_copy_associations"
902
+ author = authors(:david)
903
+ assert_not_equal [], author.posts
904
+
905
+ author_dup = author.dup
906
+ assert_equal [], author_dup.posts
907
+ end
908
+
909
+ def test_clone_preserves_subtype
910
+ puts "In base_test test_clone_preserves_subtype"
911
+ clone = nil
912
+ assert_nothing_raised { clone = Company.find(3).clone }
913
+ assert_kind_of Client, clone
914
+ end
915
+
916
+ def test_clone_of_new_object_with_defaults
917
+ puts "In base_test test_clone_of_new_object_with_defaults"
918
+ developer = Developer.new
919
+ assert !developer.name_changed?
920
+ assert !developer.salary_changed?
921
+
922
+ cloned_developer = developer.clone
923
+ assert !cloned_developer.name_changed?
924
+ assert !cloned_developer.salary_changed?
925
+ end
926
+
927
+ def test_clone_of_new_object_marks_attributes_as_dirty
928
+ puts "In base_test test_clone_of_new_object_marks_attributes_as_dirty"
929
+ developer = Developer.new :name => 'Bjorn', :salary => 100000
930
+ assert developer.name_changed?
931
+ assert developer.salary_changed?
932
+
933
+ cloned_developer = developer.clone
934
+ assert cloned_developer.name_changed?
935
+ assert cloned_developer.salary_changed?
936
+ end
937
+
938
+ def test_clone_of_new_object_marks_as_dirty_only_changed_attributes
939
+ puts "In base_test test_clone_of_new_object_marks_as_dirty_only_changed_attributes"
940
+ developer = Developer.new :name => 'Bjorn'
941
+ assert developer.name_changed? # obviously
942
+ assert !developer.salary_changed? # attribute has non-nil default value, so treated as not changed
943
+
944
+ cloned_developer = developer.clone
945
+ assert cloned_developer.name_changed?
946
+ assert !cloned_developer.salary_changed? # ... and cloned instance should behave same
947
+ end
948
+
949
+ def test_dup_of_saved_object_marks_attributes_as_dirty
950
+ puts "In base_test test_dup_of_saved_object_marks_attributes_as_dirty"
951
+ developer = Developer.create! :name => 'Bjorn', :salary => 100000
952
+ assert !developer.name_changed?
953
+ assert !developer.salary_changed?
954
+
955
+ cloned_developer = developer.dup
956
+ assert cloned_developer.name_changed? # both attributes differ from defaults
957
+ assert cloned_developer.salary_changed?
958
+ end
959
+
960
+ def test_dup_of_saved_object_marks_as_dirty_only_changed_attributes
961
+ puts "In base_test test_dup_of_saved_object_marks_as_dirty_only_changed_attributes"
962
+ developer = Developer.create! :name => 'Bjorn'
963
+ assert !developer.name_changed? # both attributes of saved object should be treated as not changed
964
+ assert !developer.salary_changed?
965
+
966
+ cloned_developer = developer.dup
967
+ assert cloned_developer.name_changed? # ... but on cloned object should be
968
+ assert !cloned_developer.salary_changed? # ... BUT salary has non-nil default which should be treated as not changed on cloned instance
969
+ end
970
+
971
+ def test_bignum
972
+ puts "In base_test test_bignum"
973
+ company = Company.find(1)
974
+ company.rating = 2147483647
975
+ company.save
976
+ company = Company.find(1)
977
+ assert_equal 2147483647, company.rating
978
+ end
979
+
980
+ # TODO: extend defaults tests to other databases!
981
+ if current_adapter?(:PostgreSQLAdapter)
982
+ def test_default
983
+ puts "In base_test test_default"
984
+ with_timezone_config default: :local do
985
+ default = Default.new
986
+
987
+ # fixed dates / times
988
+ assert_equal Date.new(2004, 1, 1), default.fixed_date
989
+ assert_equal Time.local(2004, 1,1,0,0,0,0), default.fixed_time
990
+
991
+ # char types
992
+ assert_equal 'Y', default.char1
993
+ assert_equal 'a varchar field', default.char2
994
+ assert_equal 'a text field', default.char3
995
+ end
996
+ end
997
+ end
998
+
999
+ class NumericData < ActiveRecord::Base
1000
+ self.table_name = 'numeric_data'
1001
+
1002
+ attribute :my_house_population, :integer
1003
+ attribute :atoms_in_universe, :integer
1004
+ end
1005
+
1006
+ def test_big_decimal_conditions
1007
+ puts "In base_test test_big_decimal_conditions"
1008
+ m = NumericData.new(
1009
+ :bank_balance => 1586.43,
1010
+ :big_bank_balance => BigDecimal("1000234000567.95"),
1011
+ :world_population => 6000000000,
1012
+ :my_house_population => 3
1013
+ )
1014
+ assert m.save
1015
+ assert_equal 0, NumericData.where("bank_balance > ?", 2000.0).count
1016
+ end
1017
+
1018
+ def test_numeric_fields
1019
+ puts "In base_test test_numeric_fields"
1020
+ m = NumericData.new(
1021
+ :bank_balance => 1586.43,
1022
+ :big_bank_balance => BigDecimal("1000234000567.95"),
1023
+ :world_population => 6000000000,
1024
+ :my_house_population => 3
1025
+ )
1026
+ assert m.save
1027
+
1028
+ m1 = NumericData.find(m.id)
1029
+ assert_not_nil m1
1030
+
1031
+ # As with migration_test.rb, we should make world_population >= 2**62
1032
+ # to cover 64-bit platforms and test it is a Bignum, but the main thing
1033
+ # is that it's an Integer.
1034
+ unless current_adapter?(:IBM_DBAdapter)
1035
+ assert_kind_of Integer, m1.world_population
1036
+ else
1037
+ assert_equal 6000000000, m1.world_population
1038
+
1039
+ assert_kind_of Integer, m1.my_house_population
1040
+ assert_equal 3, m1.my_house_population
1041
+
1042
+ assert_kind_of BigDecimal, m1.bank_balance
1043
+ assert_equal BigDecimal("1586.43"), m1.bank_balance
1044
+
1045
+ assert_kind_of BigDecimal, m1.big_bank_balance
1046
+ assert_equal BigDecimal("1000234000567.95"), m1.big_bank_balance
1047
+ end
1048
+
1049
+ def test_numeric_fields_with_scale
1050
+ puts "In base_test test_numeric_fields_with_scale"
1051
+ m = NumericData.new(
1052
+ :bank_balance => 1586.43122334,
1053
+ :big_bank_balance => BigDecimal("234000567.952344"),
1054
+ :world_population => 6000000000,
1055
+ :my_house_population => 3
1056
+ )
1057
+ assert m.save
1058
+
1059
+ m1 = NumericData.find(m.id)
1060
+ assert_not_nil m1
1061
+
1062
+ # As with migration_test.rb, we should make world_population >= 2**62
1063
+ # to cover 64-bit platforms and test it is a Bignum, but the main thing
1064
+ # is that it's an Integer.
1065
+ assert_kind_of Integer, m1.world_population
1066
+ assert_equal 6000000000, m1.world_population
1067
+
1068
+ assert_kind_of Integer, m1.my_house_population
1069
+ assert_equal 3, m1.my_house_population
1070
+
1071
+ assert_kind_of BigDecimal, m1.bank_balance
1072
+ assert_equal BigDecimal("1586.43"), m1.bank_balance
1073
+
1074
+ assert_kind_of BigDecimal, m1.big_bank_balance
1075
+ assert_equal BigDecimal("234000567.95"), m1.big_bank_balance
1076
+ end
1077
+
1078
+ def test_auto_id
1079
+ puts "In base_test test_auto_id"
1080
+ auto = AutoId.new
1081
+ auto.save
1082
+ assert(auto.id > 0)
1083
+ end
1084
+
1085
+ def test_sql_injection_via_find
1086
+ puts "In base_test test_sql_injection_via_find"
1087
+ assert_raise(ActiveRecord::RecordNotFound, ActiveRecord::StatementInvalid) do
1088
+ Topic.find("123456 OR id > 0")
1089
+ end
1090
+ end
1091
+
1092
+ def test_column_name_properly_quoted
1093
+ puts "In base_test test_column_name_properly_quoted"
1094
+ col_record = ColumnName.new
1095
+ col_record.references = 40
1096
+ assert col_record.save
1097
+ col_record.references = 41
1098
+ assert col_record.save
1099
+ assert_not_nil c2 = ColumnName.find(col_record.id)
1100
+ assert_equal(41, c2.references)
1101
+ end
1102
+
1103
+ def test_quoting_arrays
1104
+ puts "In base_test test_quoting_arrays"
1105
+ replies = Reply.all.merge!(:where => [ "id IN (?)", topics(:first).replies.collect(&:id) ]).to_a
1106
+ assert_equal topics(:first).replies.size, replies.size
1107
+
1108
+ replies = Reply.all.merge!(:where => [ "id IN (?)", [] ]).to_a
1109
+ assert_equal 0, replies.size
1110
+ end
1111
+
1112
+ def test_quote
1113
+ puts "In base_test test_quote"
1114
+ author_name = "\\ \001 ' \n \\n \""
1115
+ topic = Topic.create('author_name' => author_name)
1116
+ assert_equal author_name, Topic.find(topic.id).author_name
1117
+ end
1118
+
1119
+ def test_toggle_attribute
1120
+ puts "In base_test test_toggle_attribute"
1121
+ assert !topics(:first).approved?
1122
+ topics(:first).toggle!(:approved)
1123
+ assert topics(:first).approved?
1124
+ topic = topics(:first)
1125
+ topic.toggle(:approved)
1126
+ assert !topic.approved?
1127
+ topic.reload
1128
+ assert topic.approved?
1129
+ end
1130
+
1131
+ def test_reload
1132
+ puts "In base_test test_reload"
1133
+ t1 = Topic.find(1)
1134
+ t2 = Topic.find(1)
1135
+ t1.title = "something else"
1136
+ t1.save
1137
+ t2.reload
1138
+ assert_equal t1.title, t2.title
1139
+ end
1140
+
1141
+ def test_reload_with_exclusive_scope
1142
+ puts "In base_test test_reload_with_exclusive_scope"
1143
+ dev = DeveloperCalledDavid.first
1144
+ dev.update!(name: "NotDavid" )
1145
+ assert_equal dev, dev.reload
1146
+ end
1147
+
1148
+ def test_switching_between_table_name
1149
+ puts "In base_test test_switching_between_table_name"
1150
+ k = Class.new(Joke)
1151
+
1152
+ assert_difference("GoodJoke.count") do
1153
+ k.table_name = "cold_jokes"
1154
+ k.create
1155
+
1156
+ k.table_name = "funny_jokes"
1157
+ k.create
1158
+ end
1159
+ end
1160
+
1161
+ def test_clear_cash_when_setting_table_name
1162
+ puts "In base_test test_clear_cash_when_setting_table_name"
1163
+ original_table_name = Joke.table_name
1164
+
1165
+ Joke.table_name = "funny_jokes"
1166
+ before_columns = Joke.columns
1167
+ before_seq = Joke.sequence_name
1168
+
1169
+ Joke.table_name = "cold_jokes"
1170
+ after_columns = Joke.columns
1171
+ after_seq = Joke.sequence_name
1172
+
1173
+ assert_not_equal before_columns, after_columns
1174
+ assert_not_equal before_seq, after_seq unless before_seq.nil? && after_seq.nil?
1175
+ ensure
1176
+ Joke.table_name = original_table_name
1177
+ end
1178
+
1179
+ def test_dont_clear_sequence_name_when_setting_explicitly
1180
+ puts "In base_test test_dont_clear_sequence_name_when_setting_explicitly"
1181
+ k = Class.new(Joke)
1182
+ k.sequence_name = "black_jokes_seq"
1183
+ k.table_name = "cold_jokes"
1184
+ before_seq = k.sequence_name
1185
+
1186
+ k.table_name = "funny_jokes"
1187
+ after_seq = k.sequence_name
1188
+
1189
+ assert_equal before_seq, after_seq unless before_seq.nil? && after_seq.nil?
1190
+ end
1191
+
1192
+ def test_dont_clear_inheritance_column_when_setting_explicitly
1193
+ puts "In base_test test_dont_clear_inheritance_column_when_setting_explicitly"
1194
+ k = Class.new(Joke)
1195
+ k.inheritance_column = "my_type"
1196
+ before_inherit = k.inheritance_column
1197
+
1198
+ k.reset_column_information
1199
+ after_inherit = k.inheritance_column
1200
+
1201
+ assert_equal before_inherit, after_inherit unless before_inherit.blank? && after_inherit.blank?
1202
+ end
1203
+
1204
+ def test_set_table_name_symbol_converted_to_string
1205
+ puts "In base_test test_set_table_name_symbol_converted_to_string"
1206
+ k = Class.new(Joke)
1207
+ k.table_name = :cold_jokes
1208
+ assert_equal 'cold_jokes', k.table_name
1209
+ end
1210
+
1211
+ def test_quoted_table_name_after_set_table_name
1212
+ puts "In base_test test_quoted_table_name_after_set_table_name"
1213
+ klass = Class.new(ActiveRecord::Base)
1214
+
1215
+ klass.table_name = "foo"
1216
+ assert_equal "foo", klass.table_name
1217
+ assert_equal klass.connection.quote_table_name("foo"), klass.quoted_table_name
1218
+
1219
+ klass.table_name = "bar"
1220
+ assert_equal "bar", klass.table_name
1221
+ assert_equal klass.connection.quote_table_name("bar"), klass.quoted_table_name
1222
+ end
1223
+
1224
+ def test_set_table_name_with_inheritance
1225
+ puts "In base_test test_set_table_name_with_inheritance"
1226
+ k = Class.new( ActiveRecord::Base )
1227
+ def k.name; "Foo"; end
1228
+ def k.table_name; super + "ks"; end
1229
+ assert_equal "foosks", k.table_name
1230
+ end
1231
+
1232
+ def test_sequence_name_with_abstract_class
1233
+ puts "In base_test test_sequence_name_with_abstract_class"
1234
+ ak = Class.new(ActiveRecord::Base)
1235
+ ak.abstract_class = true
1236
+ k = Class.new(ak)
1237
+ k.table_name = "projects"
1238
+ orig_name = k.sequence_name
1239
+ skip "sequences not supported by db" unless orig_name
1240
+ assert_equal k.reset_sequence_name, orig_name
1241
+ end
1242
+
1243
+ def test_count_with_join
1244
+ puts "In base_test test_count_with_join"
1245
+ res = Post.count_by_sql "SELECT COUNT(*) FROM posts LEFT JOIN comments ON posts.id=comments.post_id WHERE posts.#{QUOTED_TYPE} = 'Post'"
1246
+
1247
+ res2 = Post.where("posts.#{QUOTED_TYPE} = 'Post'").joins("LEFT JOIN comments ON posts.id=comments.post_id").count
1248
+ assert_equal res, res2
1249
+
1250
+ res3 = nil
1251
+ assert_nothing_raised do
1252
+ res3 = Post.where("posts.#{QUOTED_TYPE} = 'Post'").joins("LEFT JOIN comments ON posts.id=comments.post_id").count
1253
+ end
1254
+ assert_equal res, res3
1255
+
1256
+ res4 = Post.count_by_sql "SELECT COUNT(p.id) FROM posts p, comments co WHERE p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id"
1257
+ res5 = nil
1258
+ assert_nothing_raised do
1259
+ res5 = Post.where("p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id").joins("p, comments co").select("p.id").count
1260
+ end
1261
+
1262
+ assert_equal res4, res5
1263
+
1264
+ res6 = Post.count_by_sql "SELECT COUNT(DISTINCT p.id) FROM posts p, comments co WHERE p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id"
1265
+ res7 = nil
1266
+ assert_nothing_raised do
1267
+ res7 = Post.where("p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id").joins("p, comments co").select("p.id").distinct.count
1268
+ end
1269
+ assert_equal res6, res7
1270
+ end
1271
+
1272
+ def test_no_limit_offset
1273
+ puts "In base_test test_no_limit_offset"
1274
+ assert_nothing_raised do
1275
+ Developer.all.merge!(:offset => 2).to_a
1276
+ end
1277
+ end
1278
+
1279
+ def test_find_last
1280
+ puts "In base_test test_find_last"
1281
+ last = Developer.last
1282
+ assert_equal last, Developer.all.merge!(:order => 'id desc').first
1283
+ end
1284
+
1285
+ def test_last
1286
+ puts "In base_test test_last"
1287
+ assert_equal Developer.all.merge!(:order => 'id desc').first, Developer.last
1288
+ end
1289
+
1290
+ def test_all
1291
+ puts "In base_test test_all"
1292
+ developers = Developer.all
1293
+ assert_kind_of ActiveRecord::Relation, developers
1294
+ assert_equal Developer.all, developers
1295
+ end
1296
+
1297
+ def test_all_with_conditions
1298
+ puts "In base_test test_all_with_conditions"
1299
+ assert_equal Developer.all.merge!(:order => 'id desc').to_a, Developer.order('id desc').to_a
1300
+ end
1301
+
1302
+ def test_find_ordered_last
1303
+ puts "In base_test test_find_ordered_last"
1304
+ last = Developer.all.merge!(:order => 'developers.salary ASC').last
1305
+ assert_equal last, Developer.all.merge!(:order => 'developers.salary ASC').to_a.last
1306
+ end
1307
+
1308
+ def test_find_reverse_ordered_last
1309
+ puts "In base_test test_find_reverse_ordered_last"
1310
+ last = Developer.all.merge!(:order => 'developers.salary DESC').last
1311
+ assert_equal last, Developer.all.merge!(:order => 'developers.salary DESC').to_a.last
1312
+ end
1313
+
1314
+ def test_find_multiple_ordered_last
1315
+ puts "In base_test test_find_multiple_ordered_last"
1316
+ last = Developer.all.merge!(:order => 'developers.name, developers.salary DESC').last
1317
+ assert_equal last, Developer.all.merge!(:order => 'developers.name, developers.salary DESC').to_a.last
1318
+ end
1319
+
1320
+ def test_find_keeps_multiple_order_values
1321
+ puts "In base_test test_find_keeps_multiple_order_values"
1322
+ combined = Developer.all.merge!(:order => 'developers.name, developers.salary').to_a
1323
+ assert_equal combined, Developer.all.merge!(:order => ['developers.name', 'developers.salary']).to_a
1324
+ end
1325
+
1326
+ def test_find_keeps_multiple_group_values
1327
+ puts "In base_test test_find_keeps_multiple_group_values"
1328
+ combined = Developer.all.merge!(:group => 'developers.name, developers.salary, developers.id, developers.created_at, developers.updated_at, developers.created_on, developers.updated_on').to_a
1329
+ assert_equal combined, Developer.all.merge!(:group => ['developers.name', 'developers.salary', 'developers.id', 'developers.created_at', 'developers.updated_at', 'developers.created_on', 'developers.updated_on']).to_a
1330
+ end
1331
+
1332
+ def test_find_symbol_ordered_last
1333
+ puts "In base_test test_find_symbol_ordered_last"
1334
+ last = Developer.all.merge!(:order => :salary).last
1335
+ assert_equal last, Developer.all.merge!(:order => :salary).to_a.last
1336
+ end
1337
+
1338
+ def test_abstract_class_table_name
1339
+ puts "In base_test test_abstract_class_table_name"
1340
+ assert_nil AbstractCompany.table_name
1341
+ end
1342
+
1343
+ def test_find_on_abstract_base_class_doesnt_use_type_condition
1344
+ puts "In base_test test_find_on_abstract_base_class_doesnt_use_type_condition"
1345
+ old_class = LooseDescendant
1346
+ Object.send :remove_const, :LooseDescendant
1347
+
1348
+ descendant = old_class.create! :first_name => 'bob'
1349
+ assert_not_nil LoosePerson.find(descendant.id), "Should have found instance of LooseDescendant when finding abstract LoosePerson: #{descendant.inspect}"
1350
+ ensure
1351
+ unless Object.const_defined?(:LooseDescendant)
1352
+ Object.const_set :LooseDescendant, old_class
1353
+ end
1354
+ end
1355
+
1356
+ def test_assert_queries
1357
+ puts "In base_test test_assert_queries"
1358
+ query = lambda { ActiveRecord::Base.connection.execute 'select count(*) from developers' }
1359
+ assert_queries(2) { 2.times { query.call } }
1360
+ assert_queries 1, &query
1361
+ assert_no_queries { assert true }
1362
+ end
1363
+
1364
+ def test_benchmark_with_log_level
1365
+ puts "In base_test test_benchmark_with_log_level"
1366
+ original_logger = ActiveRecord::Base.logger
1367
+ log = StringIO.new
1368
+ ActiveRecord::Base.logger = ActiveSupport::Logger.new(log)
1369
+ ActiveRecord::Base.logger.level = Logger::WARN
1370
+ ActiveRecord::Base.benchmark("Debug Topic Count", :level => :debug) { Topic.count }
1371
+ ActiveRecord::Base.benchmark("Warn Topic Count", :level => :warn) { Topic.count }
1372
+ ActiveRecord::Base.benchmark("Error Topic Count", :level => :error) { Topic.count }
1373
+ assert_no_match(/Debug Topic Count/, log.string)
1374
+ assert_match(/Warn Topic Count/, log.string)
1375
+ assert_match(/Error Topic Count/, log.string)
1376
+ ensure
1377
+ ActiveRecord::Base.logger = original_logger
1378
+ end
1379
+
1380
+ def test_benchmark_with_use_silence
1381
+ puts "In base_test test_benchmark_with_use_silence"
1382
+ original_logger = ActiveRecord::Base.logger
1383
+ log = StringIO.new
1384
+ ActiveRecord::Base.logger = ActiveSupport::Logger.new(log)
1385
+ ActiveRecord::Base.logger.level = Logger::DEBUG
1386
+ ActiveRecord::Base.benchmark("Logging", :level => :debug, :silence => false) { ActiveRecord::Base.logger.debug "Quiet" }
1387
+ assert_match(/Quiet/, log.string)
1388
+ ensure
1389
+ ActiveRecord::Base.logger = original_logger
1390
+ end
1391
+
1392
+ def test_clear_cache!
1393
+ puts "In base_test test_clear_cache"
1394
+ # preheat cache
1395
+ c1 = Post.connection.schema_cache.columns('posts')
1396
+ ActiveRecord::Base.clear_cache!
1397
+ c2 = Post.connection.schema_cache.columns('posts')
1398
+ c1.each_with_index do |v, i|
1399
+ assert_not_same v, c2[i]
1400
+ end
1401
+ assert_equal c1, c2
1402
+ end
1403
+
1404
+ def test_current_scope_is_reset
1405
+ puts "In base_test test_current_scope_is_reset"
1406
+ Object.const_set :UnloadablePost, Class.new(ActiveRecord::Base)
1407
+ UnloadablePost.send(:current_scope=, UnloadablePost.all)
1408
+
1409
+ UnloadablePost.unloadable
1410
+ klass = UnloadablePost
1411
+ assert_not_nil ActiveRecord::Scoping::ScopeRegistry.value_for(:current_scope, klass)
1412
+ ActiveSupport::Dependencies.remove_unloadable_constants!
1413
+ assert_nil ActiveRecord::Scoping::ScopeRegistry.value_for(:current_scope, klass)
1414
+ ensure
1415
+ Object.class_eval{ remove_const :UnloadablePost } if defined?(UnloadablePost)
1416
+ end
1417
+
1418
+ def test_marshal_round_trip
1419
+ puts "In base_test test_marshal_round_trip"
1420
+ expected = posts(:welcome)
1421
+ marshalled = Marshal.dump(expected)
1422
+ actual = Marshal.load(marshalled)
1423
+
1424
+ assert_equal expected.attributes, actual.attributes
1425
+ end
1426
+
1427
+ def test_marshal_new_record_round_trip
1428
+ puts "In base_test test_marshal_new_record_round_trip"
1429
+ marshalled = Marshal.dump(Post.new)
1430
+ post = Marshal.load(marshalled)
1431
+
1432
+ assert post.new_record?, "should be a new record"
1433
+ end
1434
+
1435
+ def test_marshalling_with_associations
1436
+ puts "In base_test test_marshalling_with_associations"
1437
+ post = Post.new
1438
+ post.comments.build
1439
+
1440
+ marshalled = Marshal.dump(post)
1441
+ post = Marshal.load(marshalled)
1442
+
1443
+ assert_equal 1, post.comments.length
1444
+ end
1445
+
1446
+ if Process.respond_to?(:fork) && !in_memory_db?
1447
+ def test_marshal_between_processes
1448
+ puts "In base_test test_marshal_between_processes"
1449
+ # Define a new model to ensure there are no caches
1450
+ if self.class.const_defined?("Post", false)
1451
+ flunk "there should be no post constant"
1452
+ end
1453
+
1454
+ self.class.const_set("Post", Class.new(ActiveRecord::Base) {
1455
+ has_many :comments
1456
+ })
1457
+
1458
+ rd, wr = IO.pipe
1459
+ rd.binmode
1460
+ wr.binmode
1461
+
1462
+ ActiveRecord::Base.connection_handler.clear_all_connections!
1463
+
1464
+ fork do
1465
+ rd.close
1466
+ post = Post.new
1467
+ post.comments.build
1468
+ wr.write Marshal.dump(post)
1469
+ wr.close
1470
+ end
1471
+
1472
+ wr.close
1473
+ assert Marshal.load rd.read
1474
+ rd.close
1475
+ end
1476
+ end
1477
+
1478
+ def test_marshalling_new_record_round_trip_with_associations
1479
+ puts "In base_test test_marshalling_new_record_round_trip_with_associations"
1480
+ post = Post.new
1481
+ post.comments.build
1482
+
1483
+ post = Marshal.load(Marshal.dump(post))
1484
+
1485
+ assert post.new_record?, "should be a new record"
1486
+ end
1487
+
1488
+ def test_attribute_names
1489
+ puts "In base_test test_attribute_names"
1490
+ assert_equal ["id", "type", "firm_id", "firm_name", "name", "client_of", "rating", "account_id", "description"],
1491
+ Company.attribute_names
1492
+ end
1493
+
1494
+ def test_has_attribute
1495
+ puts "In base_test test_has_attribute"
1496
+ assert Company.has_attribute?('id')
1497
+ assert Company.has_attribute?('type')
1498
+ assert Company.has_attribute?('name')
1499
+ assert_not Company.has_attribute?('lastname')
1500
+ assert_not Company.has_attribute?('age')
1501
+ end
1502
+
1503
+ def test_has_attribute_with_symbol
1504
+ puts "In base_test test_has_attribute_with_symbol"
1505
+ assert Company.has_attribute?(:id)
1506
+ assert_not Company.has_attribute?(:age)
1507
+ end
1508
+
1509
+ def test_attribute_names_on_table_not_exists
1510
+ puts "In base_test test_attribute_names_on_table_not_exists"
1511
+ assert_equal [], NonExistentTable.attribute_names
1512
+ end
1513
+
1514
+ def test_attribute_names_on_abstract_class
1515
+ puts "In base_test test_attribute_names_on_abstract_class"
1516
+ assert_equal [], AbstractCompany.attribute_names
1517
+ end
1518
+
1519
+ def test_touch_should_raise_error_on_a_new_object
1520
+ puts "In base_test test_touch_should_raise_error_on_a_new_object"
1521
+ company = Company.new(:rating => 1, :name => "37signals", :firm_name => "37signals")
1522
+ assert_raises(ActiveRecord::ActiveRecordError) do
1523
+ company.touch :updated_at
1524
+ end
1525
+ end
1526
+
1527
+ def test_uniq_delegates_to_scoped
1528
+ puts "In base_test test_uniq_delegates_to_scoped"
1529
+ assert_deprecated do
1530
+ assert_equal Bird.all.distinct, Bird.uniq
1531
+ end
1532
+ end
1533
+
1534
+ def test_distinct_delegates_to_scoped
1535
+ puts "In base_test test_distinct_delegates_to_scoped"
1536
+ assert_equal Bird.all.distinct, Bird.distinct
1537
+ end
1538
+
1539
+ def test_table_name_with_2_abstract_subclasses
1540
+ puts "In base_test test_table_name_with_2_abstract_subclasses"
1541
+ assert_equal "photos", Photo.table_name
1542
+ end
1543
+
1544
+ def test_column_types_typecast
1545
+ puts "In base_test test_column_types_typecast"
1546
+ topic = Topic.first
1547
+ assert_not_equal 't.lo', topic.author_name
1548
+
1549
+ attrs = topic.attributes.dup
1550
+ attrs.delete 'id'
1551
+
1552
+ typecast = Class.new(ActiveRecord::Type::Value) {
1553
+ def cast value
1554
+ "t.lo"
1555
+ end
1556
+ }
1557
+
1558
+ types = { 'author_name' => typecast.new }
1559
+ topic = Topic.instantiate(attrs, types)
1560
+
1561
+ assert_equal 't.lo', topic.author_name
1562
+ end
1563
+
1564
+ def test_typecasting_aliases
1565
+ puts "In base_test test_typecasting_aliases"
1566
+ assert_equal 10, Topic.select('10 as tenderlove').first.tenderlove
1567
+ end
1568
+
1569
+ def test_slice
1570
+ puts "In base_test test_slice"
1571
+ company = Company.new(:rating => 1, :name => "37signals", :firm_name => "37signals")
1572
+ hash = company.slice(:name, :rating, "arbitrary_method")
1573
+ assert_equal hash[:name], company.name
1574
+ assert_equal hash['name'], company.name
1575
+ assert_equal hash[:rating], company.rating
1576
+ assert_equal hash['arbitrary_method'], company.arbitrary_method
1577
+ assert_equal hash[:arbitrary_method], company.arbitrary_method
1578
+ assert_nil hash[:firm_name]
1579
+ assert_nil hash['firm_name']
1580
+ end
1581
+
1582
+ def test_default_values_are_deeply_dupped
1583
+ puts "In base_test test_default_values_are_deeply_dupped"
1584
+ company = Company.new
1585
+ company.description << "foo"
1586
+ assert_equal "", Company.new.description
1587
+ end
1588
+
1589
+ test "scoped can take a values hash" do
1590
+ puts "In base_test scoped can take a values hash"
1591
+ klass = Class.new(ActiveRecord::Base)
1592
+ assert_equal ['foo'], klass.all.merge!(select: 'foo').select_values
1593
+ end
1594
+
1595
+ test "connection_handler can be overridden" do
1596
+ puts "In base_test connection_handler can be overridden"
1597
+ klass = Class.new(ActiveRecord::Base)
1598
+ orig_handler = klass.connection_handler
1599
+ new_handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new
1600
+ thread_connection_handler = nil
1601
+
1602
+ t = Thread.new do
1603
+ klass.connection_handler = new_handler
1604
+ thread_connection_handler = klass.connection_handler
1605
+ end
1606
+ t.join
1607
+
1608
+ assert_equal klass.connection_handler, orig_handler
1609
+ assert_equal thread_connection_handler, new_handler
1610
+ end
1611
+
1612
+ test "new threads get default the default connection handler" do
1613
+ puts "In base_test new threads get default the default connection handler"
1614
+ klass = Class.new(ActiveRecord::Base)
1615
+ orig_handler = klass.connection_handler
1616
+ handler = nil
1617
+
1618
+ t = Thread.new do
1619
+ handler = klass.connection_handler
1620
+ end
1621
+ t.join
1622
+
1623
+ assert_equal handler, orig_handler
1624
+ assert_equal klass.connection_handler, orig_handler
1625
+ assert_equal klass.default_connection_handler, orig_handler
1626
+ end
1627
+
1628
+ test "changing a connection handler in a main thread does not poison the other threads" do
1629
+ puts "In base_test changing a connection handler in a main thread does not poison the other threads"
1630
+ klass = Class.new(ActiveRecord::Base)
1631
+ orig_handler = klass.connection_handler
1632
+ new_handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new
1633
+ after_handler = nil
1634
+ latch1 = Concurrent::CountDownLatch.new
1635
+ latch2 = Concurrent::CountDownLatch.new
1636
+
1637
+ t = Thread.new do
1638
+ klass.connection_handler = new_handler
1639
+ latch1.count_down
1640
+ latch2.wait
1641
+ after_handler = klass.connection_handler
1642
+ end
1643
+
1644
+ latch1.wait
1645
+
1646
+ klass.connection_handler = orig_handler
1647
+ latch2.count_down
1648
+ t.join
1649
+
1650
+ assert_equal after_handler, new_handler
1651
+ assert_equal orig_handler, klass.connection_handler
1652
+ end
1653
+
1654
+ # Note: This is a performance optimization for Array#uniq and Hash#[] with
1655
+ # AR::Base objects. If the future has made this irrelevant, feel free to
1656
+ # delete this.
1657
+ test "records without an id have unique hashes" do
1658
+ puts "In base_test records without an id have unique hashes"
1659
+ assert_not_equal Post.new.hash, Post.new.hash
1660
+ end
1661
+
1662
+ test "resetting column information doesn't remove attribute methods" do
1663
+ puts "In base_test changing a connection handler in a main thread does not poison the other threads"
1664
+ topic = topics(:first)
1665
+
1666
+ assert_not topic.id_changed?
1667
+
1668
+ Topic.reset_column_information
1669
+
1670
+ assert_not topic.id_changed?
1671
+ end
1672
+
1673
+ test "ignored columns are not present in columns_hash" do
1674
+ puts "In base_test ignored columns are not present in columns_hash"
1675
+ cache_columns = Developer.connection.schema_cache.columns_hash(Developer.table_name)
1676
+ assert_includes cache_columns.keys, "first_name"
1677
+ assert_not_includes Developer.columns_hash.keys, "first_name"
1678
+ assert_not_includes SubDeveloper.columns_hash.keys, "first_name"
1679
+ assert_not_includes SymbolIgnoredDeveloper.columns_hash.keys, "first_name"
1680
+ end
1681
+
1682
+ test "ignored columns have no attribute methods" do
1683
+ puts "In base_test ignored columns have no attribute methods"
1684
+ refute Developer.new.respond_to?(:first_name)
1685
+ refute Developer.new.respond_to?(:first_name=)
1686
+ refute Developer.new.respond_to?(:first_name?)
1687
+ refute SubDeveloper.new.respond_to?(:first_name)
1688
+ refute SubDeveloper.new.respond_to?(:first_name=)
1689
+ refute SubDeveloper.new.respond_to?(:first_name?)
1690
+ refute SymbolIgnoredDeveloper.new.respond_to?(:first_name)
1691
+ refute SymbolIgnoredDeveloper.new.respond_to?(:first_name=)
1692
+ refute SymbolIgnoredDeveloper.new.respond_to?(:first_name?)
1693
+ end
1694
+
1695
+ test "ignored columns don't prevent explicit declaration of attribute methods" do
1696
+ puts "In base_test ignored columns don't prevent explicit declaration of attribute methods"
1697
+ assert Developer.new.respond_to?(:last_name)
1698
+ assert Developer.new.respond_to?(:last_name=)
1699
+ assert Developer.new.respond_to?(:last_name?)
1700
+ assert SubDeveloper.new.respond_to?(:last_name)
1701
+ assert SubDeveloper.new.respond_to?(:last_name=)
1702
+ assert SubDeveloper.new.respond_to?(:last_name?)
1703
+ assert SymbolIgnoredDeveloper.new.respond_to?(:last_name)
1704
+ assert SymbolIgnoredDeveloper.new.respond_to?(:last_name=)
1705
+ assert SymbolIgnoredDeveloper.new.respond_to?(:last_name?)
1706
+ end
1707
+
1708
+ test "ignored columns are stored as an array of string" do
1709
+ puts "In base_test ignored columns are stored as an array of string"
1710
+ assert_equal(%w(first_name last_name), Developer.ignored_columns)
1711
+ assert_equal(%w(first_name last_name), SymbolIgnoredDeveloper.ignored_columns)
1712
+ end
1713
+ end