ibm_db 5.6.1 → 5.7.0

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 (592) hide show
  1. checksums.yaml +4 -4
  2. data/ext/Makefile +13 -9
  3. data/ext/extconf.rb +176 -110
  4. data/ext/ibm_db.c +60 -0
  5. data/ext/ibm_db.o +0 -0
  6. data/ext/ibm_db.so +0 -0
  7. data/ext/mkmf.log +6 -6
  8. data/ext/ruby_ibm_db_cli.c +14 -10
  9. data/ext/ruby_ibm_db_cli.h +4 -0
  10. data/ext/ruby_ibm_db_cli.o +0 -0
  11. data/lib/IBM_DB.rb +2 -2
  12. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +1254 -277
  13. data/test/active_record/connection_adapters/fake_legacy_adapter.rb +17 -0
  14. data/test/active_record/connection_adapters/fake_misleading_legacy_adapter.rb +8 -0
  15. data/test/activejob/destroy_association_async_job_test.rb +62 -0
  16. data/test/activejob/destroy_association_async_test.rb +147 -11
  17. data/test/activejob/job_runtime_test.rb +41 -0
  18. data/test/activejob/unloadable_base_job.rb +3 -0
  19. data/test/cases/active_record_schema_test.rb +196 -0
  20. data/test/cases/active_record_test.rb +21 -0
  21. data/test/cases/adapter_prevent_writes_test.rb +26 -202
  22. data/test/cases/adapter_test.rb +592 -82
  23. data/test/cases/adapters/abstract_mysql_adapter/active_schema_test.rb +210 -0
  24. data/test/cases/adapters/abstract_mysql_adapter/adapter_prevent_writes_test.rb +111 -0
  25. data/test/cases/adapters/abstract_mysql_adapter/auto_increment_test.rb +48 -0
  26. data/test/cases/adapters/abstract_mysql_adapter/bind_parameter_test.rb +91 -0
  27. data/test/cases/adapters/abstract_mysql_adapter/case_sensitivity_test.rb +65 -0
  28. data/test/cases/adapters/abstract_mysql_adapter/charset_collation_test.rb +85 -0
  29. data/test/cases/adapters/abstract_mysql_adapter/connection_test.rb +267 -0
  30. data/test/cases/adapters/abstract_mysql_adapter/count_deleted_rows_with_lock_test.rb +29 -0
  31. data/test/cases/adapters/abstract_mysql_adapter/json_test.rb +24 -0
  32. data/test/cases/adapters/abstract_mysql_adapter/mysql_boolean_test.rb +102 -0
  33. data/test/cases/adapters/abstract_mysql_adapter/mysql_enum_test.rb +47 -0
  34. data/test/cases/adapters/abstract_mysql_adapter/mysql_explain_test.rb +71 -0
  35. data/test/cases/adapters/abstract_mysql_adapter/nested_deadlock_test.rb +191 -0
  36. data/test/cases/adapters/abstract_mysql_adapter/optimizer_hints_test.rb +69 -0
  37. data/test/cases/adapters/abstract_mysql_adapter/quoting_test.rb +49 -0
  38. data/test/cases/adapters/abstract_mysql_adapter/schema_migrations_test.rb +68 -0
  39. data/test/cases/adapters/abstract_mysql_adapter/schema_test.rb +130 -0
  40. data/test/cases/adapters/abstract_mysql_adapter/set_test.rb +32 -0
  41. data/test/cases/adapters/abstract_mysql_adapter/sp_test.rb +39 -0
  42. data/test/cases/adapters/abstract_mysql_adapter/sql_types_test.rb +16 -0
  43. data/test/cases/adapters/abstract_mysql_adapter/table_options_test.rb +125 -0
  44. data/test/cases/adapters/abstract_mysql_adapter/transaction_test.rb +204 -0
  45. data/test/cases/adapters/abstract_mysql_adapter/unsigned_type_test.rb +77 -0
  46. data/test/cases/adapters/abstract_mysql_adapter/virtual_column_test.rb +69 -0
  47. data/test/cases/adapters/abstract_mysql_adapter/warnings_test.rb +109 -0
  48. data/test/cases/adapters/mysql2/check_constraint_quoting_test.rb +35 -0
  49. data/test/cases/adapters/mysql2/dbconsole_test.rb +87 -0
  50. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +136 -10
  51. data/test/cases/adapters/mysql2/mysql2_rake_test.rb +433 -0
  52. data/test/cases/adapters/postgresql/active_schema_test.rb +8 -4
  53. data/test/cases/adapters/postgresql/array_test.rb +6 -6
  54. data/test/cases/adapters/postgresql/bind_parameter_test.rb +52 -0
  55. data/test/cases/adapters/postgresql/bit_string_test.rb +2 -2
  56. data/test/cases/adapters/postgresql/bytea_test.rb +3 -3
  57. data/test/cases/adapters/postgresql/case_insensitive_test.rb +1 -1
  58. data/test/cases/adapters/postgresql/change_schema_test.rb +32 -1
  59. data/test/cases/adapters/postgresql/cidr_test.rb +17 -0
  60. data/test/cases/adapters/postgresql/citext_test.rb +7 -1
  61. data/test/cases/adapters/postgresql/collation_test.rb +1 -1
  62. data/test/cases/adapters/postgresql/composite_test.rb +1 -1
  63. data/test/cases/adapters/postgresql/connection_test.rb +43 -36
  64. data/test/cases/adapters/postgresql/create_unlogged_tables_test.rb +3 -2
  65. data/test/cases/adapters/postgresql/datatype_test.rb +9 -4
  66. data/test/cases/adapters/postgresql/date_test.rb +2 -2
  67. data/test/cases/adapters/postgresql/dbconsole_test.rb +109 -0
  68. data/test/cases/adapters/postgresql/deferred_constraints_test.rb +55 -0
  69. data/test/cases/adapters/postgresql/domain_test.rb +1 -1
  70. data/test/cases/adapters/postgresql/enum_test.rb +208 -8
  71. data/test/cases/adapters/postgresql/explain_test.rb +25 -6
  72. data/test/cases/adapters/postgresql/extension_migration_test.rb +51 -9
  73. data/test/cases/adapters/postgresql/foreign_table_test.rb +3 -3
  74. data/test/cases/adapters/postgresql/full_text_test.rb +1 -1
  75. data/test/cases/adapters/postgresql/geometric_test.rb +13 -6
  76. data/test/cases/adapters/postgresql/hstore_test.rb +22 -32
  77. data/test/cases/adapters/postgresql/infinity_test.rb +13 -2
  78. data/test/cases/adapters/postgresql/integer_test.rb +1 -1
  79. data/test/cases/adapters/postgresql/interval_test.rb +9 -17
  80. data/test/cases/adapters/postgresql/invertible_migration_test.rb +139 -0
  81. data/test/cases/adapters/postgresql/json_test.rb +5 -0
  82. data/test/cases/adapters/postgresql/ltree_test.rb +1 -1
  83. data/test/cases/adapters/postgresql/money_test.rb +17 -9
  84. data/test/cases/adapters/postgresql/network_test.rb +13 -1
  85. data/test/cases/adapters/postgresql/numbers_test.rb +18 -2
  86. data/test/cases/adapters/postgresql/optimizer_hints_test.rb +9 -9
  87. data/test/cases/adapters/postgresql/partitions_test.rb +5 -2
  88. data/test/cases/adapters/postgresql/postgresql_adapter_prevent_writes_test.rb +7 -110
  89. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +403 -20
  90. data/test/cases/adapters/postgresql/postgresql_rake_test.rb +637 -0
  91. data/test/cases/adapters/postgresql/prepared_statements_disabled_test.rb +1 -1
  92. data/test/cases/adapters/postgresql/quoting_test.rb +60 -1
  93. data/test/cases/adapters/postgresql/range_test.rb +185 -21
  94. data/test/cases/adapters/postgresql/referential_integrity_test.rb +29 -5
  95. data/test/cases/adapters/postgresql/rename_table_test.rb +35 -8
  96. data/test/cases/adapters/postgresql/schema_authorization_test.rb +2 -2
  97. data/test/cases/adapters/postgresql/schema_test.rb +270 -20
  98. data/test/cases/adapters/postgresql/serial_test.rb +5 -5
  99. data/test/cases/adapters/postgresql/statement_pool_test.rb +6 -2
  100. data/test/cases/adapters/postgresql/timestamp_test.rb +122 -5
  101. data/test/cases/adapters/postgresql/transaction_nested_test.rb +130 -6
  102. data/test/cases/adapters/postgresql/transaction_test.rb +37 -11
  103. data/test/cases/adapters/postgresql/type_lookup_test.rb +1 -1
  104. data/test/cases/adapters/postgresql/uuid_test.rb +77 -9
  105. data/test/cases/adapters/postgresql/virtual_column_test.rb +114 -0
  106. data/test/cases/adapters/postgresql/xml_test.rb +1 -1
  107. data/test/cases/adapters/sqlite3/bind_parameter_test.rb +52 -0
  108. data/test/cases/adapters/sqlite3/collation_test.rb +1 -1
  109. data/test/cases/adapters/sqlite3/copy_table_test.rb +28 -7
  110. data/test/cases/adapters/sqlite3/dbconsole_test.rb +81 -0
  111. data/test/cases/adapters/sqlite3/explain_test.rb +3 -3
  112. data/test/cases/adapters/sqlite3/quoting_test.rb +34 -3
  113. data/test/cases/adapters/sqlite3/sqlite3_adapter_prevent_writes_test.rb +9 -102
  114. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +727 -72
  115. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +6 -3
  116. data/test/cases/adapters/sqlite3/sqlite_rake_test.rb +264 -0
  117. data/test/cases/adapters/sqlite3/statement_pool_test.rb +1 -1
  118. data/test/cases/adapters/sqlite3/transaction_test.rb +6 -3
  119. data/test/cases/adapters/sqlite3/virtual_column_test.rb +138 -0
  120. data/test/cases/adapters/sqlite3/virtual_table_test.rb +51 -0
  121. data/test/cases/adapters/trilogy/dbconsole_test.rb +76 -0
  122. data/test/cases/adapters/trilogy/trilogy_adapter_test.rb +473 -0
  123. data/test/cases/adapters/trilogy/trilogy_rake_test.rb +433 -0
  124. data/test/cases/aggregations_test.rb +16 -0
  125. data/test/cases/annotate_test.rb +14 -12
  126. data/test/cases/arel/attributes/attribute_test.rb +86 -47
  127. data/test/cases/arel/collectors/bind_test.rb +1 -1
  128. data/test/cases/arel/collectors/composite_test.rb +11 -1
  129. data/test/cases/arel/collectors/sql_string_test.rb +1 -1
  130. data/test/cases/arel/collectors/substitute_bind_collector_test.rb +1 -1
  131. data/test/cases/arel/delete_manager_test.rb +0 -6
  132. data/test/cases/arel/factory_methods_test.rb +45 -0
  133. data/test/cases/arel/insert_manager_test.rb +1 -7
  134. data/test/cases/arel/nodes/as_test.rb +12 -0
  135. data/test/cases/arel/nodes/ascending_test.rb +1 -1
  136. data/test/cases/arel/nodes/bin_test.rb +1 -1
  137. data/test/cases/arel/nodes/bound_sql_literal_test.rb +31 -0
  138. data/test/cases/arel/nodes/cte_test.rb +46 -0
  139. data/test/cases/arel/nodes/descending_test.rb +1 -1
  140. data/test/cases/arel/nodes/equality_test.rb +3 -3
  141. data/test/cases/arel/nodes/filter_test.rb +37 -0
  142. data/test/cases/arel/nodes/fragments_test.rb +38 -0
  143. data/test/cases/arel/nodes/homogeneous_in_test.rb +52 -0
  144. data/test/cases/arel/nodes/infix_operation_test.rb +1 -1
  145. data/test/cases/arel/nodes/node_test.rb +1 -1
  146. data/test/cases/arel/nodes/or_test.rb +2 -2
  147. data/test/cases/arel/nodes/sql_literal_test.rb +18 -1
  148. data/test/cases/arel/nodes/table_alias_test.rb +12 -0
  149. data/test/cases/arel/nodes/unary_operation_test.rb +1 -1
  150. data/test/cases/arel/nodes/update_statement_test.rb +4 -0
  151. data/test/cases/arel/nodes_test.rb +3 -2
  152. data/test/cases/arel/select_manager_test.rb +12 -12
  153. data/test/cases/arel/support/fake_record.rb +22 -17
  154. data/test/cases/arel/table_test.rb +15 -25
  155. data/test/cases/arel/update_manager_test.rb +51 -6
  156. data/test/cases/arel/visitors/dispatch_contamination_test.rb +1 -1
  157. data/test/cases/arel/visitors/dot_test.rb +177 -2
  158. data/test/cases/arel/visitors/mysql_test.rb +49 -1
  159. data/test/cases/arel/visitors/postgres_test.rb +1 -31
  160. data/test/cases/arel/visitors/sqlite_test.rb +1 -1
  161. data/test/cases/arel/visitors/to_sql_test.rb +330 -20
  162. data/test/cases/assertions/query_assertions_test.rb +136 -0
  163. data/test/cases/associations/belongs_to_associations_test.rb +502 -41
  164. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +1 -1
  165. data/test/cases/associations/cascaded_eager_loading_test.rb +26 -15
  166. data/test/cases/associations/eager_load_nested_include_test.rb +1 -1
  167. data/test/cases/associations/eager_singularization_test.rb +1 -1
  168. data/test/cases/associations/eager_test.rb +255 -93
  169. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +25 -53
  170. data/test/cases/associations/has_many_associations_test.rb +282 -72
  171. data/test/cases/associations/has_many_through_associations_test.rb +172 -45
  172. data/test/cases/associations/has_many_through_disable_joins_associations_test.rb +197 -0
  173. data/test/cases/associations/has_one_associations_test.rb +160 -29
  174. data/test/cases/associations/has_one_through_associations_test.rb +64 -15
  175. data/test/cases/associations/has_one_through_disable_joins_associations_test.rb +82 -0
  176. data/test/cases/associations/inner_join_association_test.rb +36 -6
  177. data/test/cases/associations/inverse_associations_test.rb +177 -40
  178. data/test/cases/associations/join_model_test.rb +17 -12
  179. data/test/cases/associations/left_outer_join_association_test.rb +14 -3
  180. data/test/cases/associations/nested_error_test.rb +116 -0
  181. data/test/cases/associations/nested_through_associations_test.rb +54 -19
  182. data/test/cases/associations/required_test.rb +1 -1
  183. data/test/cases/associations_test.rb +1278 -21
  184. data/test/cases/asynchronous_queries_test.rb +310 -0
  185. data/test/cases/attribute_methods/read_test.rb +6 -0
  186. data/test/cases/attribute_methods/time_zone_converter_test.rb +21 -0
  187. data/test/cases/attribute_methods_test.rb +565 -46
  188. data/test/cases/attributes_test.rb +42 -1
  189. data/test/cases/autosave_association_test.rb +645 -92
  190. data/test/cases/base_prevent_writes_test.rb +28 -159
  191. data/test/cases/base_test.rb +434 -209
  192. data/test/cases/batches_test.rb +441 -57
  193. data/test/cases/binary_test.rb +31 -0
  194. data/test/cases/bind_parameter_test.rb +107 -16
  195. data/test/cases/cache_key_test.rb +7 -7
  196. data/test/cases/calculations_test.rb +541 -110
  197. data/test/cases/callbacks_test.rb +0 -1
  198. data/test/cases/clone_test.rb +5 -4
  199. data/test/cases/coders/yaml_column_test.rb +97 -2
  200. data/test/cases/collection_cache_key_test.rb +24 -16
  201. data/test/cases/column_alias_test.rb +2 -8
  202. data/test/cases/column_definition_test.rb +12 -3
  203. data/test/cases/comment_test.rb +23 -26
  204. data/test/cases/connection_adapters/adapter_leasing_test.rb +9 -9
  205. data/test/cases/connection_adapters/connection_handler_test.rb +145 -99
  206. data/test/cases/connection_adapters/connection_handlers_multi_db_test.rb +79 -55
  207. data/test/cases/connection_adapters/connection_handlers_multi_pool_config_test.rb +17 -20
  208. data/test/cases/connection_adapters/connection_handlers_sharding_db_test.rb +146 -55
  209. data/test/cases/connection_adapters/connection_swapping_nested_test.rb +136 -23
  210. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +96 -27
  211. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +5 -5
  212. data/test/cases/connection_adapters/registration_test.rb +98 -0
  213. data/test/cases/connection_adapters/schema_cache_test.rb +288 -135
  214. data/test/cases/connection_adapters/standalone_connection_test.rb +38 -0
  215. data/test/cases/connection_adapters/statement_pool_test.rb +29 -0
  216. data/test/cases/connection_adapters/type_lookup_test.rb +12 -24
  217. data/test/cases/connection_handling_test.rb +210 -0
  218. data/test/cases/connection_management_test.rb +44 -7
  219. data/test/cases/connection_pool_test.rb +466 -99
  220. data/test/cases/core_test.rb +167 -9
  221. data/test/cases/counter_cache_test.rb +129 -2
  222. data/test/cases/custom_locking_test.rb +3 -3
  223. data/test/cases/database_configurations/hash_config_test.rb +149 -13
  224. data/test/cases/database_configurations/resolver_test.rb +14 -10
  225. data/test/cases/database_configurations/url_config_test.rb +53 -0
  226. data/test/cases/database_configurations_test.rb +86 -43
  227. data/test/cases/database_selector_test.rb +30 -8
  228. data/test/cases/database_statements_test.rb +10 -14
  229. data/test/cases/date_time_precision_test.rb +141 -11
  230. data/test/cases/date_time_test.rb +19 -1
  231. data/test/cases/defaults_test.rb +107 -41
  232. data/test/cases/delegated_type_test.rb +69 -9
  233. data/test/cases/dirty_test.rb +82 -25
  234. data/test/cases/disconnected_test.rb +10 -9
  235. data/test/cases/dup_test.rb +26 -6
  236. data/test/cases/encryption/cipher/aes256_gcm_test.rb +50 -0
  237. data/test/cases/encryption/cipher_test.rb +65 -0
  238. data/test/cases/encryption/concurrency_test.rb +27 -0
  239. data/test/cases/encryption/config_test.rb +21 -0
  240. data/test/cases/encryption/configurable_test.rb +93 -0
  241. data/test/cases/encryption/contexts_test.rb +105 -0
  242. data/test/cases/encryption/derived_secret_key_provider_test.rb +31 -0
  243. data/test/cases/encryption/deterministic_key_provider_test.rb +11 -0
  244. data/test/cases/encryption/encryptable_record_api_test.rb +175 -0
  245. data/test/cases/encryption/encryptable_record_message_pack_serialized_test.rb +42 -0
  246. data/test/cases/encryption/encryptable_record_test.rb +470 -0
  247. data/test/cases/encryption/encrypted_fixtures_test.rb +22 -0
  248. data/test/cases/encryption/encrypting_only_encryptor_test.rb +20 -0
  249. data/test/cases/encryption/encryption_schemes_test.rb +240 -0
  250. data/test/cases/encryption/encryptor_test.rb +113 -0
  251. data/test/cases/encryption/envelope_encryption_key_provider_test.rb +49 -0
  252. data/test/cases/encryption/extended_deterministic_queries_test.rb +81 -0
  253. data/test/cases/encryption/helper.rb +152 -0
  254. data/test/cases/encryption/key_generator_test.rb +55 -0
  255. data/test/cases/encryption/key_provider_test.rb +57 -0
  256. data/test/cases/encryption/key_test.rb +17 -0
  257. data/test/cases/encryption/message_pack_message_serializer_test.rb +70 -0
  258. data/test/cases/encryption/message_serializer_test.rb +82 -0
  259. data/test/cases/encryption/message_test.rb +43 -0
  260. data/test/cases/encryption/null_encryptor_test.rb +21 -0
  261. data/test/cases/encryption/properties_test.rb +69 -0
  262. data/test/cases/encryption/read_only_null_encryptor_test.rb +19 -0
  263. data/test/cases/encryption/scheme_test.rb +58 -0
  264. data/test/cases/encryption/unencrypted_attributes_test.rb +27 -0
  265. data/test/cases/encryption/uniqueness_validations_test.rb +65 -0
  266. data/test/cases/enum_test.rb +374 -72
  267. data/test/cases/errors_test.rb +7 -4
  268. data/test/cases/excluding_test.rb +116 -0
  269. data/test/cases/explain_subscriber_test.rb +6 -1
  270. data/test/cases/explain_test.rb +119 -10
  271. data/test/cases/filter_attributes_test.rb +7 -14
  272. data/test/cases/finder_respond_to_test.rb +3 -3
  273. data/test/cases/finder_test.rb +357 -72
  274. data/test/cases/fixture_set/file_test.rb +9 -0
  275. data/test/cases/fixtures_test.rb +426 -190
  276. data/test/cases/helper.rb +66 -192
  277. data/test/cases/hot_compatibility_test.rb +10 -10
  278. data/test/cases/inheritance_test.rb +51 -61
  279. data/test/cases/inherited_test.rb +40 -0
  280. data/test/cases/insert_all_test.rb +419 -9
  281. data/test/cases/instrumentation_test.rb +202 -30
  282. data/test/cases/integration_test.rb +25 -7
  283. data/test/cases/invalid_connection_test.rb +5 -5
  284. data/test/cases/invertible_migration_test.rb +108 -24
  285. data/test/cases/json_attribute_test.rb +1 -0
  286. data/test/cases/json_serialization_test.rb +5 -5
  287. data/test/cases/json_shared_test_cases.rb +5 -9
  288. data/test/cases/locking_test.rb +67 -31
  289. data/test/cases/log_subscriber_test.rb +17 -15
  290. data/test/cases/marshal_serialization_test.rb +78 -5
  291. data/test/cases/message_pack_test.rb +91 -0
  292. data/test/cases/migration/change_schema_test.rb +77 -46
  293. data/test/cases/migration/change_table_test.rb +129 -114
  294. data/test/cases/migration/check_constraint_test.rb +192 -10
  295. data/test/cases/migration/column_attributes_test.rb +4 -9
  296. data/test/cases/migration/column_positioning_test.rb +2 -2
  297. data/test/cases/migration/columns_test.rb +118 -4
  298. data/test/cases/migration/command_recorder_test.rb +181 -14
  299. data/test/cases/migration/compatibility_test.rb +883 -196
  300. data/test/cases/migration/create_join_table_test.rb +8 -1
  301. data/test/cases/migration/exclusion_constraint_test.rb +192 -0
  302. data/test/cases/migration/foreign_key_test.rb +356 -14
  303. data/test/cases/migration/helper.rb +4 -1
  304. data/test/cases/migration/index_test.rb +67 -2
  305. data/test/cases/migration/invalid_options_test.rb +129 -0
  306. data/test/cases/migration/logger_test.rb +7 -4
  307. data/test/cases/migration/pending_migrations_test.rb +103 -60
  308. data/test/cases/migration/references_foreign_key_test.rb +73 -4
  309. data/test/cases/migration/references_index_test.rb +25 -27
  310. data/test/cases/migration/references_statements_test.rb +27 -3
  311. data/test/cases/migration/rename_table_test.rb +39 -54
  312. data/test/cases/migration/schema_definitions_test.rb +109 -0
  313. data/test/cases/migration/unique_constraint_test.rb +248 -0
  314. data/test/cases/migration_test.rb +677 -220
  315. data/test/cases/migrator_test.rb +102 -75
  316. data/test/cases/multi_db_migrator_test.rb +55 -34
  317. data/test/cases/multiparameter_attributes_test.rb +26 -29
  318. data/test/cases/multiple_db_test.rb +42 -19
  319. data/test/cases/nested_attributes_test.rb +124 -6
  320. data/test/cases/nested_attributes_with_callbacks_test.rb +2 -2
  321. data/test/cases/normalized_attribute_test.rb +117 -0
  322. data/test/cases/null_relation_test.rb +35 -2
  323. data/test/cases/persistence/reload_association_cache_test.rb +20 -0
  324. data/test/cases/persistence_test.rb +629 -22
  325. data/test/cases/pooled_connections_test.rb +57 -56
  326. data/test/cases/prepared_statement_status_test.rb +8 -3
  327. data/test/cases/primary_class_test.rb +134 -0
  328. data/test/cases/primary_keys_test.rb +171 -55
  329. data/test/cases/query_cache_test.rb +558 -263
  330. data/test/cases/query_logs_test.rb +293 -0
  331. data/test/cases/quoting_test.rb +39 -72
  332. data/test/cases/readonly_test.rb +50 -12
  333. data/test/cases/reaper_test.rb +22 -6
  334. data/test/cases/reflection_test.rb +207 -9
  335. data/test/cases/relation/and_test.rb +43 -0
  336. data/test/cases/relation/delegation_test.rb +32 -5
  337. data/test/cases/relation/delete_all_test.rb +27 -6
  338. data/test/cases/relation/field_ordered_values_test.rb +128 -0
  339. data/test/cases/relation/load_async_test.rb +650 -0
  340. data/test/cases/relation/merging_test.rb +80 -109
  341. data/test/cases/relation/mutation_test.rb +12 -7
  342. data/test/cases/relation/or_test.rb +11 -8
  343. data/test/cases/relation/order_test.rb +90 -0
  344. data/test/cases/relation/predicate_builder_test.rb +21 -6
  345. data/test/cases/relation/select_test.rb +162 -3
  346. data/test/cases/relation/structural_compatibility_test.rb +38 -0
  347. data/test/cases/relation/update_all_test.rb +81 -27
  348. data/test/cases/relation/where_chain_test.rb +190 -3
  349. data/test/cases/relation/where_clause_test.rb +43 -1
  350. data/test/cases/relation/where_test.rb +95 -7
  351. data/test/cases/relation/with_test.rb +165 -0
  352. data/test/cases/relation_test.rb +42 -37
  353. data/test/cases/relations_test.rb +436 -138
  354. data/test/cases/reload_models_test.rb +18 -14
  355. data/test/cases/reserved_word_test.rb +2 -1
  356. data/test/cases/result_test.rb +14 -22
  357. data/test/cases/sanitize_test.rb +89 -27
  358. data/test/cases/schema_dumper_test.rb +535 -62
  359. data/test/cases/scoping/default_scoping_test.rb +219 -35
  360. data/test/cases/scoping/named_scoping_test.rb +25 -46
  361. data/test/cases/scoping/relation_scoping_test.rb +112 -4
  362. data/test/cases/secure_password_test.rb +108 -0
  363. data/test/cases/secure_token_test.rb +72 -0
  364. data/test/cases/serialization_test.rb +1 -1
  365. data/test/cases/serialized_attribute_test.rb +305 -60
  366. data/test/cases/shard_keys_test.rb +125 -0
  367. data/test/cases/shard_selector_test.rb +45 -0
  368. data/test/cases/signed_id_test.rb +57 -5
  369. data/test/cases/statement_cache_test.rb +31 -30
  370. data/test/cases/statement_invalid_test.rb +8 -4
  371. data/test/cases/store_test.rb +73 -9
  372. data/test/cases/strict_loading_test.rb +327 -13
  373. data/test/cases/table_metadata_test.rb +16 -0
  374. data/test/cases/tasks/database_tasks_test.rb +517 -244
  375. data/test/cases/test_case.rb +254 -60
  376. data/test/cases/test_case_test.rb +69 -0
  377. data/test/cases/test_databases_test.rb +7 -3
  378. data/test/cases/test_fixtures_test.rb +19 -40
  379. data/test/cases/time_precision_test.rb +17 -5
  380. data/test/cases/timestamp_test.rb +124 -16
  381. data/test/cases/token_for_test.rb +165 -0
  382. data/test/cases/touch_later_test.rb +43 -1
  383. data/test/cases/transaction_callbacks_test.rb +325 -8
  384. data/test/cases/transaction_instrumentation_test.rb +453 -0
  385. data/test/cases/transaction_isolation_test.rb +12 -8
  386. data/test/cases/transactions_test.rb +629 -112
  387. data/test/cases/type/date_time_test.rb +7 -1
  388. data/test/cases/type/time_test.rb +9 -0
  389. data/test/cases/type/type_map_test.rb +108 -73
  390. data/test/cases/type/unsigned_integer_test.rb +12 -0
  391. data/test/cases/type_caster/connection_test.rb +19 -0
  392. data/test/cases/type_test.rb +1 -1
  393. data/test/cases/unconnected_test.rb +7 -7
  394. data/test/cases/unsafe_raw_sql_test.rb +39 -8
  395. data/test/cases/validations/absence_validation_test.rb +1 -1
  396. data/test/cases/validations/association_validation_test.rb +25 -3
  397. data/test/cases/validations/numericality_validation_test.rb +3 -9
  398. data/test/cases/validations/presence_validation_test.rb +1 -1
  399. data/test/cases/validations/uniqueness_validation_test.rb +280 -40
  400. data/test/cases/validations_test.rb +2 -2
  401. data/test/cases/view_test.rb +33 -22
  402. data/test/cases/yaml_serialization_test.rb +23 -17
  403. data/test/config.example.yml +58 -56
  404. data/test/config.rb +1 -0
  405. data/test/fixtures/1_need_quoting.yml +2 -0
  406. data/test/fixtures/accounts.yml +5 -0
  407. data/test/fixtures/aircrafts.yml +7 -0
  408. data/test/fixtures/book_identifiers.yml +11 -0
  409. data/test/fixtures/books.yml +5 -4
  410. data/test/fixtures/cake_designers.yml +5 -0
  411. data/test/fixtures/cars.yml +6 -0
  412. data/test/fixtures/chefs.yml +5 -0
  413. data/test/fixtures/clothing_items.yml +23 -0
  414. data/test/fixtures/clubs.yml +1 -1
  415. data/test/fixtures/comments.yml +2 -1
  416. data/test/fixtures/cpk_authors.yml +8 -0
  417. data/test/fixtures/cpk_books.yml +21 -0
  418. data/test/fixtures/cpk_order_agreements.yml +13 -0
  419. data/test/fixtures/cpk_order_tags.yml +15 -0
  420. data/test/fixtures/cpk_orders.yml +11 -0
  421. data/test/fixtures/cpk_posts.yml +12 -0
  422. data/test/fixtures/cpk_reviews.yml +13 -0
  423. data/test/fixtures/cpk_tags.yml +11 -0
  424. data/test/fixtures/drink_designers.yml +5 -0
  425. data/test/fixtures/encrypted_book_that_ignores_cases.yml +4 -0
  426. data/test/fixtures/encrypted_books.yml +4 -0
  427. data/test/fixtures/fk_object_to_point_to.yml +2 -0
  428. data/test/fixtures/memberships.yml +15 -15
  429. data/test/fixtures/paragraphs.yml +5 -0
  430. data/test/fixtures/parrots.yml +4 -0
  431. data/test/fixtures/people.yml +2 -0
  432. data/test/fixtures/pirates.yml +2 -2
  433. data/test/fixtures/primary_key_error/primary_key_error.yml +6 -0
  434. data/test/fixtures/references.yml +3 -3
  435. data/test/fixtures/sharded_blog_posts.yml +14 -0
  436. data/test/fixtures/sharded_blog_posts_tags.yml +27 -0
  437. data/test/fixtures/sharded_blogs.yml +8 -0
  438. data/test/fixtures/sharded_comments.yml +22 -0
  439. data/test/fixtures/sharded_tags.yml +34 -0
  440. data/test/fixtures/sponsors.yml +2 -2
  441. data/test/fixtures/topics.yml +1 -0
  442. data/test/fixtures/treasures.yml +4 -0
  443. data/test/fixtures/virtual_columns.yml +5 -0
  444. data/test/fixtures/warehouse_things.yml +1 -1
  445. data/test/migrations/old_and_new_versions/20210716122844_add_people_description.rb +5 -0
  446. data/test/migrations/old_and_new_versions/20210716123013_add_people_number_of_legs.rb +5 -0
  447. data/test/migrations/old_and_new_versions/230_add_people_hobby.rb +5 -0
  448. data/test/migrations/old_and_new_versions/231_add_people_last_name.rb +5 -0
  449. data/test/migrations/scope/1_unscoped.rb +7 -0
  450. data/test/migrations/scope/2_mysql_only.mysql.rb +7 -0
  451. data/test/models/admin/user.rb +2 -0
  452. data/test/models/admin/user_json.rb +48 -0
  453. data/test/models/attachment.rb +7 -0
  454. data/test/models/author.rb +70 -3
  455. data/test/models/author_encrypted.rb +16 -0
  456. data/test/models/bird.rb +1 -1
  457. data/test/models/book.rb +18 -11
  458. data/test/models/book_destroy_async.rb +1 -1
  459. data/test/models/book_encrypted.rb +106 -0
  460. data/test/models/book_identifier.rb +5 -0
  461. data/test/models/branch.rb +11 -0
  462. data/test/models/bulb.rb +1 -1
  463. data/test/models/car.rb +8 -1
  464. data/test/models/cat.rb +1 -1
  465. data/test/models/category.rb +3 -1
  466. data/test/models/chat_message.rb +8 -0
  467. data/test/models/chef.rb +52 -0
  468. data/test/models/clothing_item.rb +12 -0
  469. data/test/models/club.rb +4 -1
  470. data/test/models/comment.rb +7 -4
  471. data/test/models/comment_overlapping_counter_cache.rb +15 -0
  472. data/test/models/company.rb +16 -2
  473. data/test/models/computer.rb +1 -0
  474. data/test/models/contact.rb +3 -3
  475. data/test/models/contract.rb +5 -1
  476. data/test/models/cpk/author.rb +9 -0
  477. data/test/models/cpk/book.rb +55 -0
  478. data/test/models/cpk/book_destroy_async.rb +9 -0
  479. data/test/models/cpk/car.rb +9 -0
  480. data/test/models/cpk/car_review.rb +9 -0
  481. data/test/models/cpk/chapter.rb +16 -0
  482. data/test/models/cpk/chapter_destroy_async.rb +10 -0
  483. data/test/models/cpk/comment.rb +9 -0
  484. data/test/models/cpk/order.rb +55 -0
  485. data/test/models/cpk/order_agreement.rb +10 -0
  486. data/test/models/cpk/order_tag.rb +10 -0
  487. data/test/models/cpk/post.rb +10 -0
  488. data/test/models/cpk/posts_tag.rb +10 -0
  489. data/test/models/cpk/review.rb +9 -0
  490. data/test/models/cpk/tag.rb +10 -0
  491. data/test/models/cpk.rb +15 -0
  492. data/test/models/customer.rb +3 -1
  493. data/test/models/destroy_async_parent.rb +1 -1
  494. data/test/models/developer.rb +44 -3
  495. data/test/models/discount.rb +4 -0
  496. data/test/models/drink_designer.rb +1 -0
  497. data/test/models/editor.rb +8 -0
  498. data/test/models/editorship.rb +6 -0
  499. data/test/models/entry.rb +5 -0
  500. data/test/models/essay.rb +6 -1
  501. data/test/models/essay_destroy_async.rb +1 -0
  502. data/test/models/eye.rb +87 -21
  503. data/test/models/face.rb +1 -1
  504. data/test/models/friendship.rb +3 -0
  505. data/test/models/hardback.rb +7 -0
  506. data/test/models/hotel.rb +2 -0
  507. data/test/models/human.rb +2 -2
  508. data/test/models/invoice.rb +2 -1
  509. data/test/models/invokes_an_undefined_method.rb +5 -0
  510. data/test/models/line_item.rb +6 -0
  511. data/test/models/member.rb +9 -4
  512. data/test/models/membership.rb +2 -2
  513. data/test/models/message.rb +2 -1
  514. data/test/models/need_quoting.rb +5 -0
  515. data/test/models/paragraph.rb +5 -0
  516. data/test/models/parrot.rb +6 -3
  517. data/test/models/person.rb +7 -4
  518. data/test/models/pirate.rb +4 -1
  519. data/test/models/pk_autopopulated_by_a_trigger_record.rb +5 -0
  520. data/test/models/post.rb +65 -2
  521. data/test/models/post_encrypted.rb +15 -0
  522. data/test/models/post_with_prefetched_pk.rb +15 -0
  523. data/test/models/project.rb +1 -0
  524. data/test/models/publication.rb +16 -0
  525. data/test/models/raises_argument_error.rb +5 -0
  526. data/test/models/raises_no_method_error.rb +5 -0
  527. data/test/models/recipient.rb +5 -0
  528. data/test/models/reference.rb +1 -1
  529. data/test/models/reply.rb +1 -1
  530. data/test/models/room.rb +3 -0
  531. data/test/models/sharded/blog.rb +12 -0
  532. data/test/models/sharded/blog_post.rb +17 -0
  533. data/test/models/sharded/blog_post_destroy_async.rb +14 -0
  534. data/test/models/sharded/blog_post_tag.rb +11 -0
  535. data/test/models/sharded/blog_post_with_revision.rb +11 -0
  536. data/test/models/sharded/comment.rb +12 -0
  537. data/test/models/sharded/comment_destroy_async.rb +12 -0
  538. data/test/models/sharded/tag.rb +11 -0
  539. data/test/models/sharded.rb +8 -0
  540. data/test/models/ship.rb +1 -1
  541. data/test/models/shipping_line.rb +11 -0
  542. data/test/models/subscriber.rb +1 -0
  543. data/test/models/subscription.rb +3 -1
  544. data/test/models/too_long_table_name.rb +5 -0
  545. data/test/models/topic.rb +3 -1
  546. data/test/models/traffic_light.rb +2 -2
  547. data/test/models/traffic_light_encrypted.rb +21 -0
  548. data/test/models/translation.rb +9 -0
  549. data/test/models/treasure.rb +1 -1
  550. data/test/models/tyre.rb +1 -1
  551. data/test/models/user.rb +16 -0
  552. data/test/models/user_with_invalid_relation.rb +28 -0
  553. data/test/models/uuid_comment.rb +5 -0
  554. data/test/models/uuid_entry.rb +5 -0
  555. data/test/models/uuid_message.rb +5 -0
  556. data/test/models/zine.rb +2 -1
  557. data/test/schema/mysql2_specific_schema.rb +26 -12
  558. data/test/schema/postgresql_specific_schema.rb +121 -13
  559. data/test/schema/schema.rb +361 -103
  560. data/test/schema/sqlite_specific_schema.rb +17 -6
  561. data/test/schema/trilogy_specific_schema.rb +96 -0
  562. data/test/support/adapter_helper.rb +104 -0
  563. data/test/support/async_helper.rb +15 -0
  564. data/test/support/config.rb +1 -1
  565. data/test/support/connection.rb +14 -2
  566. data/test/support/ddl_helper.rb +1 -1
  567. data/test/support/fake_adapter.rb +42 -0
  568. data/test/support/load_schema_helper.rb +22 -0
  569. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_1_topic.dump +0 -0
  570. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_1_topic_associations.dump +0 -0
  571. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_7_1_topic.dump +0 -0
  572. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_7_1_topic_associations.dump +0 -0
  573. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_1_topic.dump +0 -0
  574. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_1_topic_associations.dump +0 -0
  575. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_7_1_topic.dump +0 -0
  576. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_7_1_topic_associations.dump +0 -0
  577. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_1_topic.dump +0 -0
  578. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_1_topic_associations.dump +0 -0
  579. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_7_1_topic.dump +0 -0
  580. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_7_1_topic_associations.dump +0 -0
  581. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_1_topic.dump +0 -0
  582. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_1_topic_associations.dump +0 -0
  583. data/test/support/marshal_compatibility_fixtures/SQLite/rails_7_1_topic.dump +0 -0
  584. data/test/support/marshal_compatibility_fixtures/SQLite/rails_7_1_topic_associations.dump +0 -0
  585. data/test/support/marshal_compatibility_fixtures/Trilogy/rails_6_1_topic.dump +0 -0
  586. data/test/support/marshal_compatibility_fixtures/Trilogy/rails_6_1_topic_associations.dump +0 -0
  587. data/test/support/marshal_compatibility_fixtures/Trilogy/rails_7_1_topic.dump +0 -0
  588. data/test/support/marshal_compatibility_fixtures/Trilogy/rails_7_1_topic_associations.dump +0 -0
  589. data/test/support/schema_dumping_helper.rb +15 -9
  590. data/test/support/tools.rb +37 -0
  591. data/test/support/yaml_compatibility_fixtures/rails_4_1_no_symbol.yml +22 -0
  592. metadata +247 -15
@@ -4,9 +4,18 @@ require "cases/helper"
4
4
  require "models/person"
5
5
  require "models/traffic_light"
6
6
  require "models/post"
7
- require "models/binary_field"
8
7
 
9
8
  class SerializedAttributeTest < ActiveRecord::TestCase
9
+ def setup
10
+ ActiveRecord.use_yaml_unsafe_load = true
11
+ @yaml_column_permitted_classes_default = ActiveRecord.yaml_column_permitted_classes
12
+ end
13
+
14
+ def teardown
15
+ Topic.serialize("content")
16
+ ActiveRecord.yaml_column_permitted_classes = @yaml_column_permitted_classes_default
17
+ end
18
+
10
19
  fixtures :topics, :posts
11
20
 
12
21
  MyObject = Struct.new :attribute1, :attribute2
@@ -16,11 +25,11 @@ class SerializedAttributeTest < ActiveRecord::TestCase
16
25
  end
17
26
 
18
27
  class ImportantTopic < Topic
19
- serialize :important, Hash
28
+ serialize :important, type: Hash
20
29
  end
21
30
 
22
- teardown do
23
- Topic.serialize("content")
31
+ class ClassifiedTopic < Topic
32
+ serialize :important, type: Class
24
33
  end
25
34
 
26
35
  def test_serialize_does_not_eagerly_load_columns
@@ -31,7 +40,7 @@ class SerializedAttributeTest < ActiveRecord::TestCase
31
40
  end
32
41
 
33
42
  def test_serialized_attribute
34
- Topic.serialize("content", MyObject)
43
+ Topic.serialize("content", type: MyObject)
35
44
 
36
45
  myobj = MyObject.new("value1", "value2")
37
46
  topic = Topic.create("content" => myobj)
@@ -41,10 +50,25 @@ class SerializedAttributeTest < ActiveRecord::TestCase
41
50
  assert_equal(myobj, topic.content)
42
51
  end
43
52
 
53
+ def test_serialized_attribute_on_alias_attribute
54
+ klass = Class.new(ActiveRecord::Base) do
55
+ self.table_name = Topic.table_name
56
+ alias_attribute :object, :content
57
+ serialize :object, type: MyObject
58
+ end
59
+
60
+ myobj = MyObject.new("value1", "value2")
61
+ topic = klass.create!(object: myobj)
62
+ assert_equal(myobj, topic.object)
63
+
64
+ topic.reload
65
+ assert_equal(myobj, topic.object)
66
+ end
67
+
44
68
  def test_serialized_attribute_with_default
45
69
  klass = Class.new(ActiveRecord::Base) do
46
70
  self.table_name = Topic.table_name
47
- serialize(:content, Hash, default: { key: "value" })
71
+ serialize(:content, type: Hash, default: { key: "value" })
48
72
  end
49
73
 
50
74
  t = klass.new
@@ -55,7 +79,7 @@ class SerializedAttributeTest < ActiveRecord::TestCase
55
79
  klass = Class.new(ActiveRecord::Base) do
56
80
  self.table_name = Topic.table_name
57
81
  attribute :content, default: { key: "value" }
58
- serialize :content, Hash
82
+ serialize :content, type: Hash
59
83
  end
60
84
 
61
85
  t = klass.new
@@ -63,7 +87,7 @@ class SerializedAttributeTest < ActiveRecord::TestCase
63
87
  end
64
88
 
65
89
  def test_serialized_attribute_in_base_class
66
- Topic.serialize("content", Hash)
90
+ Topic.serialize("content", type: Hash)
67
91
 
68
92
  hash = { "content1" => "value1", "content2" => "value2" }
69
93
  important_topic = ImportantTopic.create("content" => hash)
@@ -74,7 +98,7 @@ class SerializedAttributeTest < ActiveRecord::TestCase
74
98
  end
75
99
 
76
100
  def test_serialized_attributes_from_database_on_subclass
77
- Topic.serialize :content, Hash
101
+ Topic.serialize :content, type: Hash
78
102
 
79
103
  t = ImportantTopic.new(content: { foo: :bar })
80
104
  assert_equal({ foo: :bar }, t.content)
@@ -84,7 +108,7 @@ class SerializedAttributeTest < ActiveRecord::TestCase
84
108
  end
85
109
 
86
110
  def test_serialized_attribute_calling_dup_method
87
- Topic.serialize :content, JSON
111
+ Topic.serialize :content, coder: JSON
88
112
 
89
113
  orig = Topic.new(content: { foo: :bar })
90
114
  clone = orig.dup
@@ -92,7 +116,7 @@ class SerializedAttributeTest < ActiveRecord::TestCase
92
116
  end
93
117
 
94
118
  def test_serialized_json_attribute_returns_unserialized_value
95
- Topic.serialize :content, JSON
119
+ Topic.serialize :content, coder: JSON
96
120
  my_post = posts(:welcome)
97
121
 
98
122
  t = Topic.new(content: my_post)
@@ -105,21 +129,21 @@ class SerializedAttributeTest < ActiveRecord::TestCase
105
129
  end
106
130
 
107
131
  def test_json_read_legacy_null
108
- Topic.serialize :content, JSON
132
+ Topic.serialize :content, coder: JSON
109
133
 
110
134
  # Force a row to have a JSON "null" instead of a database NULL (this is how
111
135
  # null values are saved on 4.1 and before)
112
- id = Topic.connection.insert "INSERT INTO topics (content) VALUES('null')"
136
+ id = Topic.lease_connection.insert "INSERT INTO topics (content) VALUES('null')"
113
137
  t = Topic.find(id)
114
138
 
115
139
  assert_nil t.content
116
140
  end
117
141
 
118
142
  def test_json_read_db_null
119
- Topic.serialize :content, JSON
143
+ Topic.serialize :content, coder: JSON
120
144
 
121
145
  # Force a row to have a database NULL instead of a JSON "null"
122
- id = Topic.connection.insert "INSERT INTO topics (content) VALUES(NULL)"
146
+ id = Topic.lease_connection.insert "INSERT INTO topics (content) VALUES(NULL)"
123
147
  t = Topic.find(id)
124
148
 
125
149
  assert_nil t.content
@@ -147,6 +171,23 @@ class SerializedAttributeTest < ActiveRecord::TestCase
147
171
  assert_equal(myobj, topic.content)
148
172
  end
149
173
 
174
+ def test_serialized_class_attribute
175
+ ActiveRecord.yaml_column_permitted_classes += [Class]
176
+
177
+ topic = ClassifiedTopic.create(important: Symbol).reload
178
+ assert_equal(Symbol, topic.important)
179
+ assert_not_empty ClassifiedTopic.where(important: Symbol)
180
+ end
181
+
182
+ def test_serialized_class_does_not_become_frozen
183
+ ActiveRecord.yaml_column_permitted_classes += [Class]
184
+
185
+ assert_not_predicate Symbol, :frozen?
186
+ ClassifiedTopic.create(important: Symbol)
187
+ assert_not_empty ClassifiedTopic.where(important: Symbol)
188
+ assert_not_predicate Symbol, :frozen?
189
+ end
190
+
150
191
  def test_nil_serialized_attribute_without_class_constraint
151
192
  topic = Topic.new
152
193
  assert_nil topic.content
@@ -158,13 +199,13 @@ class SerializedAttributeTest < ActiveRecord::TestCase
158
199
  end
159
200
 
160
201
  def test_nil_not_serialized_with_class_constraint
161
- Topic.serialize :content, Hash
202
+ Topic.serialize :content, type: Hash
162
203
  assert Topic.new(content: nil).save
163
204
  assert_equal 1, Topic.where(content: nil).count
164
205
  end
165
206
 
166
207
  def test_serialized_attribute_should_raise_exception_on_assignment_with_wrong_type
167
- Topic.serialize(:content, Hash)
208
+ Topic.serialize(:content, type: Hash)
168
209
  assert_raise(ActiveRecord::SerializationTypeMismatch) do
169
210
  Topic.new(content: "string")
170
211
  end
@@ -174,13 +215,13 @@ class SerializedAttributeTest < ActiveRecord::TestCase
174
215
  myobj = MyObject.new("value1", "value2")
175
216
  topic = Topic.new(content: myobj)
176
217
  assert topic.save
177
- Topic.serialize(:content, Hash)
218
+ Topic.serialize(:content, type: Hash)
178
219
  assert_raise(ActiveRecord::SerializationTypeMismatch) { Topic.find(topic.id).content }
179
220
  end
180
221
 
181
222
  def test_serialized_attribute_with_class_constraint
182
223
  settings = { "color" => "blue" }
183
- Topic.serialize(:content, Hash)
224
+ Topic.serialize(:content, type: Hash)
184
225
  topic = Topic.new(content: settings)
185
226
  assert topic.save
186
227
  assert_equal(settings, Topic.find(topic.id).content)
@@ -188,27 +229,27 @@ class SerializedAttributeTest < ActiveRecord::TestCase
188
229
 
189
230
  def test_where_by_serialized_attribute_with_array
190
231
  settings = [ "color" => "green" ]
191
- Topic.serialize(:content, Array)
232
+ Topic.serialize(:content, type: Array)
192
233
  topic = Topic.create!(content: settings)
193
234
  assert_equal topic, Topic.where(content: settings).take
194
235
  end
195
236
 
196
237
  def test_where_by_serialized_attribute_with_hash
197
238
  settings = { "color" => "green" }
198
- Topic.serialize(:content, Hash)
239
+ Topic.serialize(:content, type: Hash)
199
240
  topic = Topic.create!(content: settings)
200
241
  assert_equal topic, Topic.where(content: settings).take
201
242
  end
202
243
 
203
244
  def test_where_by_serialized_attribute_with_hash_in_array
204
245
  settings = { "color" => "green" }
205
- Topic.serialize(:content, Hash)
246
+ Topic.serialize(:content, type: Hash)
206
247
  topic = Topic.create!(content: settings)
207
- assert_equal topic, Topic.where(content: [settings]).take
248
+ assert_equal topic, Topic.where(content: [settings, { "herring" => "red" }]).take
208
249
  end
209
250
 
210
251
  def test_serialized_default_class
211
- Topic.serialize(:content, Hash)
252
+ Topic.serialize(:content, type: Hash)
212
253
  topic = Topic.new
213
254
  assert_equal Hash, topic.content.class
214
255
  assert_equal Hash, topic.read_attribute(:content).class
@@ -249,7 +290,7 @@ class SerializedAttributeTest < ActiveRecord::TestCase
249
290
  end
250
291
  end
251
292
 
252
- Topic.serialize(:content, some_class)
293
+ Topic.serialize(:content, coder: some_class)
253
294
  topic = Topic.new(content: some_class.new("my value"))
254
295
  topic.save!
255
296
  topic.reload
@@ -259,7 +300,7 @@ class SerializedAttributeTest < ActiveRecord::TestCase
259
300
 
260
301
  def test_serialize_attribute_via_select_method_when_time_zone_available
261
302
  with_timezone_config aware_attributes: true do
262
- Topic.serialize(:content, MyObject)
303
+ Topic.serialize(:content, type: MyObject)
263
304
 
264
305
  myobj = MyObject.new("value1", "value2")
265
306
  topic = Topic.create(content: myobj)
@@ -284,16 +325,16 @@ class SerializedAttributeTest < ActiveRecord::TestCase
284
325
  end
285
326
 
286
327
  def test_unexpected_serialized_type
287
- Topic.serialize :content, Hash
328
+ Topic.serialize :content, type: Hash
288
329
  topic = Topic.create!(content: { zomg: true })
289
330
 
290
- Topic.serialize :content, Array
331
+ Topic.serialize :content, type: Array
291
332
 
292
333
  topic.reload
293
334
  error = assert_raise(ActiveRecord::SerializationTypeMismatch) do
294
335
  topic.content
295
336
  end
296
- expected = "can't load `content`: was supposed to be a Array, but was a Hash. -- {:zomg=>true}"
337
+ expected = "can't load `content`: was supposed to be a Array, but was a Hash. -- #{{ zomg: true }}"
297
338
  assert_equal expected, error.to_s
298
339
  end
299
340
 
@@ -316,7 +357,7 @@ class SerializedAttributeTest < ActiveRecord::TestCase
316
357
  end
317
358
 
318
359
  def test_nil_is_not_changed_when_serialized_with_a_class
319
- Topic.serialize(:content, Array)
360
+ Topic.serialize(:content, type: Array)
320
361
 
321
362
  topic = Topic.new(content: nil)
322
363
 
@@ -325,12 +366,12 @@ class SerializedAttributeTest < ActiveRecord::TestCase
325
366
 
326
367
  def test_classes_without_no_arg_constructors_are_not_supported
327
368
  assert_raises(ArgumentError) do
328
- Topic.serialize(:content, Regexp)
369
+ Topic.serialize(:content, type: Regexp)
329
370
  end
330
371
  end
331
372
 
332
373
  def test_newly_emptied_serialized_hash_is_changed
333
- Topic.serialize(:content, Hash)
374
+ Topic.serialize(:content, type: Hash)
334
375
  topic = Topic.create(content: { "things" => "stuff" })
335
376
  topic.content.delete("things")
336
377
  topic.save!
@@ -339,36 +380,37 @@ class SerializedAttributeTest < ActiveRecord::TestCase
339
380
  assert_equal({}, topic.content)
340
381
  end
341
382
 
342
- if current_adapter?(:Mysql2Adapter)
343
- def test_is_not_changed_when_stored_in_mysql_blob
344
- value = %w(Fée)
345
- model = BinaryField.create!(normal_blob: value, normal_text: value)
346
- model.reload
383
+ def test_is_not_changed_when_stored_blob
384
+ Topic.serialize(:binary_content, type: Array)
385
+ Topic.serialize(:content, type: Array)
347
386
 
348
- model.normal_text = value
349
- assert_not_predicate model, :normal_text_changed?
387
+ value = %w(Fée)
388
+ model = Topic.create!(binary_content: value, content: value)
389
+ model.reload
350
390
 
351
- model.normal_blob = value
352
- assert_not_predicate model, :normal_blob_changed?
353
- end
391
+ model.binary_content = value
392
+ assert_not_predicate model, :binary_content_changed?
354
393
 
355
- class FrozenBinaryField < BinaryField
356
- class FrozenCoder < ActiveRecord::Coders::YAMLColumn
357
- def dump(obj)
358
- super&.freeze
359
- end
360
- end
361
- serialize :normal_blob, FrozenCoder.new(:normal_blob, Array)
394
+ model.content = value
395
+ assert_not_predicate model, :content_changed?
396
+ end
397
+
398
+ class FrozenCoder < ActiveRecord::Coders::YAMLColumn
399
+ def dump(obj)
400
+ super&.freeze
362
401
  end
402
+ end
363
403
 
364
- def test_is_not_changed_when_stored_in_mysql_blob_frozen_payload
365
- value = %w(Fée)
366
- model = FrozenBinaryField.create!(normal_blob: value, normal_text: value)
367
- model.reload
404
+ def test_is_not_changed_when_stored_in_blob_frozen_payload
405
+ Topic.serialize(:binary_content, coder: FrozenCoder.new(:binary_content, Array))
406
+ Topic.serialize(:content, coder: FrozenCoder.new(:content, Array))
368
407
 
369
- model.normal_blob = value
370
- assert_not_predicate model, :normal_blob_changed?
371
- end
408
+ value = %w(Fée)
409
+ model = Topic.create!(binary_content: value, content: value)
410
+ model.reload
411
+
412
+ model.content = value
413
+ assert_not_predicate model, :content_changed?
372
414
  end
373
415
 
374
416
  def test_values_cast_from_nil_are_persisted_as_nil
@@ -377,21 +419,101 @@ class SerializedAttributeTest < ActiveRecord::TestCase
377
419
  #
378
420
  # model.attribute = value
379
421
  # assert_equal model.attribute, model.tap(&:save).reload.attribute
380
- Topic.serialize(:content, Hash)
422
+ Topic.serialize(:content, type: Hash)
381
423
  topic = Topic.create!(content: {})
382
424
  topic2 = Topic.create!(content: nil)
383
425
 
384
426
  assert_equal [topic, topic2], Topic.where(content: nil).sort_by(&:id)
385
427
  end
386
428
 
429
+ def test_serialized_attribute_can_be_defined_in_abstract_classes
430
+ klass = Class.new(ActiveRecord::Base) do
431
+ self.abstract_class = true
432
+ self.table_name = nil
433
+ serialize(:content, type: Hash)
434
+ end
435
+
436
+ subclass = Class.new(klass) do
437
+ self.table_name = "topics"
438
+ end
439
+
440
+ subclass.define_attribute_methods
441
+
442
+ topic = subclass.create!(content: { foo: 1 })
443
+ assert_equal [topic], subclass.where(content: { foo: 1 }).to_a
444
+ end
445
+
387
446
  def test_nil_is_always_persisted_as_null
388
- Topic.serialize(:content, Hash)
447
+ Topic.serialize(:content, type: Hash)
389
448
 
390
449
  topic = Topic.create!(content: { foo: "bar" })
391
450
  topic.update_attribute :content, nil
392
451
  assert_equal [topic], Topic.where(content: nil)
393
452
  end
394
453
 
454
+ class EncryptedType < ActiveRecord::Type::Text
455
+ include ActiveModel::Type::Helpers::Mutable
456
+
457
+ attr_reader :subtype, :encryptor
458
+
459
+ def initialize(subtype: ActiveModel::Type::String.new)
460
+ super()
461
+
462
+ @subtype = subtype
463
+ @encryptor = ActiveSupport::MessageEncryptor.new("abcd" * 8)
464
+ end
465
+
466
+ def serialize(value)
467
+ subtype.serialize(value).yield_self do |cleartext|
468
+ encryptor.encrypt_and_sign(cleartext) unless cleartext.nil?
469
+ end
470
+ end
471
+
472
+ def deserialize(ciphertext)
473
+ encryptor.decrypt_and_verify(ciphertext)
474
+ .yield_self { |cleartext| subtype.deserialize(cleartext) } unless ciphertext.nil?
475
+ end
476
+
477
+ def changed_in_place?(old, new)
478
+ if old.nil?
479
+ !new.nil?
480
+ else
481
+ deserialize(old) != new
482
+ end
483
+ end
484
+ end
485
+
486
+ def test_decorated_type_with_type_for_attribute
487
+ old_registry = ActiveRecord::Type.registry
488
+ ActiveRecord::Type.registry = ActiveRecord::Type.registry.dup
489
+ ActiveRecord::Type.register :encrypted, EncryptedType
490
+
491
+ klass = Class.new(ActiveRecord::Base) do
492
+ self.table_name = Topic.table_name
493
+ store :content, coder: ActiveRecord::Coders::JSON
494
+ attribute :content, :encrypted, subtype: type_for_attribute(:content)
495
+ end
496
+
497
+ topic = klass.create!(content: { trial: true })
498
+
499
+ assert_equal({ "trial" => true }, topic.content)
500
+ ensure
501
+ ActiveRecord::Type.registry = old_registry
502
+ end
503
+
504
+ def test_decorated_type_with_decorator_block
505
+ klass = Class.new(ActiveRecord::Base) do
506
+ self.table_name = Topic.table_name
507
+ store :content, coder: ActiveRecord::Coders::JSON
508
+ decorate_attributes([:content]) do |name, type|
509
+ EncryptedType.new(subtype: type)
510
+ end
511
+ end
512
+
513
+ topic = klass.create!(content: { trial: true })
514
+ assert_equal({ "trial" => true }, topic.content)
515
+ end
516
+
395
517
  def test_mutation_detection_does_not_double_serialize
396
518
  coder = Object.new
397
519
  def coder.dump(value)
@@ -417,7 +539,7 @@ class SerializedAttributeTest < ActiveRecord::TestCase
417
539
  end.new
418
540
  model = Class.new(Topic) do
419
541
  attribute :foo, type
420
- serialize :foo, coder
542
+ serialize :foo, coder: coder
421
543
  end
422
544
 
423
545
  topic = model.create!(foo: "bar")
@@ -431,7 +553,7 @@ class SerializedAttributeTest < ActiveRecord::TestCase
431
553
  topic = model.create!
432
554
  topic.update group: "1"
433
555
 
434
- model.serialize :group, JSON
556
+ model.serialize :group, coder: JSON
435
557
  model.reset_column_information
436
558
 
437
559
  # This isn't strictly necessary for the test, but a little bit of
@@ -453,3 +575,126 @@ class SerializedAttributeTest < ActiveRecord::TestCase
453
575
  assert_equal [1] * threads.size, threads.map(&:value)
454
576
  end
455
577
  end
578
+
579
+ class SerializedAttributeTestWithYamlSafeLoad < SerializedAttributeTest
580
+ def setup
581
+ @use_yaml_unsafe_load = ActiveRecord.use_yaml_unsafe_load
582
+ @yaml_column_permitted_classes_default = ActiveRecord.yaml_column_permitted_classes
583
+ ActiveRecord.use_yaml_unsafe_load = false
584
+ end
585
+
586
+ def teardown
587
+ Topic.serialize("content")
588
+ ActiveRecord.yaml_column_permitted_classes = @yaml_column_permitted_classes_default
589
+ ActiveRecord.use_yaml_unsafe_load = @use_yaml_unsafe_load
590
+ end
591
+
592
+ def test_serialized_attribute
593
+ Topic.serialize("content", type: String)
594
+
595
+ myobj = String.new("value1")
596
+ topic = Topic.create("content" => myobj)
597
+ assert_equal(myobj, topic.content)
598
+
599
+ topic.reload
600
+ assert_equal(myobj, topic.content)
601
+ end
602
+
603
+ def test_serialized_attribute_on_custom_attribute_with_default
604
+ klass = Class.new(ActiveRecord::Base) do
605
+ self.table_name = Topic.table_name
606
+ attribute :content, default: { "key" => "value" }
607
+ serialize :content, type: Hash
608
+ end
609
+
610
+ t = klass.new
611
+ assert_equal({ "key" => "value" }, t.content)
612
+ end
613
+
614
+ def test_nil_is_always_persisted_as_null
615
+ Topic.serialize(:content, type: Hash)
616
+
617
+ topic = Topic.create!(content: { "foo" => "bar" })
618
+ topic.update_attribute :content, nil
619
+ assert_equal [topic], Topic.where(content: nil)
620
+ end
621
+
622
+ def test_serialized_attribute_with_default
623
+ klass = Class.new(ActiveRecord::Base) do
624
+ self.table_name = Topic.table_name
625
+ serialize(:content, type: Hash, default: { "key" => "value" })
626
+ end
627
+
628
+ t = klass.new
629
+ assert_equal({ "key" => "value" }, t.content)
630
+ end
631
+
632
+ def test_serialized_attributes_from_database_on_subclass
633
+ Topic.serialize :content, type: Hash
634
+
635
+ t = ImportantTopic.new(content: { "foo" => "bar" })
636
+ assert_equal({ "foo" => "bar" }, t.content)
637
+ t.save!
638
+ t = ImportantTopic.last
639
+ assert_equal({ "foo" => "bar" }, t.content)
640
+ end
641
+
642
+ def test_serialized_attribute_on_alias_attribute
643
+ klass = Class.new(ActiveRecord::Base) do
644
+ self.table_name = Topic.table_name
645
+ alias_attribute :object, :content
646
+ serialize :object, type: Hash
647
+ end
648
+
649
+ myobj = { "somevalue" => "thevalue" }
650
+ topic = klass.create!(object: myobj)
651
+ assert_equal(myobj, topic.object)
652
+
653
+ topic.reload
654
+ assert_equal(myobj, topic.object)
655
+ end
656
+
657
+ def test_unexpected_serialized_type
658
+ Topic.serialize :content, type: Hash
659
+ topic = Topic.create!(content: { "zomg" => true })
660
+
661
+ Topic.serialize :content, type: Array
662
+
663
+ topic.reload
664
+ error = assert_raise(ActiveRecord::SerializationTypeMismatch) do
665
+ topic.content
666
+ end
667
+ expected = "can't load `content`: was supposed to be a Array, but was a Hash. -- #{{ "zomg" => true }}"
668
+ assert_equal expected, error.to_s
669
+ end
670
+
671
+ def test_serialize_attribute_via_select_method_when_time_zone_available
672
+ with_timezone_config aware_attributes: true do
673
+ Topic.serialize(:content, type: Hash)
674
+
675
+ myobj = { "somevalue" => "thevalue" }
676
+ topic = Topic.create(content: myobj)
677
+
678
+ assert_equal(myobj, Topic.select(:content).find(topic.id).content)
679
+ assert_raise(ActiveModel::MissingAttributeError) { Topic.select(:id).find(topic.id).content }
680
+ end
681
+ end
682
+
683
+ def test_should_raise_exception_on_serialized_attribute_with_type_mismatch
684
+ myobj = { "somevalue" => "thevalue" }
685
+ topic = Topic.new(content: myobj)
686
+ assert topic.save
687
+ Topic.serialize(:content, type: String)
688
+ assert_raise(ActiveRecord::SerializationTypeMismatch) { Topic.find(topic.id).content }
689
+ end
690
+
691
+ def test_serialized_time_attribute
692
+ skip "Time is a DisallowedClass in Psych safe_load()."
693
+ end
694
+
695
+ def test_supports_permitted_classes_for_default_column_serializer
696
+ Topic.serialize(:content, yaml: { permitted_classes: [Time] })
697
+ topic = Topic.new(content: Time.now)
698
+ assert topic.save
699
+ end
700
+ end