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,959 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+ require "models/topic" # For booleans
5
+ require "models/pirate" # For timestamps
6
+ require "models/parrot"
7
+ require "models/person" # For optimistic locking
8
+ require "models/aircraft"
9
+ require "models/numeric_data"
10
+
11
+ class DirtyTest < ActiveRecord::TestCase
12
+ include InTimeZone
13
+
14
+ # Dummy to force column loads so query counts are clean.
15
+ def setup
16
+ Person.create first_name: "foo"
17
+ end
18
+
19
+ def teardown
20
+ Person.delete_by(first_name: "foo")
21
+ end
22
+
23
+ def test_attribute_changes
24
+ # New record - no changes.
25
+ pirate = Pirate.new
26
+ assert_equal false, pirate.catchphrase_changed?
27
+ assert_equal false, pirate.non_validated_parrot_id_changed?
28
+
29
+ # Change catchphrase.
30
+ pirate.catchphrase = "arrr"
31
+ assert_predicate pirate, :catchphrase_changed?
32
+ assert_nil pirate.catchphrase_was
33
+ assert_equal [nil, "arrr"], pirate.catchphrase_change
34
+
35
+ # Saved - no changes.
36
+ pirate.save!
37
+ assert_not_predicate pirate, :catchphrase_changed?
38
+ assert_nil pirate.catchphrase_change
39
+
40
+ # Same value - no changes.
41
+ pirate.catchphrase = "arrr"
42
+ assert_not_predicate pirate, :catchphrase_changed?
43
+ assert_nil pirate.catchphrase_change
44
+ end
45
+
46
+ def test_time_attributes_changes_with_time_zone
47
+ in_time_zone "Paris" do
48
+ target = Class.new(ActiveRecord::Base)
49
+ target.table_name = "pirates"
50
+
51
+ # New record - no changes.
52
+ pirate = target.new
53
+ assert_not_predicate pirate, :created_on_changed?
54
+ assert_nil pirate.created_on_change
55
+
56
+ # Saved - no changes.
57
+ pirate.catchphrase = "arrrr, time zone!!"
58
+ pirate.save!
59
+ assert_not_predicate pirate, :created_on_changed?
60
+ assert_nil pirate.created_on_change
61
+
62
+ # Change created_on.
63
+ old_created_on = pirate.created_on
64
+ pirate.created_on = Time.now - 1.day
65
+ assert_predicate pirate, :created_on_changed?
66
+ assert_kind_of ActiveSupport::TimeWithZone, pirate.created_on_was
67
+ assert_equal old_created_on, pirate.created_on_was
68
+ pirate.created_on = old_created_on
69
+ assert_not_predicate pirate, :created_on_changed?
70
+ end
71
+ end
72
+
73
+ def test_setting_time_attributes_with_time_zone_field_to_itself_should_not_be_marked_as_a_change
74
+ in_time_zone "Paris" do
75
+ target = Class.new(ActiveRecord::Base)
76
+ target.table_name = "pirates"
77
+
78
+ pirate = target.create!
79
+ pirate.created_on = pirate.created_on
80
+ assert_not_predicate pirate, :created_on_changed?
81
+ end
82
+ end
83
+
84
+ def test_time_attributes_changes_without_time_zone_by_skip
85
+ in_time_zone "Paris" do
86
+ target = Class.new(ActiveRecord::Base)
87
+ target.table_name = "pirates"
88
+
89
+ target.skip_time_zone_conversion_for_attributes = [:created_on]
90
+
91
+ # New record - no changes.
92
+ pirate = target.new
93
+ assert_not_predicate pirate, :created_on_changed?
94
+ assert_nil pirate.created_on_change
95
+
96
+ # Saved - no changes.
97
+ pirate.catchphrase = "arrrr, time zone!!"
98
+ pirate.save!
99
+ assert_not_predicate pirate, :created_on_changed?
100
+ assert_nil pirate.created_on_change
101
+
102
+ # Change created_on.
103
+ old_created_on = pirate.created_on
104
+ pirate.created_on = Time.now + 1.day
105
+ assert_predicate pirate, :created_on_changed?
106
+ # kind_of does not work because
107
+ # ActiveSupport::TimeWithZone.name == 'Time'
108
+ assert_instance_of Time, pirate.created_on_was
109
+ assert_equal old_created_on, pirate.created_on_was
110
+ end
111
+ end
112
+
113
+ def test_time_attributes_changes_without_time_zone
114
+ with_timezone_config aware_attributes: false do
115
+ target = Class.new(ActiveRecord::Base)
116
+ target.table_name = "pirates"
117
+
118
+ # New record - no changes.
119
+ pirate = target.new
120
+ assert_not_predicate pirate, :created_on_changed?
121
+ assert_nil pirate.created_on_change
122
+
123
+ # Saved - no changes.
124
+ pirate.catchphrase = "arrrr, time zone!!"
125
+ pirate.save!
126
+ assert_not_predicate pirate, :created_on_changed?
127
+ assert_nil pirate.created_on_change
128
+
129
+ # Change created_on.
130
+ old_created_on = pirate.created_on
131
+ pirate.created_on = Time.now + 1.day
132
+ assert_predicate pirate, :created_on_changed?
133
+ # kind_of does not work because
134
+ # ActiveSupport::TimeWithZone.name == 'Time'
135
+ assert_instance_of Time, pirate.created_on_was
136
+ assert_equal old_created_on, pirate.created_on_was
137
+ end
138
+ end
139
+
140
+ def test_aliased_attribute_changes
141
+ # the actual attribute here is name, title is an
142
+ # alias setup via alias_attribute
143
+ parrot = Parrot.new
144
+ assert_not_predicate parrot, :title_changed?
145
+ assert_nil parrot.title_change
146
+
147
+ parrot.name = "Sam"
148
+ assert_predicate parrot, :title_changed?
149
+ assert_nil parrot.title_was
150
+ assert_equal parrot.name_change, parrot.title_change
151
+ end
152
+
153
+ def test_restore_attribute!
154
+ pirate = Pirate.create!(catchphrase: "Yar!")
155
+ pirate.catchphrase = "Ahoy!"
156
+
157
+ assert_equal "Ahoy!", pirate.catchphrase
158
+ assert_equal ["Yar!", "Ahoy!"], pirate.catchphrase_change
159
+
160
+ pirate.restore_catchphrase!
161
+
162
+ assert_nil pirate.catchphrase_change
163
+ assert_equal "Yar!", pirate.catchphrase
164
+ assert_equal Hash.new, pirate.changes
165
+ assert_not_predicate pirate, :catchphrase_changed?
166
+ end
167
+
168
+ def test_clear_attribute_change
169
+ pirate = Pirate.create!(catchphrase: "Yar!")
170
+ pirate.catchphrase = "Ahoy!"
171
+
172
+ assert_equal "Ahoy!", pirate.catchphrase
173
+ assert_equal ["Yar!", "Ahoy!"], pirate.catchphrase_change
174
+
175
+ pirate.clear_catchphrase_change
176
+
177
+ assert_nil pirate.catchphrase_change
178
+ assert_equal "Ahoy!", pirate.catchphrase
179
+ assert_equal Hash.new, pirate.changes
180
+ assert_not_predicate pirate, :catchphrase_changed?
181
+ end
182
+
183
+ def test_nullable_number_not_marked_as_changed_if_new_value_is_blank
184
+ pirate = Pirate.new
185
+
186
+ ["", nil].each do |value|
187
+ pirate.parrot_id = value
188
+ assert_not_predicate pirate, :parrot_id_changed?
189
+ assert_nil pirate.parrot_id_change
190
+ end
191
+ end
192
+
193
+ def test_nullable_decimal_not_marked_as_changed_if_new_value_is_blank
194
+ numeric_data = NumericData.new
195
+
196
+ ["", nil].each do |value|
197
+ numeric_data.bank_balance = value
198
+ assert_not_predicate numeric_data, :bank_balance_changed?
199
+ assert_nil numeric_data.bank_balance_change
200
+ end
201
+ end
202
+
203
+ def test_nullable_float_not_marked_as_changed_if_new_value_is_blank
204
+ numeric_data = NumericData.new
205
+
206
+ ["", nil].each do |value|
207
+ numeric_data.temperature = value
208
+ assert_not_predicate numeric_data, :temperature_changed?
209
+ assert_nil numeric_data.temperature_change
210
+ end
211
+ end
212
+
213
+ def test_nullable_datetime_not_marked_as_changed_if_new_value_is_blank
214
+ in_time_zone "Edinburgh" do
215
+ target = Class.new(ActiveRecord::Base)
216
+ target.table_name = "topics"
217
+
218
+ topic = target.create
219
+ assert_nil topic.written_on
220
+
221
+ ["", nil].each do |value|
222
+ topic.written_on = value
223
+ assert_nil topic.written_on
224
+ assert_not_predicate topic, :written_on_changed?
225
+ end
226
+ end
227
+ end
228
+
229
+ def test_integer_zero_to_string_zero_not_marked_as_changed
230
+ pirate = Pirate.new
231
+ pirate.parrot_id = 0
232
+ pirate.catchphrase = "arrr"
233
+ assert pirate.save!
234
+
235
+ assert_not_predicate pirate, :changed?
236
+
237
+ pirate.parrot_id = "0"
238
+ assert_not_predicate pirate, :changed?
239
+ end
240
+
241
+ def test_integer_zero_to_integer_zero_not_marked_as_changed
242
+ pirate = Pirate.new
243
+ pirate.parrot_id = 0
244
+ pirate.catchphrase = "arrr"
245
+ assert pirate.save!
246
+
247
+ assert_not_predicate pirate, :changed?
248
+
249
+ pirate.parrot_id = 0
250
+ assert_not_predicate pirate, :changed?
251
+ end
252
+
253
+ def test_float_zero_to_string_zero_not_marked_as_changed
254
+ data = NumericData.new temperature: 0.0
255
+ data.save!
256
+
257
+ assert_not_predicate data, :changed?
258
+
259
+ data.temperature = "0"
260
+ assert_empty data.changes
261
+
262
+ data.temperature = "0.0"
263
+ assert_empty data.changes
264
+
265
+ data.temperature = "0.00"
266
+ assert_empty data.changes
267
+ end
268
+
269
+ def test_zero_to_blank_marked_as_changed
270
+ pirate = Pirate.new
271
+ pirate.catchphrase = "Yarrrr, me hearties"
272
+ pirate.parrot_id = 1
273
+ pirate.save
274
+
275
+ # check the change from 1 to ''
276
+ pirate = Pirate.find_by_catchphrase("Yarrrr, me hearties")
277
+ pirate.parrot_id = ""
278
+ assert_predicate pirate, :parrot_id_changed?
279
+ assert_equal([1, nil], pirate.parrot_id_change)
280
+ pirate.save
281
+
282
+ # check the change from nil to 0
283
+ pirate = Pirate.find_by_catchphrase("Yarrrr, me hearties")
284
+ pirate.parrot_id = 0
285
+ assert_predicate pirate, :parrot_id_changed?
286
+ assert_equal([nil, 0], pirate.parrot_id_change)
287
+ pirate.save
288
+
289
+ # check the change from 0 to ''
290
+ pirate = Pirate.find_by_catchphrase("Yarrrr, me hearties")
291
+ pirate.parrot_id = ""
292
+ assert_predicate pirate, :parrot_id_changed?
293
+ assert_equal([0, nil], pirate.parrot_id_change)
294
+ end
295
+
296
+ def test_object_should_be_changed_if_any_attribute_is_changed
297
+ pirate = Pirate.new
298
+ assert_not_predicate pirate, :changed?
299
+ assert_equal [], pirate.changed
300
+ assert_equal Hash.new, pirate.changes
301
+
302
+ pirate.catchphrase = "arrr"
303
+ assert_predicate pirate, :changed?
304
+ assert_nil pirate.catchphrase_was
305
+ assert_equal %w(catchphrase), pirate.changed
306
+ assert_equal({ "catchphrase" => [nil, "arrr"] }, pirate.changes)
307
+
308
+ pirate.save
309
+ assert_not_predicate pirate, :changed?
310
+ assert_equal [], pirate.changed
311
+ assert_equal Hash.new, pirate.changes
312
+ end
313
+
314
+ def test_attribute_will_change!
315
+ pirate = Pirate.create!(catchphrase: "arr")
316
+
317
+ assert_not_predicate pirate, :catchphrase_changed?
318
+ assert pirate.catchphrase_will_change!
319
+ assert_predicate pirate, :catchphrase_changed?
320
+ assert_equal ["arr", "arr"], pirate.catchphrase_change
321
+
322
+ pirate.catchphrase << " matey!"
323
+ assert_predicate pirate, :catchphrase_changed?
324
+ assert_equal ["arr", "arr matey!"], pirate.catchphrase_change
325
+ end
326
+
327
+ def test_virtual_attribute_will_change
328
+ parrot = Parrot.create!(name: "Ruby")
329
+ parrot.send(:attribute_will_change!, :cancel_save_from_callback)
330
+ assert_predicate parrot, :has_changes_to_save?
331
+ end
332
+
333
+ def test_association_assignment_changes_foreign_key
334
+ pirate = Pirate.create!(catchphrase: "jarl")
335
+ pirate.parrot = Parrot.create!(name: "Lorre")
336
+ assert_predicate pirate, :changed?
337
+ assert_equal %w(parrot_id), pirate.changed
338
+ end
339
+
340
+ def test_attribute_should_be_compared_with_type_cast
341
+ topic = Topic.new
342
+ assert_predicate topic, :approved?
343
+ assert_not_predicate topic, :approved_changed?
344
+
345
+ # Coming from web form.
346
+ params = { topic: { approved: 1 } }
347
+ # In the controller.
348
+ topic.attributes = params[:topic]
349
+ assert_predicate topic, :approved?
350
+ assert_not_predicate topic, :approved_changed?
351
+ end
352
+
353
+ def test_string_attribute_should_compare_with_typecast_symbol_after_update
354
+ pirate = Pirate.create!(catchphrase: :foo)
355
+ pirate.update_column :catchphrase, :foo
356
+ pirate.catchphrase
357
+ assert_not_predicate pirate, :catchphrase_changed?
358
+ end
359
+
360
+ def test_partial_update
361
+ pirate = Pirate.new(catchphrase: "foo")
362
+ old_updated_on = 1.hour.ago.beginning_of_day
363
+
364
+ with_partial_writes Pirate, false do
365
+ assert_queries(2) { 2.times { pirate.save! } }
366
+ Pirate.where(id: pirate.id).update_all(updated_on: old_updated_on)
367
+ end
368
+
369
+ with_partial_writes Pirate, true do
370
+ assert_no_queries { 2.times { pirate.save! } }
371
+ assert_equal old_updated_on, pirate.reload.updated_on
372
+
373
+ assert_queries(1) { pirate.catchphrase = "bar"; pirate.save! }
374
+ assert_not_equal old_updated_on, pirate.reload.updated_on
375
+ end
376
+ end
377
+
378
+ def test_partial_update_with_optimistic_locking
379
+ person = Person.new(first_name: "foo")
380
+
381
+ with_partial_writes Person, false do
382
+ assert_queries(2) { 2.times { person.save! } }
383
+ Person.where(id: person.id).update_all(first_name: "baz")
384
+ end
385
+
386
+ old_lock_version = person.lock_version + 1
387
+
388
+ with_partial_writes Person, true do
389
+ assert_no_queries { 2.times { person.save! } }
390
+ assert_equal old_lock_version, person.reload.lock_version
391
+
392
+ assert_queries(1) { person.first_name = "bar"; person.save! }
393
+ assert_not_equal old_lock_version, person.reload.lock_version
394
+ end
395
+ end
396
+
397
+ def test_changed_attributes_should_be_preserved_if_save_failure
398
+ pirate = Pirate.new
399
+ pirate.parrot_id = 1
400
+ assert_not pirate.save
401
+ check_pirate_after_save_failure(pirate)
402
+
403
+ pirate = Pirate.new
404
+ pirate.parrot_id = 1
405
+ assert_raise(ActiveRecord::RecordInvalid) { pirate.save! }
406
+ check_pirate_after_save_failure(pirate)
407
+ end
408
+
409
+ def test_reload_should_clear_changed_attributes
410
+ pirate = Pirate.create!(catchphrase: "shiver me timbers")
411
+ pirate.catchphrase = "*hic*"
412
+ assert_predicate pirate, :changed?
413
+ pirate.reload
414
+ assert_not_predicate pirate, :changed?
415
+ end
416
+
417
+ def test_dup_objects_should_not_copy_dirty_flag_from_creator
418
+ pirate = Pirate.create!(catchphrase: "shiver me timbers")
419
+ pirate_dup = pirate.dup
420
+ pirate_dup.restore_catchphrase!
421
+ pirate.catchphrase = "I love Rum"
422
+ assert_predicate pirate, :catchphrase_changed?
423
+ assert_not_predicate pirate_dup, :catchphrase_changed?
424
+ end
425
+
426
+ def test_reverted_changes_are_not_dirty
427
+ phrase = "shiver me timbers"
428
+ pirate = Pirate.create!(catchphrase: phrase)
429
+ pirate.catchphrase = "*hic*"
430
+ assert_predicate pirate, :changed?
431
+ pirate.catchphrase = phrase
432
+ assert_not_predicate pirate, :changed?
433
+ end
434
+
435
+ def test_reverted_changes_are_not_dirty_after_multiple_changes
436
+ phrase = "shiver me timbers"
437
+ pirate = Pirate.create!(catchphrase: phrase)
438
+ 10.times do |i|
439
+ pirate.catchphrase = "*hic*" * i
440
+ assert_predicate pirate, :changed?
441
+ end
442
+ assert_predicate pirate, :changed?
443
+ pirate.catchphrase = phrase
444
+ assert_not_predicate pirate, :changed?
445
+ end
446
+
447
+ def test_reverted_changes_are_not_dirty_going_from_nil_to_value_and_back
448
+ pirate = Pirate.create!(catchphrase: "Yar!")
449
+
450
+ pirate.parrot_id = 1
451
+ assert_predicate pirate, :changed?
452
+ assert_predicate pirate, :parrot_id_changed?
453
+ assert_not_predicate pirate, :catchphrase_changed?
454
+
455
+ pirate.parrot_id = nil
456
+ assert_not_predicate pirate, :changed?
457
+ assert_not_predicate pirate, :parrot_id_changed?
458
+ assert_not_predicate pirate, :catchphrase_changed?
459
+ end
460
+
461
+ def test_save_should_store_serialized_attributes_even_with_partial_writes
462
+ with_partial_writes(Topic) do
463
+ topic = Topic.create!(content: { a: "a" })
464
+
465
+ assert_not_predicate topic, :changed?
466
+
467
+ topic.content[:b] = "b"
468
+
469
+ assert_predicate topic, :changed?
470
+
471
+ topic.save!
472
+
473
+ assert_not_predicate topic, :changed?
474
+ assert_equal "b", topic.content[:b]
475
+
476
+ topic.reload
477
+
478
+ assert_equal "b", topic.content[:b]
479
+ end
480
+ end
481
+
482
+ def test_save_always_should_update_timestamps_when_serialized_attributes_are_present
483
+ with_partial_writes(Topic) do
484
+ topic = Topic.create!(content: { a: "a" })
485
+ topic.save!
486
+
487
+ updated_at = topic.updated_at
488
+ travel(1.second) do
489
+ topic.content[:hello] = "world"
490
+ topic.save!
491
+ end
492
+
493
+ assert_not_equal updated_at, topic.updated_at
494
+ assert_equal "world", topic.content[:hello]
495
+ end
496
+ end
497
+
498
+ def test_save_should_not_save_serialized_attribute_with_partial_writes_if_not_present
499
+ with_partial_writes(Topic) do
500
+ topic = Topic.create!(author_name: "Bill", content: { a: "a" })
501
+ topic = Topic.select("id, author_name").find(topic.id)
502
+ topic.update_columns author_name: "John"
503
+ assert_not_nil topic.reload.content
504
+ end
505
+ end
506
+
507
+ def test_changes_to_save_should_not_mutate_array_of_hashes
508
+ topic = Topic.new(author_name: "Bill", content: [{ a: "a" }])
509
+
510
+ topic.changes_to_save
511
+
512
+ assert_equal [{ a: "a" }], topic.content
513
+ end
514
+
515
+ def test_previous_changes
516
+ # original values should be in previous_changes
517
+ pirate = Pirate.new
518
+
519
+ assert_equal Hash.new, pirate.previous_changes
520
+ pirate.catchphrase = "arrr"
521
+ pirate.save!
522
+
523
+ assert_equal 4, pirate.previous_changes.size
524
+ assert_equal [nil, "arrr"], pirate.previous_changes["catchphrase"]
525
+ assert_nil pirate.catchphrase_previously_was
526
+ assert_equal [nil, pirate.id], pirate.previous_changes["id"]
527
+ assert_nil pirate.previous_changes["updated_on"][0]
528
+ assert_not_nil pirate.previous_changes["updated_on"][1]
529
+ assert_nil pirate.previous_changes["created_on"][0]
530
+ assert_not_nil pirate.previous_changes["created_on"][1]
531
+ assert_not pirate.previous_changes.key?("parrot_id")
532
+
533
+ # original values should be in previous_changes
534
+ pirate = Pirate.new
535
+
536
+ assert_equal Hash.new, pirate.previous_changes
537
+ pirate.catchphrase = "arrr"
538
+ pirate.save
539
+
540
+ assert_equal 4, pirate.previous_changes.size
541
+ assert_equal [nil, "arrr"], pirate.previous_changes["catchphrase"]
542
+ assert_nil pirate.catchphrase_previously_was
543
+ assert_equal [nil, pirate.id], pirate.previous_changes["id"]
544
+ assert_includes pirate.previous_changes, "updated_on"
545
+ assert_includes pirate.previous_changes, "created_on"
546
+ assert_not pirate.previous_changes.key?("parrot_id")
547
+
548
+ pirate.catchphrase = "Yar!!"
549
+ pirate.reload
550
+ assert_equal Hash.new, pirate.previous_changes
551
+
552
+ pirate = Pirate.find_by_catchphrase("arrr")
553
+
554
+ travel(1.second)
555
+
556
+ pirate.catchphrase = "Me Maties!"
557
+ pirate.save!
558
+
559
+ assert_equal 2, pirate.previous_changes.size
560
+ assert_equal ["arrr", "Me Maties!"], pirate.previous_changes["catchphrase"]
561
+ assert_equal "arrr", pirate.catchphrase_previously_was
562
+ assert_not_nil pirate.previous_changes["updated_on"][0]
563
+ assert_not_nil pirate.previous_changes["updated_on"][1]
564
+ assert_not pirate.previous_changes.key?("parrot_id")
565
+ assert_not pirate.previous_changes.key?("created_on")
566
+
567
+ pirate = Pirate.find_by_catchphrase("Me Maties!")
568
+
569
+ travel(1.second)
570
+
571
+ pirate.catchphrase = "Thar She Blows!"
572
+ pirate.save
573
+
574
+ assert_equal 2, pirate.previous_changes.size
575
+ assert_equal ["Me Maties!", "Thar She Blows!"], pirate.previous_changes["catchphrase"]
576
+ assert_equal "Me Maties!", pirate.catchphrase_previously_was
577
+ assert_not_nil pirate.previous_changes["updated_on"][0]
578
+ assert_not_nil pirate.previous_changes["updated_on"][1]
579
+ assert_not pirate.previous_changes.key?("parrot_id")
580
+ assert_not pirate.previous_changes.key?("created_on")
581
+
582
+ travel(1.second)
583
+
584
+ pirate = Pirate.find_by_catchphrase("Thar She Blows!")
585
+ pirate.update(catchphrase: "Ahoy!")
586
+
587
+ assert_equal 2, pirate.previous_changes.size
588
+ assert_equal ["Thar She Blows!", "Ahoy!"], pirate.previous_changes["catchphrase"]
589
+ assert_equal "Thar She Blows!", pirate.catchphrase_previously_was
590
+ assert_not_nil pirate.previous_changes["updated_on"][0]
591
+ assert_not_nil pirate.previous_changes["updated_on"][1]
592
+ assert_not pirate.previous_changes.key?("parrot_id")
593
+ assert_not pirate.previous_changes.key?("created_on")
594
+
595
+ travel(1.second)
596
+
597
+ pirate = Pirate.find_by_catchphrase("Ahoy!")
598
+ pirate.update_attribute(:catchphrase, "Ninjas suck!")
599
+
600
+ assert_equal 2, pirate.previous_changes.size
601
+ assert_equal ["Ahoy!", "Ninjas suck!"], pirate.previous_changes["catchphrase"]
602
+ assert_equal "Ahoy!", pirate.catchphrase_previously_was
603
+ assert_not_nil pirate.previous_changes["updated_on"][0]
604
+ assert_not_nil pirate.previous_changes["updated_on"][1]
605
+ assert_not pirate.previous_changes.key?("parrot_id")
606
+ assert_not pirate.previous_changes.key?("created_on")
607
+ end
608
+
609
+ class Testings < ActiveRecord::Base; end
610
+ def test_field_named_field
611
+ ActiveRecord::Base.connection.create_table :testings do |t|
612
+ t.string :field
613
+ end
614
+ assert_nothing_raised do
615
+ Testings.new.attributes
616
+ end
617
+ ensure
618
+ ActiveRecord::Base.connection.drop_table :testings rescue nil
619
+ ActiveRecord::Base.clear_cache!
620
+ end
621
+
622
+ def test_datetime_attribute_can_be_updated_with_fractional_seconds
623
+ skip "Fractional seconds are not supported" unless supports_datetime_with_precision?
624
+ in_time_zone "Paris" do
625
+ target = Class.new(ActiveRecord::Base)
626
+ target.table_name = "topics"
627
+
628
+ written_on = Time.utc(2012, 12, 1, 12, 0, 0).in_time_zone("Paris")
629
+
630
+ topic = target.create(written_on: written_on)
631
+ topic.written_on += 0.3
632
+
633
+ assert topic.written_on_changed?, "Fractional second update not detected"
634
+ end
635
+ end
636
+
637
+ def test_datetime_attribute_doesnt_change_if_zone_is_modified_in_string
638
+ time_in_paris = Time.utc(2014, 1, 1, 12, 0, 0).in_time_zone("Paris")
639
+ pirate = Pirate.create!(catchphrase: "rrrr", created_on: time_in_paris)
640
+
641
+ pirate.created_on = pirate.created_on.in_time_zone("Tokyo").to_s
642
+ assert_not_predicate pirate, :created_on_changed?
643
+ end
644
+
645
+ test "partial insert" do
646
+ with_partial_writes Person do
647
+ jon = nil
648
+ assert_sql(/first_name/i) do
649
+ jon = Person.create! first_name: "Jon"
650
+ end
651
+
652
+ assert ActiveRecord::SQLCounter.log_all.none? { |sql| sql.include?("followers_count") }
653
+
654
+ jon.reload
655
+ assert_equal "Jon", jon.first_name
656
+ assert_equal 0, jon.followers_count
657
+ assert_not_nil jon.id
658
+ end
659
+ end
660
+
661
+ test "partial insert with empty values" do
662
+ with_partial_writes Aircraft do
663
+ a = Aircraft.create!
664
+ a.reload
665
+ assert_not_nil a.id
666
+ end
667
+ end
668
+
669
+ test "in place mutation detection" do
670
+ pirate = Pirate.create!(catchphrase: "arrrr")
671
+ pirate.catchphrase << " matey!"
672
+
673
+ assert_predicate pirate, :catchphrase_changed?
674
+ expected_changes = {
675
+ "catchphrase" => ["arrrr", "arrrr matey!"]
676
+ }
677
+ assert_equal(expected_changes, pirate.changes)
678
+ assert_equal("arrrr", pirate.catchphrase_was)
679
+ assert pirate.catchphrase_changed?(from: "arrrr")
680
+ assert_not pirate.catchphrase_changed?(from: "anything else")
681
+ assert_includes pirate.changed_attributes, :catchphrase
682
+
683
+ pirate.save!
684
+ pirate.reload
685
+
686
+ assert_equal "arrrr matey!", pirate.catchphrase
687
+ assert_not_predicate pirate, :changed?
688
+ end
689
+
690
+ test "in place mutation for binary" do
691
+ klass = Class.new(ActiveRecord::Base) do
692
+ self.table_name = :binaries
693
+ serialize :data
694
+ end
695
+
696
+ binary = klass.create!(data: "\\\\foo")
697
+
698
+ assert_not_predicate binary, :changed?
699
+
700
+ binary.data = binary.data.dup
701
+
702
+ assert_not_predicate binary, :changed?
703
+
704
+ binary = klass.last
705
+
706
+ assert_not_predicate binary, :changed?
707
+
708
+ binary.data << "bar"
709
+
710
+ assert_predicate binary, :changed?
711
+ end
712
+
713
+ test "changes is correct for subclass" do
714
+ foo = Class.new(Pirate) do
715
+ def catchphrase
716
+ super.upcase
717
+ end
718
+ end
719
+
720
+ pirate = foo.create!(catchphrase: "arrrr")
721
+
722
+ new_catchphrase = "arrrr matey!"
723
+
724
+ pirate.catchphrase = new_catchphrase
725
+ assert_predicate pirate, :catchphrase_changed?
726
+
727
+ expected_changes = {
728
+ "catchphrase" => ["arrrr", new_catchphrase]
729
+ }
730
+
731
+ assert_equal new_catchphrase.upcase, pirate.catchphrase
732
+ assert_equal expected_changes, pirate.changes
733
+ end
734
+
735
+ test "changes is correct if override attribute reader" do
736
+ pirate = Pirate.create!(catchphrase: "arrrr")
737
+ def pirate.catchphrase
738
+ super.upcase
739
+ end
740
+
741
+ new_catchphrase = "arrrr matey!"
742
+
743
+ pirate.catchphrase = new_catchphrase
744
+ assert_predicate pirate, :catchphrase_changed?
745
+
746
+ expected_changes = {
747
+ "catchphrase" => ["arrrr", new_catchphrase]
748
+ }
749
+
750
+ assert_equal new_catchphrase.upcase, pirate.catchphrase
751
+ assert_equal expected_changes, pirate.changes
752
+ end
753
+
754
+ test "attribute_changed? doesn't compute in-place changes for unrelated attributes" do
755
+ test_type_class = Class.new(ActiveRecord::Type::Value) do
756
+ define_method(:changed_in_place?) do |*|
757
+ raise
758
+ end
759
+ end
760
+ klass = Class.new(ActiveRecord::Base) do
761
+ self.table_name = "people"
762
+ attribute :foo, test_type_class.new
763
+ end
764
+
765
+ model = klass.new(first_name: "Jim")
766
+ assert_predicate model, :first_name_changed?
767
+ end
768
+
769
+ test "attribute_will_change! doesn't try to save non-persistable attributes" do
770
+ klass = Class.new(ActiveRecord::Base) do
771
+ self.table_name = "people"
772
+ attribute :non_persisted_attribute, :string
773
+ end
774
+
775
+ record = klass.new(first_name: "Sean")
776
+ record.non_persisted_attribute_will_change!
777
+
778
+ assert_predicate record, :non_persisted_attribute_changed?
779
+ assert record.save
780
+ end
781
+
782
+ test "virtual attributes are not written with partial_writes off" do
783
+ with_partial_writes(ActiveRecord::Base, false) do
784
+ klass = Class.new(ActiveRecord::Base) do
785
+ self.table_name = "people"
786
+ attribute :non_persisted_attribute, :string
787
+ end
788
+
789
+ record = klass.new(first_name: "Sean")
790
+ record.non_persisted_attribute_will_change!
791
+
792
+ assert record.save
793
+
794
+ record.non_persisted_attribute_will_change!
795
+
796
+ assert record.save
797
+ end
798
+ end
799
+
800
+ test "mutating and then assigning doesn't remove the change" do
801
+ pirate = Pirate.create!(catchphrase: "arrrr")
802
+ pirate.catchphrase << " matey!"
803
+ pirate.catchphrase = "arrrr matey!"
804
+
805
+ assert pirate.catchphrase_changed?(from: "arrrr", to: "arrrr matey!")
806
+ end
807
+
808
+ test "getters with side effects are allowed" do
809
+ klass = Class.new(Pirate) do
810
+ def catchphrase
811
+ if super.blank?
812
+ update_attribute(:catchphrase, "arr") # what could possibly go wrong?
813
+ end
814
+ super
815
+ end
816
+ end
817
+
818
+ pirate = klass.create!(catchphrase: "lol")
819
+ pirate.update_attribute(:catchphrase, nil)
820
+
821
+ assert_equal "arr", pirate.catchphrase
822
+ end
823
+
824
+ test "attributes assigned but not selected are dirty" do
825
+ person = Person.select(:id).first
826
+ assert_not_predicate person, :changed?
827
+
828
+ person.first_name = "Sean"
829
+ assert_predicate person, :changed?
830
+
831
+ person.first_name = nil
832
+ assert_predicate person, :changed?
833
+ end
834
+
835
+ test "attributes not selected are still missing after save" do
836
+ person = Person.select(:id).first
837
+ assert_raises(ActiveModel::MissingAttributeError) { person.first_name }
838
+ assert person.save # calls forget_attribute_assignments
839
+ assert_raises(ActiveModel::MissingAttributeError) { person.first_name }
840
+ end
841
+
842
+ test "saved_change_to_attribute? returns whether a change occurred in the last save" do
843
+ person = Person.create!(first_name: "Sean")
844
+
845
+ assert_predicate person, :saved_change_to_first_name?
846
+ assert_not_predicate person, :saved_change_to_gender?
847
+ assert person.saved_change_to_first_name?(from: nil, to: "Sean")
848
+ assert person.saved_change_to_first_name?(from: nil)
849
+ assert person.saved_change_to_first_name?(to: "Sean")
850
+ assert_not person.saved_change_to_first_name?(from: "Jim", to: "Sean")
851
+ assert_not person.saved_change_to_first_name?(from: "Jim")
852
+ assert_not person.saved_change_to_first_name?(to: "Jim")
853
+ end
854
+
855
+ test "saved_change_to_attribute returns the change that occurred in the last save" do
856
+ person = Person.create!(first_name: "Sean", gender: "M")
857
+
858
+ assert_equal [nil, "Sean"], person.saved_change_to_first_name
859
+ assert_equal [nil, "M"], person.saved_change_to_gender
860
+
861
+ person.update(first_name: "Jim")
862
+
863
+ assert_equal ["Sean", "Jim"], person.saved_change_to_first_name
864
+ assert_nil person.saved_change_to_gender
865
+ end
866
+
867
+ test "attribute_before_last_save returns the original value before saving" do
868
+ person = Person.create!(first_name: "Sean", gender: "M")
869
+
870
+ assert_nil person.first_name_before_last_save
871
+ assert_nil person.gender_before_last_save
872
+
873
+ person.first_name = "Jim"
874
+
875
+ assert_nil person.first_name_before_last_save
876
+ assert_nil person.gender_before_last_save
877
+
878
+ person.save
879
+
880
+ assert_equal "Sean", person.first_name_before_last_save
881
+ assert_equal "M", person.gender_before_last_save
882
+ end
883
+
884
+ test "saved_changes? returns whether the last call to save changed anything" do
885
+ person = Person.create!(first_name: "Sean")
886
+
887
+ assert_predicate person, :saved_changes?
888
+
889
+ person.save
890
+
891
+ assert_not_predicate person, :saved_changes?
892
+ end
893
+
894
+ test "saved_changes returns a hash of all the changes that occurred" do
895
+ person = Person.create!(first_name: "Sean", gender: "M")
896
+
897
+ assert_equal [nil, "Sean"], person.saved_changes[:first_name]
898
+ assert_equal [nil, "M"], person.saved_changes[:gender]
899
+ assert_equal %w(id first_name gender created_at updated_at).sort, person.saved_changes.keys.sort
900
+
901
+ travel(1.second) do
902
+ person.update(first_name: "Jim")
903
+ end
904
+
905
+ assert_equal ["Sean", "Jim"], person.saved_changes[:first_name]
906
+ assert_equal %w(first_name lock_version updated_at).sort, person.saved_changes.keys.sort
907
+ end
908
+
909
+ test "changed? in after callbacks returns false" do
910
+ klass = Class.new(ActiveRecord::Base) do
911
+ self.table_name = "people"
912
+
913
+ after_save do
914
+ raise "changed? should be false" if changed?
915
+ raise "has_changes_to_save? should be false" if has_changes_to_save?
916
+ raise "saved_changes? should be true" unless saved_changes?
917
+ raise "id_in_database should not be nil" if id_in_database.nil?
918
+ end
919
+ end
920
+
921
+ person = klass.create!(first_name: "Sean")
922
+ assert_not_predicate person, :changed?
923
+ end
924
+
925
+ test "changed? in around callbacks after yield returns false" do
926
+ klass = Class.new(ActiveRecord::Base) do
927
+ self.table_name = "people"
928
+
929
+ around_create :check_around
930
+
931
+ def check_around
932
+ yield
933
+ raise "changed? should be false" if changed?
934
+ raise "has_changes_to_save? should be false" if has_changes_to_save?
935
+ raise "saved_changes? should be true" unless saved_changes?
936
+ raise "id_in_database should not be nil" if id_in_database.nil?
937
+ end
938
+ end
939
+
940
+ person = klass.create!(first_name: "Sean")
941
+ assert_not_predicate person, :changed?
942
+ end
943
+
944
+ private
945
+ def with_partial_writes(klass, on = true)
946
+ old = klass.partial_writes?
947
+ klass.partial_writes = on
948
+ yield
949
+ ensure
950
+ klass.partial_writes = old
951
+ end
952
+
953
+ def check_pirate_after_save_failure(pirate)
954
+ assert_predicate pirate, :changed?
955
+ assert_predicate pirate, :parrot_id_changed?
956
+ assert_equal %w(parrot_id), pirate.changed
957
+ assert_nil pirate.parrot_id_was
958
+ end
959
+ end