ibm_db 5.6.1-arm64-darwin-24

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