ibm_db 5.2.0-x86-mingw32 → 5.4.0-x86-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (625) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +9 -0
  3. data/LICENSE +55 -18
  4. data/README +1 -1
  5. data/debug.log +1 -0
  6. data/ext/Makefile +28 -24
  7. data/ext/ibm_db.c +66 -65
  8. data/ext/ibm_db.o +0 -0
  9. data/ext/ibm_db.so +0 -0
  10. data/ext/mkmf.log +26 -24
  11. data/ext/ruby_ibm_db_cli.c +1 -0
  12. data/ext/ruby_ibm_db_cli.o +0 -0
  13. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +1520 -1282
  14. data/lib/ibm_db.so +1 -0
  15. data/lib/mswin32/ibm_db.rb +3 -1
  16. data/lib/mswin32/rb3x/i386/ruby30/ibm_db.so +0 -0
  17. data/lib/mswin32/rb3x/i386/ruby31/ibm_db.so +0 -0
  18. data/test/active_record/connection_adapters/fake_adapter.rb +5 -2
  19. data/test/activejob/destroy_association_async_test.rb +305 -0
  20. data/test/activejob/destroy_async_job_not_present_test.rb +31 -0
  21. data/test/activejob/helper.rb +15 -0
  22. data/test/assets/schema_dump_5_1.yml +345 -0
  23. data/test/cases/adapter_prevent_writes_test.rb +334 -0
  24. data/test/cases/adapter_test.rb +432 -218
  25. data/test/cases/adapters/mysql2/active_schema_test.rb +85 -75
  26. data/test/cases/adapters/mysql2/auto_increment_test.rb +34 -0
  27. data/test/cases/adapters/mysql2/bind_parameter_test.rb +5 -3
  28. data/test/cases/adapters/mysql2/boolean_test.rb +6 -4
  29. data/test/cases/adapters/mysql2/case_sensitivity_test.rb +26 -24
  30. data/test/cases/adapters/mysql2/charset_collation_test.rb +20 -17
  31. data/test/cases/adapters/mysql2/connection_test.rb +48 -50
  32. data/test/cases/adapters/mysql2/count_deleted_rows_with_lock_test.rb +28 -0
  33. data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +23 -19
  34. data/test/cases/adapters/mysql2/enum_test.rb +32 -11
  35. data/test/cases/adapters/mysql2/explain_test.rb +13 -11
  36. data/test/cases/adapters/mysql2/json_test.rb +17 -188
  37. data/test/cases/adapters/mysql2/mysql2_adapter_prevent_writes_test.rb +208 -0
  38. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +183 -28
  39. data/test/cases/adapters/mysql2/nested_deadlock_test.rb +75 -0
  40. data/test/cases/adapters/mysql2/optimizer_hints_test.rb +69 -0
  41. data/test/cases/adapters/mysql2/schema_migrations_test.rb +26 -21
  42. data/test/cases/adapters/mysql2/schema_test.rb +24 -22
  43. data/test/cases/adapters/mysql2/set_test.rb +32 -0
  44. data/test/cases/adapters/mysql2/sp_test.rb +10 -8
  45. data/test/cases/adapters/mysql2/sql_types_test.rb +8 -6
  46. data/test/cases/adapters/mysql2/table_options_test.rb +93 -10
  47. data/test/cases/adapters/mysql2/transaction_test.rb +151 -0
  48. data/test/cases/adapters/mysql2/unsigned_type_test.rb +11 -9
  49. data/test/cases/adapters/mysql2/virtual_column_test.rb +66 -0
  50. data/test/cases/adapters/postgresql/active_schema_test.rb +40 -25
  51. data/test/cases/adapters/postgresql/array_test.rb +118 -63
  52. data/test/cases/adapters/postgresql/bit_string_test.rb +12 -10
  53. data/test/cases/adapters/postgresql/bytea_test.rb +26 -25
  54. data/test/cases/adapters/postgresql/case_insensitive_test.rb +10 -9
  55. data/test/cases/adapters/postgresql/change_schema_test.rb +7 -5
  56. data/test/cases/adapters/postgresql/cidr_test.rb +2 -0
  57. data/test/cases/adapters/postgresql/citext_test.rb +58 -58
  58. data/test/cases/adapters/postgresql/collation_test.rb +17 -15
  59. data/test/cases/adapters/postgresql/composite_test.rb +25 -23
  60. data/test/cases/adapters/postgresql/connection_test.rb +73 -85
  61. data/test/cases/adapters/postgresql/create_unlogged_tables_test.rb +74 -0
  62. data/test/cases/adapters/postgresql/datatype_test.rb +19 -22
  63. data/test/cases/adapters/postgresql/date_test.rb +42 -0
  64. data/test/cases/adapters/postgresql/domain_test.rb +9 -7
  65. data/test/cases/adapters/postgresql/enum_test.rb +12 -10
  66. data/test/cases/adapters/postgresql/explain_test.rb +10 -8
  67. data/test/cases/adapters/postgresql/extension_migration_test.rb +13 -12
  68. data/test/cases/adapters/postgresql/foreign_table_test.rb +109 -0
  69. data/test/cases/adapters/postgresql/full_text_test.rb +8 -6
  70. data/test/cases/adapters/postgresql/geometric_test.rb +57 -63
  71. data/test/cases/adapters/postgresql/hstore_test.rb +288 -280
  72. data/test/cases/adapters/postgresql/infinity_test.rb +54 -15
  73. data/test/cases/adapters/postgresql/integer_test.rb +2 -0
  74. data/test/cases/adapters/postgresql/interval_test.rb +99 -0
  75. data/test/cases/adapters/postgresql/json_test.rb +16 -201
  76. data/test/cases/adapters/postgresql/ltree_test.rb +14 -16
  77. data/test/cases/adapters/postgresql/money_test.rb +47 -16
  78. data/test/cases/adapters/postgresql/network_test.rb +36 -28
  79. data/test/cases/adapters/postgresql/numbers_test.rb +7 -5
  80. data/test/cases/adapters/postgresql/optimizer_hints_test.rb +71 -0
  81. data/test/cases/adapters/postgresql/partitions_test.rb +22 -0
  82. data/test/cases/adapters/postgresql/postgresql_adapter_prevent_writes_test.rb +205 -0
  83. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +178 -136
  84. data/test/cases/adapters/postgresql/prepared_statements_disabled_test.rb +27 -0
  85. data/test/cases/adapters/postgresql/quoting_test.rb +12 -6
  86. data/test/cases/adapters/postgresql/range_test.rb +406 -292
  87. data/test/cases/adapters/postgresql/referential_integrity_test.rb +16 -15
  88. data/test/cases/adapters/postgresql/rename_table_test.rb +9 -8
  89. data/test/cases/adapters/postgresql/schema_authorization_test.rb +14 -23
  90. data/test/cases/adapters/postgresql/schema_test.rb +207 -91
  91. data/test/cases/adapters/postgresql/serial_test.rb +9 -7
  92. data/test/cases/adapters/postgresql/statement_pool_test.rb +26 -6
  93. data/test/cases/adapters/postgresql/timestamp_test.rb +17 -15
  94. data/test/cases/adapters/postgresql/transaction_nested_test.rb +114 -0
  95. data/test/cases/adapters/postgresql/transaction_test.rb +189 -0
  96. data/test/cases/adapters/postgresql/type_lookup_test.rb +12 -10
  97. data/test/cases/adapters/postgresql/utils_test.rb +11 -9
  98. data/test/cases/adapters/postgresql/uuid_test.rb +226 -109
  99. data/test/cases/adapters/postgresql/xml_test.rb +10 -14
  100. data/test/cases/adapters/sqlite3/collation_test.rb +26 -15
  101. data/test/cases/adapters/sqlite3/copy_table_test.rb +31 -28
  102. data/test/cases/adapters/sqlite3/explain_test.rb +13 -11
  103. data/test/cases/adapters/sqlite3/json_test.rb +29 -0
  104. data/test/cases/adapters/sqlite3/quoting_test.rb +35 -57
  105. data/test/cases/adapters/sqlite3/sqlite3_adapter_prevent_writes_test.rb +186 -0
  106. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +318 -131
  107. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +11 -11
  108. data/test/cases/adapters/sqlite3/statement_pool_test.rb +7 -6
  109. data/test/cases/adapters/sqlite3/transaction_test.rb +123 -0
  110. data/test/cases/aggregations_test.rb +14 -12
  111. data/test/cases/annotate_test.rb +46 -0
  112. data/test/cases/ar_schema_test.rb +153 -86
  113. data/test/cases/arel/attributes/attribute_test.rb +1145 -0
  114. data/test/cases/arel/attributes/math_test.rb +83 -0
  115. data/test/cases/arel/attributes_test.rb +27 -0
  116. data/test/cases/arel/collectors/bind_test.rb +40 -0
  117. data/test/cases/arel/collectors/composite_test.rb +47 -0
  118. data/test/cases/arel/collectors/sql_string_test.rb +41 -0
  119. data/test/cases/arel/collectors/substitute_bind_collector_test.rb +48 -0
  120. data/test/cases/arel/crud_test.rb +65 -0
  121. data/test/cases/arel/delete_manager_test.rb +53 -0
  122. data/test/cases/arel/factory_methods_test.rb +46 -0
  123. data/test/cases/arel/helper.rb +45 -0
  124. data/test/cases/arel/insert_manager_test.rb +241 -0
  125. data/test/cases/arel/nodes/and_test.rb +30 -0
  126. data/test/cases/arel/nodes/as_test.rb +36 -0
  127. data/test/cases/arel/nodes/ascending_test.rb +46 -0
  128. data/test/cases/arel/nodes/bin_test.rb +35 -0
  129. data/test/cases/arel/nodes/binary_test.rb +29 -0
  130. data/test/cases/arel/nodes/bind_param_test.rb +22 -0
  131. data/test/cases/arel/nodes/case_test.rb +96 -0
  132. data/test/cases/arel/nodes/casted_test.rb +18 -0
  133. data/test/cases/arel/nodes/comment_test.rb +22 -0
  134. data/test/cases/arel/nodes/count_test.rb +35 -0
  135. data/test/cases/arel/nodes/delete_statement_test.rb +36 -0
  136. data/test/cases/arel/nodes/descending_test.rb +46 -0
  137. data/test/cases/arel/nodes/distinct_test.rb +21 -0
  138. data/test/cases/arel/nodes/equality_test.rb +62 -0
  139. data/test/cases/arel/nodes/extract_test.rb +43 -0
  140. data/test/cases/arel/nodes/false_test.rb +21 -0
  141. data/test/cases/arel/nodes/grouping_test.rb +26 -0
  142. data/test/cases/arel/nodes/infix_operation_test.rb +42 -0
  143. data/test/cases/arel/nodes/insert_statement_test.rb +44 -0
  144. data/test/cases/arel/nodes/named_function_test.rb +48 -0
  145. data/test/cases/arel/nodes/node_test.rb +22 -0
  146. data/test/cases/arel/nodes/not_test.rb +31 -0
  147. data/test/cases/arel/nodes/or_test.rb +36 -0
  148. data/test/cases/arel/nodes/over_test.rb +69 -0
  149. data/test/cases/arel/nodes/select_core_test.rb +79 -0
  150. data/test/cases/arel/nodes/select_statement_test.rb +51 -0
  151. data/test/cases/arel/nodes/sql_literal_test.rb +75 -0
  152. data/test/cases/arel/nodes/sum_test.rb +35 -0
  153. data/test/cases/arel/nodes/table_alias_test.rb +29 -0
  154. data/test/cases/arel/nodes/true_test.rb +21 -0
  155. data/test/cases/arel/nodes/unary_operation_test.rb +41 -0
  156. data/test/cases/arel/nodes/update_statement_test.rb +60 -0
  157. data/test/cases/arel/nodes/window_test.rb +81 -0
  158. data/test/cases/arel/nodes_test.rb +34 -0
  159. data/test/cases/arel/select_manager_test.rb +1238 -0
  160. data/test/cases/arel/support/fake_record.rb +135 -0
  161. data/test/cases/arel/table_test.rb +216 -0
  162. data/test/cases/arel/update_manager_test.rb +126 -0
  163. data/test/cases/arel/visitors/dispatch_contamination_test.rb +78 -0
  164. data/test/cases/arel/visitors/dot_test.rb +90 -0
  165. data/test/cases/arel/visitors/mysql_test.rb +157 -0
  166. data/test/cases/arel/visitors/postgres_test.rb +366 -0
  167. data/test/cases/arel/visitors/sqlite_test.rb +75 -0
  168. data/test/cases/arel/visitors/to_sql_test.rb +750 -0
  169. data/test/cases/associations/belongs_to_associations_test.rb +510 -158
  170. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +4 -2
  171. data/test/cases/associations/callbacks_test.rb +56 -38
  172. data/test/cases/associations/cascaded_eager_loading_test.rb +118 -61
  173. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +138 -18
  174. data/test/cases/associations/eager_load_nested_include_test.rb +38 -37
  175. data/test/cases/associations/eager_singularization_test.rb +21 -21
  176. data/test/cases/associations/eager_test.rb +559 -415
  177. data/test/cases/associations/extension_test.rb +18 -12
  178. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +234 -213
  179. data/test/cases/associations/has_many_associations_test.rb +1038 -465
  180. data/test/cases/associations/has_many_through_associations_test.rb +558 -249
  181. data/test/cases/associations/has_one_associations_test.rb +294 -129
  182. data/test/cases/associations/has_one_through_associations_test.rb +121 -75
  183. data/test/cases/associations/inner_join_association_test.rb +114 -38
  184. data/test/cases/associations/inverse_associations_test.rb +606 -398
  185. data/test/cases/associations/join_model_test.rb +158 -148
  186. data/test/cases/associations/left_outer_join_association_test.rb +59 -24
  187. data/test/cases/associations/nested_through_associations_test.rb +166 -109
  188. data/test/cases/associations/required_test.rb +35 -10
  189. data/test/cases/associations_test.rb +241 -110
  190. data/test/cases/attribute_methods/read_test.rb +11 -11
  191. data/test/cases/attribute_methods_test.rb +413 -298
  192. data/test/cases/attributes_test.rb +145 -27
  193. data/test/cases/autosave_association_test.rb +681 -436
  194. data/test/cases/base_prevent_writes_test.rb +229 -0
  195. data/test/cases/base_test.rb +599 -542
  196. data/test/cases/batches_test.rb +288 -82
  197. data/test/cases/binary_test.rb +26 -31
  198. data/test/cases/bind_parameter_test.rb +194 -21
  199. data/test/cases/boolean_test.rb +52 -0
  200. data/test/cases/cache_key_test.rb +110 -5
  201. data/test/cases/calculations_test.rb +740 -177
  202. data/test/cases/callbacks_test.rb +74 -207
  203. data/test/cases/clone_test.rb +15 -10
  204. data/test/cases/coders/json_test.rb +2 -0
  205. data/test/cases/coders/yaml_column_test.rb +16 -13
  206. data/test/cases/collection_cache_key_test.rb +177 -20
  207. data/test/cases/column_alias_test.rb +9 -7
  208. data/test/cases/column_definition_test.rb +10 -68
  209. data/test/cases/comment_test.rb +166 -107
  210. data/test/cases/connection_adapters/adapter_leasing_test.rb +14 -10
  211. data/test/cases/connection_adapters/connection_handler_test.rb +358 -51
  212. data/test/cases/connection_adapters/connection_handlers_multi_db_test.rb +400 -0
  213. data/test/cases/connection_adapters/connection_handlers_multi_pool_config_test.rb +103 -0
  214. data/test/cases/connection_adapters/connection_handlers_sharding_db_test.rb +499 -0
  215. data/test/cases/connection_adapters/connection_swapping_nested_test.rb +457 -0
  216. data/test/cases/connection_adapters/legacy_connection_handlers_multi_db_test.rb +486 -0
  217. data/test/cases/connection_adapters/legacy_connection_handlers_sharding_db_test.rb +586 -0
  218. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +319 -138
  219. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +62 -50
  220. data/test/cases/connection_adapters/schema_cache_test.rb +259 -26
  221. data/test/cases/connection_adapters/type_lookup_test.rb +96 -95
  222. data/test/cases/connection_management_test.rb +13 -11
  223. data/test/cases/connection_pool_test.rb +316 -83
  224. data/test/cases/core_test.rb +82 -58
  225. data/test/cases/counter_cache_test.rb +204 -50
  226. data/test/cases/custom_locking_test.rb +5 -3
  227. data/test/cases/database_configurations/hash_config_test.rb +74 -0
  228. data/test/cases/database_configurations/resolver_test.rb +150 -0
  229. data/test/cases/database_configurations_test.rb +145 -0
  230. data/test/cases/database_selector_test.rb +296 -0
  231. data/test/cases/database_statements_test.rb +18 -16
  232. data/test/cases/date_test.rb +8 -16
  233. data/test/cases/date_time_precision_test.rb +100 -78
  234. data/test/cases/date_time_test.rb +23 -8
  235. data/test/cases/defaults_test.rb +106 -71
  236. data/test/cases/delegated_type_test.rb +57 -0
  237. data/test/cases/dirty_test.rb +419 -223
  238. data/test/cases/disconnected_test.rb +6 -6
  239. data/test/cases/dup_test.rb +54 -27
  240. data/test/cases/enum_test.rb +461 -82
  241. data/test/cases/errors_test.rb +7 -7
  242. data/test/cases/explain_subscriber_test.rb +17 -15
  243. data/test/cases/explain_test.rb +11 -19
  244. data/test/cases/filter_attributes_test.rb +153 -0
  245. data/test/cases/finder_respond_to_test.rb +14 -14
  246. data/test/cases/finder_test.rb +669 -287
  247. data/test/cases/fixture_set/file_test.rb +34 -38
  248. data/test/cases/fixtures_test.rb +833 -176
  249. data/test/cases/forbidden_attributes_protection_test.rb +32 -67
  250. data/test/cases/habtm_destroy_order_test.rb +25 -25
  251. data/test/cases/helper.rb +78 -49
  252. data/test/cases/hot_compatibility_test.rb +33 -32
  253. data/test/cases/i18n_test.rb +18 -17
  254. data/test/cases/inheritance_test.rb +180 -115
  255. data/test/cases/insert_all_test.rb +489 -0
  256. data/test/cases/instrumentation_test.rb +101 -0
  257. data/test/cases/integration_test.rb +119 -31
  258. data/test/cases/invalid_connection_test.rb +18 -16
  259. data/test/cases/invertible_migration_test.rb +183 -43
  260. data/test/cases/json_attribute_test.rb +35 -0
  261. data/test/cases/json_serialization_test.rb +57 -58
  262. data/test/cases/json_shared_test_cases.rb +290 -0
  263. data/test/cases/locking_test.rb +413 -119
  264. data/test/cases/log_subscriber_test.rb +68 -26
  265. data/test/cases/marshal_serialization_test.rb +39 -0
  266. data/test/cases/migration/change_schema_test.rb +118 -72
  267. data/test/cases/migration/change_table_test.rb +138 -30
  268. data/test/cases/migration/check_constraint_test.rb +162 -0
  269. data/test/cases/migration/column_attributes_test.rb +45 -35
  270. data/test/cases/migration/column_positioning_test.rb +18 -6
  271. data/test/cases/migration/columns_test.rb +93 -77
  272. data/test/cases/migration/command_recorder_test.rb +121 -34
  273. data/test/cases/migration/compatibility_test.rb +578 -23
  274. data/test/cases/migration/create_join_table_test.rb +35 -25
  275. data/test/cases/migration/foreign_key_test.rb +503 -284
  276. data/test/cases/migration/helper.rb +4 -3
  277. data/test/cases/migration/index_test.rb +119 -70
  278. data/test/cases/migration/logger_test.rb +9 -6
  279. data/test/cases/migration/pending_migrations_test.rb +88 -34
  280. data/test/cases/migration/references_foreign_key_test.rb +164 -150
  281. data/test/cases/migration/references_index_test.rb +38 -19
  282. data/test/cases/migration/references_statements_test.rb +15 -14
  283. data/test/cases/migration/rename_table_test.rb +53 -30
  284. data/test/cases/migration_test.rb +637 -269
  285. data/test/cases/migrator_test.rb +191 -135
  286. data/test/cases/mixin_test.rb +7 -11
  287. data/test/cases/modules_test.rb +36 -34
  288. data/test/cases/multi_db_migrator_test.rb +223 -0
  289. data/test/cases/multiparameter_attributes_test.rb +60 -33
  290. data/test/cases/multiple_db_test.rb +16 -22
  291. data/test/cases/nested_attributes_test.rb +341 -320
  292. data/test/cases/nested_attributes_with_callbacks_test.rb +26 -24
  293. data/test/cases/null_relation_test.rb +84 -0
  294. data/test/cases/numeric_data_test.rb +93 -0
  295. data/test/cases/persistence_test.rb +361 -269
  296. data/test/cases/pooled_connections_test.rb +18 -26
  297. data/test/cases/prepared_statement_status_test.rb +48 -0
  298. data/test/cases/primary_keys_test.rb +210 -104
  299. data/test/cases/query_cache_test.rb +610 -141
  300. data/test/cases/quoting_test.rb +132 -31
  301. data/test/cases/readonly_test.rb +49 -48
  302. data/test/cases/reaper_test.rb +146 -32
  303. data/test/cases/reflection_test.rb +167 -156
  304. data/test/cases/relation/delegation_test.rb +49 -36
  305. data/test/cases/relation/delete_all_test.rb +117 -0
  306. data/test/cases/relation/merging_test.rb +319 -42
  307. data/test/cases/relation/mutation_test.rb +55 -93
  308. data/test/cases/relation/or_test.rb +129 -29
  309. data/test/cases/relation/predicate_builder_test.rb +21 -6
  310. data/test/cases/relation/record_fetch_warning_test.rb +5 -3
  311. data/test/cases/relation/select_test.rb +67 -0
  312. data/test/cases/relation/update_all_test.rb +317 -0
  313. data/test/cases/relation/where_chain_test.rb +68 -32
  314. data/test/cases/relation/where_clause_test.rb +136 -61
  315. data/test/cases/relation/where_test.rb +155 -48
  316. data/test/cases/relation_test.rb +266 -112
  317. data/test/cases/relations_test.rb +969 -744
  318. data/test/cases/reload_models_test.rb +13 -9
  319. data/test/cases/reserved_word_test.rb +141 -0
  320. data/test/cases/result_test.rb +68 -17
  321. data/test/cases/sanitize_test.rb +87 -71
  322. data/test/cases/schema_dumper_test.rb +221 -128
  323. data/test/cases/schema_loading_test.rb +3 -2
  324. data/test/cases/scoping/default_scoping_test.rb +185 -144
  325. data/test/cases/scoping/named_scoping_test.rb +177 -89
  326. data/test/cases/scoping/relation_scoping_test.rb +197 -75
  327. data/test/cases/secure_token_test.rb +18 -3
  328. data/test/cases/serialization_test.rb +30 -28
  329. data/test/cases/serialized_attribute_test.rb +133 -42
  330. data/test/cases/signed_id_test.rb +168 -0
  331. data/test/cases/statement_cache_test.rb +41 -24
  332. data/test/cases/statement_invalid_test.rb +42 -0
  333. data/test/cases/store_test.rb +180 -55
  334. data/test/cases/strict_loading_test.rb +473 -0
  335. data/test/cases/suppressor_test.rb +26 -12
  336. data/test/cases/tasks/database_tasks_test.rb +1258 -194
  337. data/test/cases/tasks/mysql_rake_test.rb +370 -298
  338. data/test/cases/tasks/postgresql_rake_test.rb +481 -251
  339. data/test/cases/tasks/sqlite_rake_test.rb +225 -178
  340. data/test/cases/test_case.rb +51 -40
  341. data/test/cases/test_databases_test.rb +79 -0
  342. data/test/cases/test_fixtures_test.rb +79 -19
  343. data/test/cases/time_precision_test.rb +98 -76
  344. data/test/cases/timestamp_test.rb +102 -99
  345. data/test/cases/touch_later_test.rb +12 -10
  346. data/test/cases/transaction_callbacks_test.rb +344 -90
  347. data/test/cases/transaction_isolation_test.rb +12 -12
  348. data/test/cases/transactions_test.rb +612 -162
  349. data/test/cases/type/adapter_specific_registry_test.rb +14 -2
  350. data/test/cases/type/date_time_test.rb +4 -2
  351. data/test/cases/type/integer_test.rb +4 -2
  352. data/test/cases/type/string_test.rb +10 -8
  353. data/test/cases/type/time_test.rb +28 -0
  354. data/test/cases/type/type_map_test.rb +29 -28
  355. data/test/cases/type/unsigned_integer_test.rb +19 -0
  356. data/test/cases/type_test.rb +2 -0
  357. data/test/cases/types_test.rb +3 -1
  358. data/test/cases/unconnected_test.rb +14 -1
  359. data/test/cases/unsafe_raw_sql_test.rb +274 -0
  360. data/test/cases/validations/absence_validation_test.rb +19 -17
  361. data/test/cases/validations/association_validation_test.rb +30 -28
  362. data/test/cases/validations/i18n_generate_message_validation_test.rb +34 -16
  363. data/test/cases/validations/i18n_validation_test.rb +22 -21
  364. data/test/cases/validations/length_validation_test.rb +34 -33
  365. data/test/cases/validations/numericality_validation_test.rb +181 -0
  366. data/test/cases/validations/presence_validation_test.rb +21 -19
  367. data/test/cases/validations/uniqueness_validation_test.rb +156 -86
  368. data/test/cases/validations_repair_helper.rb +2 -0
  369. data/test/cases/validations_test.rb +61 -26
  370. data/test/cases/view_test.rb +122 -116
  371. data/test/cases/yaml_serialization_test.rb +79 -34
  372. data/test/config.example.yml +19 -19
  373. data/test/config.rb +3 -1
  374. data/test/config.yml +16 -6
  375. data/test/fixtures/all/namespaced/accounts.yml +2 -0
  376. data/test/fixtures/author_addresses.yml +1 -8
  377. data/test/fixtures/authors.yml +1 -7
  378. data/test/fixtures/binaries.yml +4 -0
  379. data/test/fixtures/books.yml +9 -2
  380. data/test/fixtures/categories_posts.yml +3 -0
  381. data/test/fixtures/citations.yml +5 -0
  382. data/test/fixtures/comments.yml +7 -0
  383. data/test/fixtures/companies.yml +5 -0
  384. data/test/fixtures/computers.yml +2 -0
  385. data/test/fixtures/customers.yml +10 -1
  386. data/test/fixtures/developers.yml +1 -1
  387. data/test/fixtures/essays.yml +10 -0
  388. data/test/fixtures/faces.yml +3 -3
  389. data/test/fixtures/humans.yml +5 -0
  390. data/test/fixtures/interests.yml +7 -7
  391. data/test/fixtures/memberships.yml +7 -0
  392. data/test/fixtures/minimalistics.yml +3 -0
  393. data/test/fixtures/mixed_case_monkeys.yml +2 -2
  394. data/test/fixtures/naked/yml/courses_with_invalid_key.yml +3 -0
  395. data/test/fixtures/naked/yml/parrots.yml +1 -0
  396. data/test/fixtures/other_books.yml +26 -0
  397. data/test/fixtures/other_posts.yml +1 -0
  398. data/test/fixtures/parrots.yml +7 -1
  399. data/test/fixtures/pirates.yml +3 -0
  400. data/test/fixtures/posts.yml +11 -3
  401. data/test/fixtures/readers.yml +6 -0
  402. data/test/fixtures/reserved_words/values.yml +2 -2
  403. data/test/fixtures/sponsors.yml +3 -0
  404. data/test/fixtures/strict_zines.yml +2 -0
  405. data/test/fixtures/subscribers.yml +1 -1
  406. data/test/fixtures/tasks.yml +1 -1
  407. data/test/fixtures/warehouse-things.yml +3 -0
  408. data/test/migrations/10_urban/9_add_expressions.rb +2 -0
  409. data/test/migrations/decimal/1_give_me_big_numbers.rb +6 -4
  410. data/test/migrations/magic/1_currencies_have_symbols.rb +3 -2
  411. data/test/migrations/missing/1000_people_have_middle_names.rb +2 -0
  412. data/test/migrations/missing/1_people_have_last_names.rb +2 -0
  413. data/test/migrations/missing/3_we_need_reminders.rb +2 -0
  414. data/test/migrations/missing/4_innocent_jointable.rb +3 -1
  415. data/test/migrations/rename/1_we_need_things.rb +2 -0
  416. data/test/migrations/rename/2_rename_things.rb +2 -0
  417. data/test/migrations/to_copy/1_people_have_hobbies.rb +3 -1
  418. data/test/migrations/to_copy/2_people_have_descriptions.rb +3 -1
  419. data/test/migrations/to_copy2/1_create_articles.rb +2 -0
  420. data/test/migrations/to_copy2/2_create_comments.rb +3 -1
  421. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +3 -1
  422. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +3 -1
  423. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +3 -1
  424. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +2 -0
  425. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +2 -0
  426. data/test/migrations/valid/1_valid_people_have_last_names.rb +2 -0
  427. data/test/migrations/valid/2_we_need_reminders.rb +2 -0
  428. data/test/migrations/valid/3_innocent_jointable.rb +3 -1
  429. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +2 -0
  430. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +2 -0
  431. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +3 -1
  432. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +2 -0
  433. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +2 -0
  434. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +3 -1
  435. data/test/migrations/version_check/20131219224947_migration_version_check.rb +2 -0
  436. data/test/models/account.rb +46 -0
  437. data/test/models/admin/account.rb +3 -1
  438. data/test/models/admin/randomly_named_c1.rb +2 -0
  439. data/test/models/admin/user.rb +16 -8
  440. data/test/models/admin.rb +4 -2
  441. data/test/models/aircraft.rb +3 -1
  442. data/test/models/arunit2_model.rb +2 -0
  443. data/test/models/author.rb +153 -102
  444. data/test/models/auto_id.rb +2 -0
  445. data/test/models/autoloadable/extra_firm.rb +2 -0
  446. data/test/models/binary.rb +3 -1
  447. data/test/models/binary_field.rb +6 -0
  448. data/test/models/bird.rb +13 -1
  449. data/test/models/book.rb +14 -4
  450. data/test/models/book_destroy_async.rb +24 -0
  451. data/test/models/boolean.rb +5 -0
  452. data/test/models/bulb.rb +13 -4
  453. data/test/models/cake_designer.rb +2 -0
  454. data/test/models/car.rb +17 -10
  455. data/test/models/carrier.rb +2 -0
  456. data/test/models/cart.rb +5 -0
  457. data/test/models/cat.rb +2 -0
  458. data/test/models/categorization.rb +8 -6
  459. data/test/models/category.rb +28 -16
  460. data/test/models/chef.rb +2 -0
  461. data/test/models/citation.rb +5 -1
  462. data/test/models/club.rb +13 -10
  463. data/test/models/college.rb +4 -2
  464. data/test/models/column.rb +2 -0
  465. data/test/models/column_name.rb +2 -0
  466. data/test/models/comment.rb +32 -10
  467. data/test/models/company.rb +102 -106
  468. data/test/models/company_in_module.rb +27 -26
  469. data/test/models/computer.rb +3 -1
  470. data/test/models/contact.rb +15 -13
  471. data/test/models/content.rb +5 -3
  472. data/test/models/contract.rb +21 -3
  473. data/test/models/country.rb +2 -4
  474. data/test/models/course.rb +3 -1
  475. data/test/models/customer.rb +10 -8
  476. data/test/models/customer_carrier.rb +2 -0
  477. data/test/models/dashboard.rb +2 -0
  478. data/test/models/default.rb +2 -0
  479. data/test/models/department.rb +2 -0
  480. data/test/models/destroy_async_parent.rb +15 -0
  481. data/test/models/destroy_async_parent_soft_delete.rb +20 -0
  482. data/test/models/developer.rb +152 -85
  483. data/test/models/dl_keyed_belongs_to.rb +13 -0
  484. data/test/models/dl_keyed_belongs_to_soft_delete.rb +19 -0
  485. data/test/models/dl_keyed_has_many.rb +5 -0
  486. data/test/models/dl_keyed_has_many_through.rb +5 -0
  487. data/test/models/dl_keyed_has_one.rb +5 -0
  488. data/test/models/dl_keyed_join.rb +10 -0
  489. data/test/models/dog.rb +2 -0
  490. data/test/models/dog_lover.rb +2 -0
  491. data/test/models/doubloon.rb +3 -1
  492. data/test/models/drink_designer.rb +17 -0
  493. data/test/models/edge.rb +4 -2
  494. data/test/models/electron.rb +2 -0
  495. data/test/models/engine.rb +3 -2
  496. data/test/models/entrant.rb +2 -0
  497. data/test/models/entry.rb +5 -0
  498. data/test/models/essay.rb +6 -3
  499. data/test/models/essay_destroy_async.rb +12 -0
  500. data/test/models/event.rb +3 -1
  501. data/test/models/eye.rb +5 -3
  502. data/test/models/face.rb +14 -6
  503. data/test/models/family.rb +6 -0
  504. data/test/models/family_tree.rb +6 -0
  505. data/test/models/friendship.rb +5 -3
  506. data/test/models/frog.rb +8 -0
  507. data/test/models/guid.rb +3 -1
  508. data/test/models/guitar.rb +2 -0
  509. data/test/models/hotel.rb +5 -3
  510. data/test/models/human.rb +39 -0
  511. data/test/models/image.rb +3 -1
  512. data/test/models/interest.rb +14 -3
  513. data/test/models/invoice.rb +4 -2
  514. data/test/models/item.rb +3 -1
  515. data/test/models/job.rb +5 -3
  516. data/test/models/joke.rb +4 -2
  517. data/test/models/keyboard.rb +3 -1
  518. data/test/models/legacy_thing.rb +2 -0
  519. data/test/models/lesson.rb +2 -0
  520. data/test/models/line_item.rb +3 -1
  521. data/test/models/liquid.rb +2 -0
  522. data/test/models/matey.rb +3 -1
  523. data/test/models/measurement.rb +4 -0
  524. data/test/models/member.rb +23 -20
  525. data/test/models/member_detail.rb +3 -0
  526. data/test/models/member_type.rb +2 -0
  527. data/test/models/membership.rb +4 -1
  528. data/test/models/mentor.rb +3 -1
  529. data/test/models/message.rb +5 -0
  530. data/test/models/minimalistic.rb +2 -0
  531. data/test/models/minivan.rb +3 -2
  532. data/test/models/mixed_case_monkey.rb +3 -1
  533. data/test/models/molecule.rb +2 -0
  534. data/test/models/mouse.rb +6 -0
  535. data/test/models/movie.rb +2 -0
  536. data/test/models/node.rb +4 -2
  537. data/test/models/non_primary_key.rb +2 -0
  538. data/test/models/notification.rb +2 -0
  539. data/test/models/numeric_data.rb +12 -0
  540. data/test/models/order.rb +4 -2
  541. data/test/models/organization.rb +9 -7
  542. data/test/models/other_dog.rb +3 -1
  543. data/test/models/owner.rb +6 -4
  544. data/test/models/parrot.rb +12 -4
  545. data/test/models/person.rb +59 -54
  546. data/test/models/personal_legacy_thing.rb +3 -1
  547. data/test/models/pet.rb +4 -2
  548. data/test/models/pet_treasure.rb +2 -0
  549. data/test/models/pirate.rb +67 -43
  550. data/test/models/possession.rb +3 -1
  551. data/test/models/post.rb +184 -86
  552. data/test/models/price_estimate.rb +11 -1
  553. data/test/models/professor.rb +3 -1
  554. data/test/models/project.rb +14 -12
  555. data/test/models/publisher/article.rb +2 -0
  556. data/test/models/publisher/magazine.rb +2 -0
  557. data/test/models/publisher.rb +2 -0
  558. data/test/models/randomly_named_c1.rb +2 -0
  559. data/test/models/rating.rb +5 -1
  560. data/test/models/reader.rb +7 -5
  561. data/test/models/recipe.rb +2 -0
  562. data/test/models/record.rb +2 -0
  563. data/test/models/reference.rb +6 -3
  564. data/test/models/reply.rb +39 -21
  565. data/test/models/room.rb +6 -0
  566. data/test/models/section.rb +6 -0
  567. data/test/models/seminar.rb +6 -0
  568. data/test/models/session.rb +6 -0
  569. data/test/models/ship.rb +12 -9
  570. data/test/models/ship_part.rb +5 -3
  571. data/test/models/shop.rb +4 -2
  572. data/test/models/shop_account.rb +2 -0
  573. data/test/models/speedometer.rb +2 -0
  574. data/test/models/sponsor.rb +8 -5
  575. data/test/models/squeak.rb +6 -0
  576. data/test/models/strict_zine.rb +7 -0
  577. data/test/models/string_key_object.rb +2 -0
  578. data/test/models/student.rb +2 -0
  579. data/test/models/subscriber.rb +4 -2
  580. data/test/models/subscription.rb +5 -1
  581. data/test/models/tag.rb +6 -3
  582. data/test/models/tagging.rb +13 -6
  583. data/test/models/task.rb +2 -0
  584. data/test/models/topic.rb +54 -19
  585. data/test/models/toy.rb +4 -0
  586. data/test/models/traffic_light.rb +2 -0
  587. data/test/models/treasure.rb +5 -3
  588. data/test/models/treaty.rb +2 -4
  589. data/test/models/tree.rb +2 -0
  590. data/test/models/tuning_peg.rb +2 -0
  591. data/test/models/tyre.rb +2 -0
  592. data/test/models/user.rb +12 -4
  593. data/test/models/uuid_child.rb +2 -0
  594. data/test/models/uuid_item.rb +2 -0
  595. data/test/models/uuid_parent.rb +2 -0
  596. data/test/models/vegetables.rb +12 -3
  597. data/test/models/vertex.rb +6 -4
  598. data/test/models/warehouse_thing.rb +2 -0
  599. data/test/models/wheel.rb +3 -1
  600. data/test/models/without_table.rb +3 -1
  601. data/test/models/zine.rb +3 -1
  602. data/test/schema/mysql2_specific_schema.rb +49 -35
  603. data/test/schema/oracle_specific_schema.rb +13 -15
  604. data/test/schema/postgresql_specific_schema.rb +51 -40
  605. data/test/schema/schema.rb +334 -154
  606. data/test/schema/sqlite_specific_schema.rb +9 -16
  607. data/test/support/config.rb +26 -26
  608. data/test/support/connection.rb +14 -8
  609. data/test/support/connection_helper.rb +3 -1
  610. data/test/support/ddl_helper.rb +2 -0
  611. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic.dump +0 -0
  612. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic_associations.dump +0 -0
  613. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic.dump +0 -0
  614. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic_associations.dump +0 -0
  615. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic.dump +0 -0
  616. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic_associations.dump +0 -0
  617. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic.dump +0 -0
  618. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic_associations.dump +0 -0
  619. data/test/support/marshal_compatibility_fixtures/legacy_6_0_record_mysql.dump +0 -0
  620. data/test/support/marshal_compatibility_fixtures/legacy_relation.dump +0 -0
  621. data/test/support/schema_dumping_helper.rb +2 -0
  622. data/test/support/stubs/strong_parameters.rb +40 -0
  623. data/test/support/yaml_compatibility_fixtures/rails_v1_mysql.yml +206 -0
  624. data/test/support/yaml_compatibility_fixtures/rails_v2.yml +55 -0
  625. metadata +192 -14
@@ -1,24 +1,27 @@
1
- require 'thread'
1
+ # frozen_string_literal: true
2
+
3
+ require "thread"
2
4
  require "cases/helper"
3
- require 'models/person'
4
- require 'models/job'
5
- require 'models/reader'
6
- require 'models/ship'
7
- require 'models/legacy_thing'
8
- require 'models/personal_legacy_thing'
9
- require 'models/reference'
10
- require 'models/string_key_object'
11
- require 'models/car'
12
- require 'models/bulb'
13
- require 'models/engine'
14
- require 'models/wheel'
15
- require 'models/treasure'
5
+ require "models/person"
6
+ require "models/job"
7
+ require "models/reader"
8
+ require "models/ship"
9
+ require "models/legacy_thing"
10
+ require "models/personal_legacy_thing"
11
+ require "models/reference"
12
+ require "models/string_key_object"
13
+ require "models/car"
14
+ require "models/bulb"
15
+ require "models/engine"
16
+ require "models/wheel"
17
+ require "models/treasure"
18
+ require "models/frog"
16
19
 
17
20
  class LockWithoutDefault < ActiveRecord::Base; end
18
21
 
19
22
  class LockWithCustomColumnWithoutDefault < ActiveRecord::Base
20
23
  self.table_name = :lock_without_defaults_cust
21
- self.column_defaults # to test @column_defaults caching.
24
+ column_defaults # to test @column_defaults caching.
22
25
  self.locking_column = :custom_lock_version
23
26
  end
24
27
 
@@ -33,7 +36,7 @@ class OptimisticLockingTest < ActiveRecord::TestCase
33
36
  p1 = Person.find(1)
34
37
  assert_equal 0, p1.lock_version
35
38
 
36
- p1.first_name = 'anika2'
39
+ p1.first_name = "anika2"
37
40
  p1.save!
38
41
 
39
42
  assert_equal 1, p1.lock_version
@@ -45,12 +48,12 @@ class OptimisticLockingTest < ActiveRecord::TestCase
45
48
  assert_equal 0, s1.lock_version
46
49
  assert_equal 0, s2.lock_version
47
50
 
48
- s1.name = 'updated record'
51
+ s1.name = "updated record"
49
52
  s1.save!
50
53
  assert_equal 1, s1.lock_version
51
54
  assert_equal 0, s2.lock_version
52
55
 
53
- s2.name = 'doubly updated record'
56
+ s2.name = "doubly updated record"
54
57
  assert_raise(ActiveRecord::StaleObjectError) { s2.save! }
55
58
  end
56
59
 
@@ -60,15 +63,15 @@ class OptimisticLockingTest < ActiveRecord::TestCase
60
63
  assert_equal 0, s1.lock_version
61
64
  assert_equal 0, s2.lock_version
62
65
 
63
- s1.name = 'updated record'
66
+ s1.name = "updated record"
64
67
  s1.save!
65
68
  assert_equal 1, s1.lock_version
66
69
  assert_equal 0, s2.lock_version
67
70
  assert_raise(ActiveRecord::StaleObjectError) { s2.destroy }
68
71
 
69
72
  assert s1.destroy
70
- assert s1.frozen?
71
- assert s1.destroyed?
73
+ assert_predicate s1, :frozen?
74
+ assert_predicate s1, :destroyed?
72
75
  assert_raises(ActiveRecord::RecordNotFound) { StringKeyObject.find("record1") }
73
76
  end
74
77
 
@@ -78,12 +81,12 @@ class OptimisticLockingTest < ActiveRecord::TestCase
78
81
  assert_equal 0, p1.lock_version
79
82
  assert_equal 0, p2.lock_version
80
83
 
81
- p1.first_name = 'stu'
84
+ p1.first_name = "stu"
82
85
  p1.save!
83
86
  assert_equal 1, p1.lock_version
84
87
  assert_equal 0, p2.lock_version
85
88
 
86
- p2.first_name = 'sue'
89
+ p2.first_name = "sue"
87
90
  assert_raise(ActiveRecord::StaleObjectError) { p2.save! }
88
91
  end
89
92
 
@@ -94,7 +97,7 @@ class OptimisticLockingTest < ActiveRecord::TestCase
94
97
  assert_equal 0, p1.lock_version
95
98
  assert_equal 0, p2.lock_version
96
99
 
97
- p1.first_name = 'stu'
100
+ p1.first_name = "stu"
98
101
  p1.save!
99
102
  assert_equal 1, p1.lock_version
100
103
  assert_equal 0, p2.lock_version
@@ -102,8 +105,8 @@ class OptimisticLockingTest < ActiveRecord::TestCase
102
105
  assert_raises(ActiveRecord::StaleObjectError) { p2.destroy }
103
106
 
104
107
  assert p1.destroy
105
- assert p1.frozen?
106
- assert p1.destroyed?
108
+ assert_predicate p1, :frozen?
109
+ assert_predicate p1, :destroyed?
107
110
  assert_raises(ActiveRecord::RecordNotFound) { Person.find(1) }
108
111
  end
109
112
 
@@ -113,66 +116,64 @@ class OptimisticLockingTest < ActiveRecord::TestCase
113
116
  assert_equal 0, p1.lock_version
114
117
  assert_equal 0, p2.lock_version
115
118
 
116
- p1.first_name = 'stu'
119
+ p1.first_name = "stu"
117
120
  p1.save!
118
121
  assert_equal 1, p1.lock_version
119
122
  assert_equal 0, p2.lock_version
120
123
 
121
- p2.first_name = 'sue'
124
+ p2.first_name = "sue"
122
125
  assert_raise(ActiveRecord::StaleObjectError) { p2.save! }
123
- p2.first_name = 'sue2'
126
+ p2.first_name = "sue2"
124
127
  assert_raise(ActiveRecord::StaleObjectError) { p2.save! }
125
128
  end
126
129
 
127
130
  def test_lock_new
128
- p1 = Person.new(:first_name => 'anika')
131
+ p1 = Person.new(first_name: "anika")
129
132
  assert_equal 0, p1.lock_version
130
133
 
131
- p1.first_name = 'anika2'
134
+ p1.first_name = "anika2"
132
135
  p1.save!
133
136
  p2 = Person.find(p1.id)
134
137
  assert_equal 0, p1.lock_version
135
138
  assert_equal 0, p2.lock_version
136
139
 
137
- p1.first_name = 'anika3'
140
+ p1.first_name = "anika3"
138
141
  p1.save!
139
142
  assert_equal 1, p1.lock_version
140
143
  assert_equal 0, p2.lock_version
141
144
 
142
- p2.first_name = 'sue'
145
+ p2.first_name = "sue"
143
146
  assert_raise(ActiveRecord::StaleObjectError) { p2.save! }
144
147
  end
145
148
 
146
149
  def test_lock_exception_record
147
- p1 = Person.new(:first_name => 'mira')
150
+ p1 = Person.new(first_name: "mira")
148
151
  assert_equal 0, p1.lock_version
149
152
 
150
- p1.first_name = 'mira2'
153
+ p1.first_name = "mira2"
151
154
  p1.save!
152
155
  p2 = Person.find(p1.id)
153
156
  assert_equal 0, p1.lock_version
154
157
  assert_equal 0, p2.lock_version
155
158
 
156
- p1.first_name = 'mira3'
159
+ p1.first_name = "mira3"
157
160
  p1.save!
158
161
 
159
- p2.first_name = 'sue'
162
+ p2.first_name = "sue"
160
163
  error = assert_raise(ActiveRecord::StaleObjectError) { p2.save! }
161
- assert_equal(error.record.object_id, p2.object_id)
164
+ assert_same error.record, p2
162
165
  end
163
166
 
164
- def test_lock_new_with_nil
165
- p1 = Person.new(:first_name => 'anika')
166
- p1.save!
167
- p1.lock_version = nil # simulate bad fixture or column with no default
167
+ def test_lock_new_when_explicitly_passing_nil
168
+ p1 = Person.new(first_name: "anika", lock_version: nil)
168
169
  p1.save!
169
- assert_equal 1, p1.lock_version
170
+ assert_equal 0, p1.lock_version
170
171
  end
171
172
 
172
- def test_lock_new_when_explicitly_passing_nil
173
- p1 = Person.new(:first_name => 'anika', lock_version: nil)
173
+ def test_lock_new_when_explicitly_passing_value
174
+ p1 = Person.new(first_name: "Douglas Adams", lock_version: 42)
174
175
  p1.save!
175
- assert_equal 0, p1.lock_version
176
+ assert_equal 42, p1.lock_version
176
177
  end
177
178
 
178
179
  def test_touch_existing_lock
@@ -181,16 +182,73 @@ class OptimisticLockingTest < ActiveRecord::TestCase
181
182
 
182
183
  p1.touch
183
184
  assert_equal 1, p1.lock_version
185
+ assert_not_predicate p1, :changed?, "Changes should have been cleared"
186
+ assert_predicate p1, :saved_changes?
187
+ assert_equal ["lock_version", "updated_at"], p1.saved_changes.keys.sort
184
188
  end
185
189
 
186
190
  def test_touch_stale_object
187
- person = Person.create!(first_name: 'Mehmet Emin')
191
+ person = Person.create!(first_name: "Mehmet Emin")
188
192
  stale_person = Person.find(person.id)
189
- person.update_attribute(:gender, 'M')
193
+ person.update_attribute(:gender, "M")
190
194
 
191
195
  assert_raises(ActiveRecord::StaleObjectError) do
192
196
  stale_person.touch
193
197
  end
198
+
199
+ assert_not_predicate stale_person, :saved_changes?
200
+ end
201
+
202
+ def test_update_with_dirty_primary_key
203
+ assert_raises(ActiveRecord::RecordNotUnique) do
204
+ person = Person.find(1)
205
+ person.id = 2
206
+ person.save!
207
+ end
208
+
209
+ person = Person.find(1)
210
+ person.id = 42
211
+ person.save!
212
+
213
+ assert Person.find(42)
214
+ assert_raises(ActiveRecord::RecordNotFound) do
215
+ Person.find(1)
216
+ end
217
+ end
218
+
219
+ def test_delete_with_dirty_primary_key
220
+ person = Person.find(1)
221
+ person.id = 2
222
+ person.delete
223
+
224
+ assert Person.find(2)
225
+ assert_raises(ActiveRecord::RecordNotFound) do
226
+ Person.find(1)
227
+ end
228
+ end
229
+
230
+ def test_destroy_with_dirty_primary_key
231
+ person = Person.find(1)
232
+ person.id = 2
233
+ person.destroy
234
+
235
+ assert Person.find(2)
236
+ assert_raises(ActiveRecord::RecordNotFound) do
237
+ Person.find(1)
238
+ end
239
+ end
240
+
241
+ def test_explicit_update_lock_column_raise_error
242
+ person = Person.find(1)
243
+
244
+ assert_raises(ActiveRecord::StaleObjectError) do
245
+ person.first_name = "Douglas Adams"
246
+ person.lock_version = 42
247
+
248
+ assert_predicate person, :lock_version_changed?
249
+
250
+ person.save
251
+ end
194
252
  end
195
253
 
196
254
  def test_lock_column_name_existing
@@ -209,11 +267,11 @@ class OptimisticLockingTest < ActiveRecord::TestCase
209
267
  end
210
268
 
211
269
  def test_lock_column_is_mass_assignable
212
- p1 = Person.create(:first_name => 'bianca')
270
+ p1 = Person.create(first_name: "bianca")
213
271
  assert_equal 0, p1.lock_version
214
272
  assert_equal p1.lock_version, Person.new(p1.attributes).lock_version
215
273
 
216
- p1.first_name = 'bianca2'
274
+ p1.first_name = "bianca2"
217
275
  p1.save!
218
276
  assert_equal 1, p1.lock_version
219
277
  assert_equal p1.lock_version, Person.new(p1.attributes).lock_version
@@ -221,28 +279,182 @@ class OptimisticLockingTest < ActiveRecord::TestCase
221
279
 
222
280
  def test_lock_without_default_sets_version_to_zero
223
281
  t1 = LockWithoutDefault.new
282
+
283
+ assert_equal 0, t1.lock_version
284
+ assert_nil t1.lock_version_before_type_cast
285
+
286
+ t1.save!
287
+ t1.reload
288
+
289
+ assert_equal 0, t1.lock_version
290
+ assert_equal 0, t1.lock_version_before_type_cast
291
+ end
292
+
293
+ def test_touch_existing_lock_without_default_should_work_with_null_in_the_database
294
+ ActiveRecord::Base.connection.execute("INSERT INTO lock_without_defaults(title) VALUES('title1')")
295
+ t1 = LockWithoutDefault.last
296
+
297
+ assert_equal 0, t1.lock_version
298
+ assert_nil t1.lock_version_before_type_cast
299
+
300
+ t1.touch
301
+
302
+ assert_equal 1, t1.lock_version
303
+ assert_not_predicate t1, :changed?
304
+ assert_predicate t1, :saved_changes?
305
+ assert_equal ["lock_version", "updated_at"], t1.saved_changes.keys.sort
306
+ end
307
+
308
+ def test_touch_stale_object_with_lock_without_default
309
+ t1 = LockWithoutDefault.create!(title: "title1")
310
+ stale_object = LockWithoutDefault.find(t1.id)
311
+
312
+ t1.update!(title: "title2")
313
+
314
+ assert_raises(ActiveRecord::StaleObjectError) do
315
+ stale_object.touch
316
+ end
317
+
318
+ assert_not_predicate stale_object, :saved_changes?
319
+ end
320
+
321
+ def test_lock_without_default_should_work_with_null_in_the_database
322
+ ActiveRecord::Base.connection.execute("INSERT INTO lock_without_defaults(title) VALUES('title1')")
323
+ t1 = LockWithoutDefault.last
324
+ t2 = LockWithoutDefault.find(t1.id)
325
+
326
+ assert_equal 0, t1.lock_version
327
+ assert_nil t1.lock_version_before_type_cast
328
+ assert_equal 0, t2.lock_version
329
+ assert_nil t2.lock_version_before_type_cast
330
+
331
+ t1.title = "new title1"
332
+ t2.title = "new title2"
333
+
334
+ assert_nothing_raised { t1.save! }
335
+ assert_equal 1, t1.lock_version
336
+ assert_equal "new title1", t1.title
337
+
338
+ assert_raise(ActiveRecord::StaleObjectError) { t2.save! }
339
+ assert_equal 0, t2.lock_version
340
+ assert_equal "new title2", t2.title
341
+ end
342
+
343
+ def test_update_with_lock_version_without_default_should_work_on_dirty_value_before_type_cast
344
+ ActiveRecord::Base.connection.execute("INSERT INTO lock_without_defaults(title) VALUES('title1')")
345
+ t1 = LockWithoutDefault.last
346
+
224
347
  assert_equal 0, t1.lock_version
348
+ assert_nil t1.lock_version_before_type_cast
349
+
350
+ t1.lock_version = t1.lock_version
225
351
 
226
- t1.save
227
- t1 = LockWithoutDefault.find(t1.id)
228
352
  assert_equal 0, t1.lock_version
353
+ assert_equal 0, t1.lock_version_before_type_cast
354
+
355
+ assert_nothing_raised { t1.update!(title: "new title1") }
356
+ assert_equal 1, t1.lock_version
357
+ assert_equal "new title1", t1.title
358
+ end
359
+
360
+ def test_destroy_with_lock_version_without_default_should_work_on_dirty_value_before_type_cast
361
+ ActiveRecord::Base.connection.execute("INSERT INTO lock_without_defaults(title) VALUES('title1')")
362
+ t1 = LockWithoutDefault.last
363
+
364
+ assert_equal 0, t1.lock_version
365
+ assert_nil t1.lock_version_before_type_cast
366
+
367
+ t1.lock_version = t1.lock_version
368
+
369
+ assert_equal 0, t1.lock_version
370
+ assert_equal 0, t1.lock_version_before_type_cast
371
+
372
+ assert_nothing_raised { t1.destroy! }
373
+ assert_predicate t1, :destroyed?
374
+ end
375
+
376
+ def test_lock_without_default_queries_count
377
+ t1 = LockWithoutDefault.create(title: "title1")
378
+
379
+ assert_equal "title1", t1.title
380
+ assert_equal 0, t1.lock_version
381
+
382
+ assert_queries(1) { t1.update(title: "title2") }
383
+
384
+ t1.reload
385
+ assert_equal "title2", t1.title
386
+ assert_equal 1, t1.lock_version
387
+
388
+ t2 = LockWithoutDefault.new(title: "title1")
389
+
390
+ assert_queries(1) { t2.save! }
391
+
392
+ t2.reload
393
+ assert_equal "title1", t2.title
394
+ assert_equal 0, t2.lock_version
229
395
  end
230
396
 
231
397
  def test_lock_with_custom_column_without_default_sets_version_to_zero
232
398
  t1 = LockWithCustomColumnWithoutDefault.new
399
+
233
400
  assert_equal 0, t1.custom_lock_version
234
401
  assert_nil t1.custom_lock_version_before_type_cast
235
402
 
236
403
  t1.save!
237
404
  t1.reload
405
+
406
+ assert_equal 0, t1.custom_lock_version
407
+ assert_equal 0, t1.custom_lock_version_before_type_cast
408
+ end
409
+
410
+ def test_lock_with_custom_column_without_default_should_work_with_null_in_the_database
411
+ ActiveRecord::Base.connection.execute("INSERT INTO lock_without_defaults_cust(title) VALUES('title1')")
412
+
413
+ t1 = LockWithCustomColumnWithoutDefault.last
414
+ t2 = LockWithCustomColumnWithoutDefault.find(t1.id)
415
+
416
+ assert_equal 0, t1.custom_lock_version
417
+ assert_nil t1.custom_lock_version_before_type_cast
418
+ assert_equal 0, t2.custom_lock_version
419
+ assert_nil t2.custom_lock_version_before_type_cast
420
+
421
+ t1.title = "new title1"
422
+ t2.title = "new title2"
423
+
424
+ assert_nothing_raised { t1.save! }
425
+ assert_equal 1, t1.custom_lock_version
426
+ assert_equal "new title1", t1.title
427
+
428
+ assert_raise(ActiveRecord::StaleObjectError) { t2.save! }
429
+ assert_equal 0, t2.custom_lock_version
430
+ assert_equal "new title2", t2.title
431
+ end
432
+
433
+ def test_lock_with_custom_column_without_default_queries_count
434
+ t1 = LockWithCustomColumnWithoutDefault.create(title: "title1")
435
+
436
+ assert_equal "title1", t1.title
238
437
  assert_equal 0, t1.custom_lock_version
239
- assert [0, "0"].include?(t1.custom_lock_version_before_type_cast)
438
+
439
+ assert_queries(1) { t1.update(title: "title2") }
440
+
441
+ t1.reload
442
+ assert_equal "title2", t1.title
443
+ assert_equal 1, t1.custom_lock_version
444
+
445
+ t2 = LockWithCustomColumnWithoutDefault.new(title: "title1")
446
+
447
+ assert_queries(1) { t2.save! }
448
+
449
+ t2.reload
450
+ assert_equal "title1", t2.title
451
+ assert_equal 0, t2.custom_lock_version
240
452
  end
241
453
 
242
454
  def test_readonly_attributes
243
- assert_equal Set.new([ 'name' ]), ReadonlyNameShip.readonly_attributes
455
+ assert_equal Set.new([ "name" ]), ReadonlyNameShip.readonly_attributes
244
456
 
245
- s = ReadonlyNameShip.create(:name => "unchangeable name")
457
+ s = ReadonlyNameShip.create(name: "unchangeable name")
246
458
  s.reload
247
459
  assert_equal "unchangeable name", s.name
248
460
 
@@ -261,7 +473,7 @@ class OptimisticLockingTest < ActiveRecord::TestCase
261
473
  # is nothing else being updated.
262
474
  def test_update_without_attributes_does_not_only_update_lock_version
263
475
  assert_nothing_raised do
264
- p1 = Person.create!(:first_name => 'anika')
476
+ p1 = Person.create!(first_name: "anika")
265
477
  lock_version = p1.lock_version
266
478
  p1.save
267
479
  p1.reload
@@ -269,30 +481,77 @@ class OptimisticLockingTest < ActiveRecord::TestCase
269
481
  end
270
482
  end
271
483
 
484
+ def test_counter_cache_with_touch_and_lock_version
485
+ car = Car.create!
486
+
487
+ assert_equal 0, car.wheels_count
488
+ assert_equal 0, car.lock_version
489
+
490
+ previously_updated_at = car.updated_at
491
+ previously_wheels_owned_at = car.wheels_owned_at
492
+ travel(1.second) do
493
+ Wheel.create!(wheelable: car)
494
+ end
495
+
496
+ assert_equal 1, car.reload.wheels_count
497
+ assert_equal 1, car.lock_version
498
+ assert_operator previously_updated_at, :<, car.updated_at
499
+ assert_operator previously_wheels_owned_at, :<, car.wheels_owned_at
500
+
501
+ previously_updated_at = car.updated_at
502
+ previously_wheels_owned_at = car.wheels_owned_at
503
+ travel(2.second) do
504
+ car.wheels.first.update(size: 42)
505
+ end
506
+
507
+ assert_equal 1, car.reload.wheels_count
508
+ assert_equal 2, car.lock_version
509
+ assert_operator previously_updated_at, :<, car.updated_at
510
+ assert_operator previously_wheels_owned_at, :<, car.wheels_owned_at
511
+
512
+ previously_updated_at = car.updated_at
513
+ previously_wheels_owned_at = car.wheels_owned_at
514
+ travel(3.second) do
515
+ car.wheels.first.destroy!
516
+ end
517
+
518
+ assert_equal 0, car.reload.wheels_count
519
+ assert_equal 3, car.lock_version
520
+ assert_operator previously_updated_at, :<, car.updated_at
521
+ assert_operator previously_wheels_owned_at, :<, car.wheels_owned_at
522
+
523
+ car.wheels << Wheel.create!
524
+ assert_equal 1, car.wheels_count
525
+ assert_equal 4, car.lock_version
526
+ assert_not car.lock_version_changed?
527
+ assert_nothing_raised { car.update(name: "herbie") }
528
+ end
529
+
272
530
  def test_polymorphic_destroy_with_dependencies_and_lock_version
273
531
  car = Car.create!
274
532
 
275
- assert_difference 'car.wheels.count' do
276
- car.wheels << Wheel.create!
533
+ assert_difference "car.wheels.count" do
534
+ car.wheels.create
277
535
  end
278
- assert_difference 'car.wheels.count', -1 do
536
+ assert_difference "car.wheels.count", -1 do
279
537
  car.reload.destroy
280
538
  end
281
- assert car.destroyed?
539
+ assert_predicate car, :destroyed?
282
540
  end
283
541
 
284
542
  def test_removing_has_and_belongs_to_many_associations_upon_destroy
285
- p = RichPerson.create! first_name: 'Jon'
543
+ p = RichPerson.create! first_name: "Jon"
286
544
  p.treasures.create!
287
- assert !p.treasures.empty?
545
+ assert_not_empty p.treasures
288
546
  p.destroy
289
- assert p.treasures.empty?
290
- assert RichPerson.connection.select_all("SELECT * FROM peoples_treasures WHERE rich_person_id = 1").empty?
547
+ assert_empty p.treasures
548
+ assert_empty RichPerson.connection.select_all("SELECT * FROM peoples_treasures WHERE rich_person_id = 1")
291
549
  end
292
550
 
293
551
  def test_yaml_dumping_with_lock_column
294
552
  t1 = LockWithoutDefault.new
295
- t2 = YAML.load(YAML.dump(t1))
553
+ payload = YAML.dump(t1)
554
+ t2 = YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(payload) : YAML.load(payload)
296
555
 
297
556
  assert_equal t1.attributes, t2.attributes
298
557
  end
@@ -306,7 +565,7 @@ class OptimisticLockingWithSchemaChangeTest < ActiveRecord::TestCase
306
565
  # of a test (see test_increment_counter_*).
307
566
  self.use_transactional_tests = false
308
567
 
309
- { :lock_version => Person, :custom_lock_version => LegacyThing }.each do |name, model|
568
+ { lock_version: Person, custom_lock_version: LegacyThing }.each do |name, model|
310
569
  define_method("test_increment_counter_updates_#{name}") do
311
570
  counter_test model, 1 do |id|
312
571
  model.increment_counter :test_count, id
@@ -321,7 +580,7 @@ class OptimisticLockingWithSchemaChangeTest < ActiveRecord::TestCase
321
580
 
322
581
  define_method("test_update_counters_updates_#{name}") do
323
582
  counter_test model, 1 do |id|
324
- model.update_counters id, :test_count => 1
583
+ model.update_counters id, test_count: 1
325
584
  end
326
585
  end
327
586
  end
@@ -329,13 +588,13 @@ class OptimisticLockingWithSchemaChangeTest < ActiveRecord::TestCase
329
588
  # See Lighthouse ticket #1966
330
589
  def test_destroy_dependents
331
590
  # Establish dependent relationship between Person and PersonalLegacyThing
332
- add_counter_column_to(Person, 'personal_legacy_things_count')
591
+ add_counter_column_to(Person, "personal_legacy_things_count")
333
592
  PersonalLegacyThing.reset_column_information
334
593
 
335
594
  # Make sure that counter incrementing doesn't cause problems
336
- p1 = Person.new(:first_name => 'fjord')
595
+ p1 = Person.new(first_name: "fjord")
337
596
  p1.save!
338
- t = PersonalLegacyThing.new(:person => p1)
597
+ t = PersonalLegacyThing.new(person: p1)
339
598
  t.save!
340
599
  p1.reload
341
600
  assert_equal 1, p1.personal_legacy_things_count
@@ -344,14 +603,38 @@ class OptimisticLockingWithSchemaChangeTest < ActiveRecord::TestCase
344
603
  assert_raises(ActiveRecord::RecordNotFound) { Person.find(p1.id) }
345
604
  assert_raises(ActiveRecord::RecordNotFound) { PersonalLegacyThing.find(t.id) }
346
605
  ensure
347
- remove_counter_column_from(Person, 'personal_legacy_things_count')
606
+ remove_counter_column_from(Person, "personal_legacy_things_count")
348
607
  PersonalLegacyThing.reset_column_information
349
608
  end
350
609
 
351
- private
610
+ def test_destroy_existing_object_with_locking_column_value_null_in_the_database
611
+ ActiveRecord::Base.connection.execute("INSERT INTO lock_without_defaults(title) VALUES('title1')")
612
+ t1 = LockWithoutDefault.last
613
+
614
+ assert_equal 0, t1.lock_version
615
+ assert_nil t1.lock_version_before_type_cast
616
+
617
+ t1.destroy
618
+
619
+ assert_predicate t1, :destroyed?
620
+ end
621
+
622
+ def test_destroy_stale_object
623
+ t1 = LockWithoutDefault.create!(title: "title1")
624
+ stale_object = LockWithoutDefault.find(t1.id)
625
+
626
+ t1.update!(title: "title2")
352
627
 
353
- def add_counter_column_to(model, col='test_count')
354
- model.connection.add_column model.table_name, col, :integer, :null => false, :default => 0
628
+ assert_raises(ActiveRecord::StaleObjectError) do
629
+ stale_object.destroy!
630
+ end
631
+
632
+ assert_not_predicate stale_object, :destroyed?
633
+ end
634
+
635
+ private
636
+ def add_counter_column_to(model, col = "test_count")
637
+ model.connection.add_column model.table_name, col, :integer, null: false, default: 0
355
638
  model.reset_column_information
356
639
  end
357
640
 
@@ -364,17 +647,16 @@ class OptimisticLockingWithSchemaChangeTest < ActiveRecord::TestCase
364
647
  add_counter_column_to(model)
365
648
  object = model.first
366
649
  assert_equal 0, object.test_count
367
- assert_equal 0, object.send(model.locking_column)
650
+ assert_equal 0, object.public_send(model.locking_column)
368
651
  yield object.id
369
652
  object.reload
370
653
  assert_equal expected_count, object.test_count
371
- assert_equal 1, object.send(model.locking_column)
654
+ assert_equal 1, object.public_send(model.locking_column)
372
655
  ensure
373
656
  remove_counter_column_from(model)
374
657
  end
375
658
  end
376
659
 
377
-
378
660
  # TODO: test against the generated SQL since testing locking behavior itself
379
661
  # is so cumbersome. Will deadlock Ruby threads if the underlying db.execute
380
662
  # blocks, so separate script called by Kernel#system is needed.
@@ -411,34 +693,48 @@ unless in_memory_db?
411
693
  end
412
694
  end
413
695
 
414
- # Locking a record reloads it.
415
- def test_sane_lock_method
696
+ def test_lock_does_not_raise_when_the_object_is_not_dirty
697
+ person = Person.find 1
416
698
  assert_nothing_raised do
417
- Person.transaction do
418
- person = Person.find 1
419
- old, person.first_name = person.first_name, 'fooman'
420
- person.lock!
421
- assert_equal old, person.first_name
699
+ person.lock!
700
+ end
701
+ end
702
+
703
+ def test_lock_raises_when_the_record_is_dirty
704
+ person = Person.find 1
705
+ person.first_name = "fooman"
706
+ assert_raises(RuntimeError) do
707
+ person.lock!
708
+ end
709
+ end
710
+
711
+ def test_locking_in_after_save_callback
712
+ assert_nothing_raised do
713
+ frog = ::Frog.create(name: "Old Frog")
714
+ frog.name = "New Frog"
715
+ assert_not_deprecated do
716
+ frog.save!
422
717
  end
423
718
  end
424
719
  end
425
720
 
426
721
  def test_with_lock_commits_transaction
722
+ puts "Inside test_with_lock_commits_transaction"
427
723
  person = Person.find 1
428
724
  person.with_lock do
429
- person.first_name = 'fooman'
725
+ person.first_name = "fooman"
430
726
  person.save!
431
727
  end
432
- assert_equal 'fooman', person.reload.first_name
728
+ assert_equal "fooman", person.reload.first_name
433
729
  end
434
730
 
435
731
  def test_with_lock_rolls_back_transaction
436
732
  person = Person.find 1
437
733
  old = person.first_name
438
734
  person.with_lock do
439
- person.first_name = 'fooman'
735
+ person.first_name = "fooman"
440
736
  person.save!
441
- raise 'oops'
737
+ raise "oops"
442
738
  end rescue nil
443
739
  assert_equal old, person.reload.first_name
444
740
  end
@@ -448,46 +744,44 @@ unless in_memory_db?
448
744
  Person.transaction do
449
745
  person = Person.find(1)
450
746
  assert_sql(/LIMIT \$?\d FOR SHARE NOWAIT/) do
451
- person.lock!('FOR SHARE NOWAIT')
747
+ person.lock!("FOR SHARE NOWAIT")
452
748
  end
453
749
  end
454
750
  end
455
751
  end
456
752
 
457
- if current_adapter?(:PostgreSQLAdapter, :OracleAdapter)
458
- def test_no_locks_no_wait
459
- first, second = duel { Person.find 1 }
460
- assert first.end > second.end
461
- end
753
+ def test_no_locks_no_wait
754
+ first, second = duel { Person.find 1 }
755
+ assert first.end > second.end
756
+ end
462
757
 
463
- protected
464
- def duel(zzz = 5)
465
- t0, t1, t2, t3 = nil, nil, nil, nil
466
-
467
- a = Thread.new do
468
- t0 = Time.now
469
- Person.transaction do
470
- yield
471
- sleep zzz # block thread 2 for zzz seconds
472
- end
473
- t1 = Time.now
474
- end
758
+ private
759
+ def duel(zzz = 5)
760
+ t0, t1, t2, t3 = nil, nil, nil, nil
475
761
 
476
- b = Thread.new do
477
- sleep zzz / 2.0 # ensure thread 1 tx starts first
478
- t2 = Time.now
479
- Person.transaction { yield }
480
- t3 = Time.now
762
+ a = Thread.new do
763
+ t0 = Time.now
764
+ Person.transaction do
765
+ yield
766
+ sleep zzz # block thread 2 for zzz seconds
481
767
  end
768
+ t1 = Time.now
769
+ end
482
770
 
483
- a.join
484
- b.join
485
-
486
- assert t1 > t0 + zzz
487
- assert t2 > t0
488
- assert t3 > t2
489
- [t0.to_f..t1.to_f, t2.to_f..t3.to_f]
771
+ b = Thread.new do
772
+ sleep zzz / 2.0 # ensure thread 1 tx starts first
773
+ t2 = Time.now
774
+ Person.transaction { yield }
775
+ t3 = Time.now
490
776
  end
491
- end
777
+
778
+ a.join
779
+ b.join
780
+
781
+ assert t1 > t0 + zzz
782
+ assert t2 > t0
783
+ assert t3 > t2
784
+ [t0.to_f..t1.to_f, t2.to_f..t3.to_f]
785
+ end
492
786
  end
493
787
  end