activerecord 6.1.7 → 7.2.2

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 (333) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +616 -1290
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +31 -31
  5. data/examples/performance.rb +2 -2
  6. data/lib/active_record/aggregations.rb +17 -14
  7. data/lib/active_record/association_relation.rb +2 -12
  8. data/lib/active_record/associations/alias_tracker.rb +25 -19
  9. data/lib/active_record/associations/association.rb +60 -21
  10. data/lib/active_record/associations/association_scope.rb +17 -12
  11. data/lib/active_record/associations/belongs_to_association.rb +37 -11
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -4
  13. data/lib/active_record/associations/builder/association.rb +11 -5
  14. data/lib/active_record/associations/builder/belongs_to.rb +41 -14
  15. data/lib/active_record/associations/builder/collection_association.rb +10 -3
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -7
  17. data/lib/active_record/associations/builder/has_many.rb +4 -4
  18. data/lib/active_record/associations/builder/has_one.rb +4 -4
  19. data/lib/active_record/associations/builder/singular_association.rb +6 -2
  20. data/lib/active_record/associations/collection_association.rb +46 -36
  21. data/lib/active_record/associations/collection_proxy.rb +44 -16
  22. data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
  23. data/lib/active_record/associations/errors.rb +265 -0
  24. data/lib/active_record/associations/foreign_association.rb +10 -3
  25. data/lib/active_record/associations/has_many_association.rb +29 -19
  26. data/lib/active_record/associations/has_many_through_association.rb +19 -8
  27. data/lib/active_record/associations/has_one_association.rb +20 -10
  28. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  29. data/lib/active_record/associations/join_dependency/join_association.rb +30 -27
  30. data/lib/active_record/associations/join_dependency.rb +28 -20
  31. data/lib/active_record/associations/nested_error.rb +47 -0
  32. data/lib/active_record/associations/preloader/association.rb +212 -53
  33. data/lib/active_record/associations/preloader/batch.rb +48 -0
  34. data/lib/active_record/associations/preloader/branch.rb +153 -0
  35. data/lib/active_record/associations/preloader/through_association.rb +50 -16
  36. data/lib/active_record/associations/preloader.rb +50 -121
  37. data/lib/active_record/associations/singular_association.rb +15 -3
  38. data/lib/active_record/associations/through_association.rb +25 -14
  39. data/lib/active_record/associations.rb +429 -522
  40. data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
  41. data/lib/active_record/attribute_assignment.rb +1 -5
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +24 -2
  43. data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
  44. data/lib/active_record/attribute_methods/dirty.rb +73 -22
  45. data/lib/active_record/attribute_methods/primary_key.rb +47 -27
  46. data/lib/active_record/attribute_methods/query.rb +31 -19
  47. data/lib/active_record/attribute_methods/read.rb +14 -11
  48. data/lib/active_record/attribute_methods/serialization.rb +174 -37
  49. data/lib/active_record/attribute_methods/time_zone_conversion.rb +15 -9
  50. data/lib/active_record/attribute_methods/write.rb +12 -15
  51. data/lib/active_record/attribute_methods.rb +164 -52
  52. data/lib/active_record/attributes.rb +57 -54
  53. data/lib/active_record/autosave_association.rb +74 -57
  54. data/lib/active_record/base.rb +27 -5
  55. data/lib/active_record/callbacks.rb +19 -35
  56. data/lib/active_record/coders/column_serializer.rb +61 -0
  57. data/lib/active_record/coders/json.rb +1 -1
  58. data/lib/active_record/coders/yaml_column.rb +70 -46
  59. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +284 -0
  60. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
  61. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +79 -0
  62. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +325 -604
  63. data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
  64. data/lib/active_record/connection_adapters/abstract/database_statements.rb +199 -60
  65. data/lib/active_record/connection_adapters/abstract/query_cache.rb +230 -64
  66. data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -131
  67. data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
  68. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +21 -20
  69. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +186 -31
  70. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
  71. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +378 -143
  72. data/lib/active_record/connection_adapters/abstract/transaction.rb +361 -76
  73. data/lib/active_record/connection_adapters/abstract_adapter.rb +624 -163
  74. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +348 -165
  75. data/lib/active_record/connection_adapters/column.rb +13 -0
  76. data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
  77. data/lib/active_record/connection_adapters/mysql/database_statements.rb +29 -130
  78. data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -55
  79. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
  80. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
  81. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
  82. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +45 -14
  83. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
  84. data/lib/active_record/connection_adapters/mysql2_adapter.rb +107 -68
  85. data/lib/active_record/connection_adapters/pool_config.rb +26 -16
  86. data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
  87. data/lib/active_record/connection_adapters/postgresql/column.rb +30 -1
  88. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +114 -54
  89. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
  94. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
  95. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
  96. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +12 -3
  97. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
  100. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
  101. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  102. data/lib/active_record/connection_adapters/postgresql/quoting.rb +137 -104
  103. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +28 -0
  104. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +92 -2
  105. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +173 -3
  106. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -0
  107. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +403 -77
  108. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
  109. data/lib/active_record/connection_adapters/postgresql_adapter.rb +520 -253
  110. data/lib/active_record/connection_adapters/schema_cache.rb +326 -102
  111. data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
  112. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +78 -55
  113. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +68 -54
  114. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  115. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +20 -0
  116. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
  117. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +66 -22
  118. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +372 -130
  119. data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
  120. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
  121. data/lib/active_record/connection_adapters/trilogy_adapter.rb +229 -0
  122. data/lib/active_record/connection_adapters.rb +130 -6
  123. data/lib/active_record/connection_handling.rb +132 -146
  124. data/lib/active_record/core.rb +310 -253
  125. data/lib/active_record/counter_cache.rb +68 -34
  126. data/lib/active_record/database_configurations/connection_url_resolver.rb +10 -4
  127. data/lib/active_record/database_configurations/database_config.rb +34 -10
  128. data/lib/active_record/database_configurations/hash_config.rb +107 -31
  129. data/lib/active_record/database_configurations/url_config.rb +38 -13
  130. data/lib/active_record/database_configurations.rb +96 -60
  131. data/lib/active_record/delegated_type.rb +90 -20
  132. data/lib/active_record/deprecator.rb +7 -0
  133. data/lib/active_record/destroy_association_async_job.rb +4 -2
  134. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  135. data/lib/active_record/dynamic_matchers.rb +3 -3
  136. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  137. data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
  138. data/lib/active_record/encryption/cipher.rb +53 -0
  139. data/lib/active_record/encryption/config.rb +68 -0
  140. data/lib/active_record/encryption/configurable.rb +60 -0
  141. data/lib/active_record/encryption/context.rb +42 -0
  142. data/lib/active_record/encryption/contexts.rb +76 -0
  143. data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
  144. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  145. data/lib/active_record/encryption/encryptable_record.rb +230 -0
  146. data/lib/active_record/encryption/encrypted_attribute_type.rb +175 -0
  147. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  148. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  149. data/lib/active_record/encryption/encryptor.rb +170 -0
  150. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  151. data/lib/active_record/encryption/errors.rb +15 -0
  152. data/lib/active_record/encryption/extended_deterministic_queries.rb +157 -0
  153. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
  154. data/lib/active_record/encryption/key.rb +28 -0
  155. data/lib/active_record/encryption/key_generator.rb +53 -0
  156. data/lib/active_record/encryption/key_provider.rb +46 -0
  157. data/lib/active_record/encryption/message.rb +33 -0
  158. data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
  159. data/lib/active_record/encryption/message_serializer.rb +96 -0
  160. data/lib/active_record/encryption/null_encryptor.rb +25 -0
  161. data/lib/active_record/encryption/properties.rb +76 -0
  162. data/lib/active_record/encryption/read_only_null_encryptor.rb +28 -0
  163. data/lib/active_record/encryption/scheme.rb +100 -0
  164. data/lib/active_record/encryption.rb +58 -0
  165. data/lib/active_record/enum.rb +170 -62
  166. data/lib/active_record/errors.rb +210 -27
  167. data/lib/active_record/explain.rb +21 -12
  168. data/lib/active_record/explain_registry.rb +11 -6
  169. data/lib/active_record/explain_subscriber.rb +1 -1
  170. data/lib/active_record/fixture_set/file.rb +15 -1
  171. data/lib/active_record/fixture_set/model_metadata.rb +14 -4
  172. data/lib/active_record/fixture_set/render_context.rb +2 -0
  173. data/lib/active_record/fixture_set/table_row.rb +70 -14
  174. data/lib/active_record/fixture_set/table_rows.rb +4 -4
  175. data/lib/active_record/fixtures.rb +179 -112
  176. data/lib/active_record/future_result.rb +178 -0
  177. data/lib/active_record/gem_version.rb +4 -4
  178. data/lib/active_record/inheritance.rb +85 -31
  179. data/lib/active_record/insert_all.rb +148 -32
  180. data/lib/active_record/integration.rb +14 -10
  181. data/lib/active_record/internal_metadata.rb +123 -23
  182. data/lib/active_record/legacy_yaml_adapter.rb +2 -39
  183. data/lib/active_record/locking/optimistic.rb +43 -27
  184. data/lib/active_record/locking/pessimistic.rb +15 -6
  185. data/lib/active_record/log_subscriber.rb +41 -29
  186. data/lib/active_record/marshalling.rb +59 -0
  187. data/lib/active_record/message_pack.rb +124 -0
  188. data/lib/active_record/middleware/database_selector/resolver.rb +10 -10
  189. data/lib/active_record/middleware/database_selector.rb +23 -13
  190. data/lib/active_record/middleware/shard_selector.rb +62 -0
  191. data/lib/active_record/migration/command_recorder.rb +113 -16
  192. data/lib/active_record/migration/compatibility.rb +235 -46
  193. data/lib/active_record/migration/default_strategy.rb +22 -0
  194. data/lib/active_record/migration/execution_strategy.rb +19 -0
  195. data/lib/active_record/migration/join_table.rb +1 -1
  196. data/lib/active_record/migration/pending_migration_connection.rb +21 -0
  197. data/lib/active_record/migration.rb +374 -177
  198. data/lib/active_record/model_schema.rb +145 -158
  199. data/lib/active_record/nested_attributes.rb +61 -23
  200. data/lib/active_record/no_touching.rb +3 -3
  201. data/lib/active_record/normalization.rb +163 -0
  202. data/lib/active_record/persistence.rb +282 -283
  203. data/lib/active_record/promise.rb +84 -0
  204. data/lib/active_record/query_cache.rb +18 -25
  205. data/lib/active_record/query_logs.rb +189 -0
  206. data/lib/active_record/query_logs_formatter.rb +41 -0
  207. data/lib/active_record/querying.rb +44 -9
  208. data/lib/active_record/railtie.rb +229 -71
  209. data/lib/active_record/railties/controller_runtime.rb +25 -11
  210. data/lib/active_record/railties/databases.rake +189 -256
  211. data/lib/active_record/railties/job_runtime.rb +23 -0
  212. data/lib/active_record/readonly_attributes.rb +41 -3
  213. data/lib/active_record/reflection.rb +332 -103
  214. data/lib/active_record/relation/batches/batch_enumerator.rb +38 -9
  215. data/lib/active_record/relation/batches.rb +200 -65
  216. data/lib/active_record/relation/calculations.rb +301 -112
  217. data/lib/active_record/relation/delegation.rb +33 -22
  218. data/lib/active_record/relation/finder_methods.rb +123 -52
  219. data/lib/active_record/relation/merger.rb +26 -19
  220. data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
  221. data/lib/active_record/relation/predicate_builder/association_query_value.rb +38 -4
  222. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -7
  223. data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
  224. data/lib/active_record/relation/predicate_builder.rb +29 -22
  225. data/lib/active_record/relation/query_attribute.rb +30 -12
  226. data/lib/active_record/relation/query_methods.rb +870 -163
  227. data/lib/active_record/relation/record_fetch_warning.rb +10 -9
  228. data/lib/active_record/relation/spawn_methods.rb +7 -6
  229. data/lib/active_record/relation/where_clause.rb +15 -36
  230. data/lib/active_record/relation.rb +736 -145
  231. data/lib/active_record/result.rb +67 -54
  232. data/lib/active_record/runtime_registry.rb +71 -13
  233. data/lib/active_record/sanitization.rb +84 -34
  234. data/lib/active_record/schema.rb +39 -23
  235. data/lib/active_record/schema_dumper.rb +90 -31
  236. data/lib/active_record/schema_migration.rb +74 -23
  237. data/lib/active_record/scoping/default.rb +72 -15
  238. data/lib/active_record/scoping/named.rb +6 -13
  239. data/lib/active_record/scoping.rb +65 -34
  240. data/lib/active_record/secure_password.rb +60 -0
  241. data/lib/active_record/secure_token.rb +21 -3
  242. data/lib/active_record/serialization.rb +6 -1
  243. data/lib/active_record/signed_id.rb +30 -9
  244. data/lib/active_record/statement_cache.rb +7 -7
  245. data/lib/active_record/store.rb +10 -10
  246. data/lib/active_record/suppressor.rb +13 -15
  247. data/lib/active_record/table_metadata.rb +7 -3
  248. data/lib/active_record/tasks/database_tasks.rb +288 -149
  249. data/lib/active_record/tasks/mysql_database_tasks.rb +16 -7
  250. data/lib/active_record/tasks/postgresql_database_tasks.rb +35 -26
  251. data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -7
  252. data/lib/active_record/test_databases.rb +1 -1
  253. data/lib/active_record/test_fixtures.rb +173 -155
  254. data/lib/active_record/testing/query_assertions.rb +121 -0
  255. data/lib/active_record/timestamp.rb +32 -19
  256. data/lib/active_record/token_for.rb +123 -0
  257. data/lib/active_record/touch_later.rb +12 -7
  258. data/lib/active_record/transaction.rb +132 -0
  259. data/lib/active_record/transactions.rb +118 -41
  260. data/lib/active_record/translation.rb +3 -5
  261. data/lib/active_record/type/adapter_specific_registry.rb +32 -14
  262. data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
  263. data/lib/active_record/type/internal/timezone.rb +7 -2
  264. data/lib/active_record/type/serialized.rb +9 -7
  265. data/lib/active_record/type/time.rb +4 -0
  266. data/lib/active_record/type/type_map.rb +17 -20
  267. data/lib/active_record/type.rb +1 -2
  268. data/lib/active_record/type_caster/connection.rb +4 -4
  269. data/lib/active_record/validations/absence.rb +1 -1
  270. data/lib/active_record/validations/associated.rb +13 -7
  271. data/lib/active_record/validations/numericality.rb +5 -4
  272. data/lib/active_record/validations/presence.rb +5 -28
  273. data/lib/active_record/validations/uniqueness.rb +65 -15
  274. data/lib/active_record/validations.rb +12 -5
  275. data/lib/active_record/version.rb +1 -1
  276. data/lib/active_record.rb +444 -32
  277. data/lib/arel/alias_predication.rb +1 -1
  278. data/lib/arel/attributes/attribute.rb +0 -8
  279. data/lib/arel/collectors/bind.rb +2 -0
  280. data/lib/arel/collectors/composite.rb +7 -0
  281. data/lib/arel/collectors/sql_string.rb +1 -1
  282. data/lib/arel/collectors/substitute_binds.rb +1 -1
  283. data/lib/arel/crud.rb +28 -22
  284. data/lib/arel/delete_manager.rb +18 -4
  285. data/lib/arel/errors.rb +10 -0
  286. data/lib/arel/factory_methods.rb +4 -0
  287. data/lib/arel/filter_predications.rb +9 -0
  288. data/lib/arel/insert_manager.rb +2 -3
  289. data/lib/arel/nodes/binary.rb +6 -7
  290. data/lib/arel/nodes/bound_sql_literal.rb +65 -0
  291. data/lib/arel/nodes/casted.rb +1 -1
  292. data/lib/arel/nodes/cte.rb +36 -0
  293. data/lib/arel/nodes/delete_statement.rb +12 -13
  294. data/lib/arel/nodes/filter.rb +10 -0
  295. data/lib/arel/nodes/fragments.rb +35 -0
  296. data/lib/arel/nodes/function.rb +1 -0
  297. data/lib/arel/nodes/homogeneous_in.rb +1 -9
  298. data/lib/arel/nodes/insert_statement.rb +2 -2
  299. data/lib/arel/nodes/leading_join.rb +8 -0
  300. data/lib/arel/nodes/{and.rb → nary.rb} +9 -2
  301. data/lib/arel/nodes/node.rb +115 -5
  302. data/lib/arel/nodes/select_core.rb +2 -2
  303. data/lib/arel/nodes/select_statement.rb +2 -2
  304. data/lib/arel/nodes/sql_literal.rb +13 -0
  305. data/lib/arel/nodes/table_alias.rb +4 -0
  306. data/lib/arel/nodes/update_statement.rb +8 -3
  307. data/lib/arel/nodes.rb +7 -2
  308. data/lib/arel/predications.rb +14 -4
  309. data/lib/arel/select_manager.rb +11 -5
  310. data/lib/arel/table.rb +9 -6
  311. data/lib/arel/tree_manager.rb +8 -15
  312. data/lib/arel/update_manager.rb +20 -5
  313. data/lib/arel/visitors/dot.rb +81 -90
  314. data/lib/arel/visitors/mysql.rb +23 -5
  315. data/lib/arel/visitors/postgresql.rb +1 -22
  316. data/lib/arel/visitors/sqlite.rb +25 -0
  317. data/lib/arel/visitors/to_sql.rb +170 -36
  318. data/lib/arel/visitors/visitor.rb +2 -2
  319. data/lib/arel.rb +23 -4
  320. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  321. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  322. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
  323. data/lib/rails/generators/active_record/migration.rb +3 -1
  324. data/lib/rails/generators/active_record/model/USAGE +113 -0
  325. data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
  326. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
  327. data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
  328. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  329. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  330. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  331. metadata +103 -17
  332. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
  333. data/lib/active_record/null_relation.rb +0 -67
@@ -7,9 +7,10 @@ require "active_support/core_ext/array/access"
7
7
  require "active_support/core_ext/enumerable"
8
8
  require "active_support/core_ext/module/attribute_accessors"
9
9
  require "active_support/actionable_error"
10
+ require "active_record/migration/pending_migration_connection"
10
11
 
11
12
  module ActiveRecord
12
- class MigrationError < ActiveRecordError #:nodoc:
13
+ class MigrationError < ActiveRecordError # :nodoc:
13
14
  def initialize(message = nil)
14
15
  message = "\n\n#{message}\n\n" if message
15
16
  super
@@ -20,7 +21,7 @@ module ActiveRecord
20
21
  # For example the following migration is not reversible.
21
22
  # Rolling back this migration will raise an ActiveRecord::IrreversibleMigration error.
22
23
  #
23
- # class IrreversibleMigrationExample < ActiveRecord::Migration[6.0]
24
+ # class IrreversibleMigrationExample < ActiveRecord::Migration[7.2]
24
25
  # def change
25
26
  # create_table :distributors do |t|
26
27
  # t.string :zipcode
@@ -38,7 +39,7 @@ module ActiveRecord
38
39
  #
39
40
  # 1. Define <tt>#up</tt> and <tt>#down</tt> methods instead of <tt>#change</tt>:
40
41
  #
41
- # class ReversibleMigrationExample < ActiveRecord::Migration[6.0]
42
+ # class ReversibleMigrationExample < ActiveRecord::Migration[7.2]
42
43
  # def up
43
44
  # create_table :distributors do |t|
44
45
  # t.string :zipcode
@@ -63,7 +64,7 @@ module ActiveRecord
63
64
  #
64
65
  # 2. Use the #reversible method in <tt>#change</tt> method:
65
66
  #
66
- # class ReversibleMigrationExample < ActiveRecord::Migration[6.0]
67
+ # class ReversibleMigrationExample < ActiveRecord::Migration[7.2]
67
68
  # def change
68
69
  # create_table :distributors do |t|
69
70
  # t.string :zipcode
@@ -90,7 +91,7 @@ module ActiveRecord
90
91
  class IrreversibleMigration < MigrationError
91
92
  end
92
93
 
93
- class DuplicateMigrationVersionError < MigrationError #:nodoc:
94
+ class DuplicateMigrationVersionError < MigrationError # :nodoc:
94
95
  def initialize(version = nil)
95
96
  if version
96
97
  super("Multiple migrations have the version number #{version}.")
@@ -100,7 +101,7 @@ module ActiveRecord
100
101
  end
101
102
  end
102
103
 
103
- class DuplicateMigrationNameError < MigrationError #:nodoc:
104
+ class DuplicateMigrationNameError < MigrationError # :nodoc:
104
105
  def initialize(name = nil)
105
106
  if name
106
107
  super("Multiple migrations have the name #{name}.")
@@ -110,7 +111,7 @@ module ActiveRecord
110
111
  end
111
112
  end
112
113
 
113
- class UnknownMigrationVersionError < MigrationError #:nodoc:
114
+ class UnknownMigrationVersionError < MigrationError # :nodoc:
114
115
  def initialize(version = nil)
115
116
  if version
116
117
  super("No migration with version number #{version}.")
@@ -120,7 +121,7 @@ module ActiveRecord
120
121
  end
121
122
  end
122
123
 
123
- class IllegalMigrationNameError < MigrationError #:nodoc:
124
+ class IllegalMigrationNameError < MigrationError # :nodoc:
124
125
  def initialize(name = nil)
125
126
  if name
126
127
  super("Illegal name for migration file: #{name}\n\t(only lower case letters, numbers, and '_' allowed).")
@@ -130,42 +131,63 @@ module ActiveRecord
130
131
  end
131
132
  end
132
133
 
133
- class PendingMigrationError < MigrationError #:nodoc:
134
+ class InvalidMigrationTimestampError < MigrationError # :nodoc:
135
+ def initialize(version = nil, name = nil)
136
+ if version && name
137
+ super(<<~MSG)
138
+ Invalid timestamp #{version} for migration file: #{name}.
139
+ Timestamp must be in form YYYYMMDDHHMMSS, and less than #{(Time.now.utc + 1.day).strftime("%Y%m%d%H%M%S")}.
140
+ MSG
141
+ else
142
+ super(<<~MSG)
143
+ Invalid timestamp for migration.
144
+ Timestamp must be in form YYYYMMDDHHMMSS, and less than #{(Time.now.utc + 1.day).strftime("%Y%m%d%H%M%S")}.
145
+ MSG
146
+ end
147
+ end
148
+ end
149
+
150
+ class PendingMigrationError < MigrationError # :nodoc:
134
151
  include ActiveSupport::ActionableError
135
152
 
136
153
  action "Run pending migrations" do
137
154
  ActiveRecord::Tasks::DatabaseTasks.migrate
138
155
 
139
- if ActiveRecord::Base.dump_schema_after_migration
140
- ActiveRecord::Tasks::DatabaseTasks.dump_schema(
141
- ActiveRecord::Base.connection_db_config
142
- )
156
+ if ActiveRecord.dump_schema_after_migration
157
+ connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection
158
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema(connection.pool.db_config)
143
159
  end
144
160
  end
145
161
 
146
- def initialize(message = nil)
147
- super(message || detailed_migration_message)
162
+ def initialize(message = nil, pending_migrations: nil)
163
+ if pending_migrations.nil?
164
+ pending_migrations = connection_pool.migration_context.open.pending_migrations
165
+ end
166
+
167
+ super(message || detailed_migration_message(pending_migrations))
148
168
  end
149
169
 
150
170
  private
151
- def detailed_migration_message
171
+ def detailed_migration_message(pending_migrations)
152
172
  message = "Migrations are pending. To resolve this issue, run:\n\n bin/rails db:migrate"
153
- message += " RAILS_ENV=#{::Rails.env}" if defined?(Rails.env)
173
+ message += " RAILS_ENV=#{::Rails.env}" if defined?(Rails.env) && !Rails.env.local?
154
174
  message += "\n\n"
155
175
 
156
- pending_migrations = ActiveRecord::Base.connection.migration_context.open.pending_migrations
157
-
158
176
  message += "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}\n\n"
159
177
 
160
178
  pending_migrations.each do |pending_migration|
161
- message += "#{pending_migration.basename}\n"
179
+ message += "#{pending_migration.filename}\n"
162
180
  end
163
181
 
164
182
  message
165
183
  end
184
+
185
+ def connection_pool
186
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool
187
+ end
166
188
  end
167
189
 
168
- class ConcurrentMigrationError < MigrationError #:nodoc:
190
+ class ConcurrentMigrationError < MigrationError # :nodoc:
169
191
  DEFAULT_MESSAGE = "Cannot run migrations because another migration process is currently running."
170
192
  RELEASE_LOCK_FAILED_MESSAGE = "Failed to release advisory lock"
171
193
 
@@ -174,7 +196,7 @@ module ActiveRecord
174
196
  end
175
197
  end
176
198
 
177
- class NoEnvironmentInSchemaError < MigrationError #:nodoc:
199
+ class NoEnvironmentInSchemaError < MigrationError # :nodoc:
178
200
  def initialize
179
201
  msg = "Environment data not found in the schema. To resolve this issue, run: \n\n bin/rails db:environment:set"
180
202
  if defined?(Rails.env)
@@ -185,7 +207,7 @@ module ActiveRecord
185
207
  end
186
208
  end
187
209
 
188
- class ProtectedEnvironmentError < ActiveRecordError #:nodoc:
210
+ class ProtectedEnvironmentError < ActiveRecordError # :nodoc:
189
211
  def initialize(env = "production")
190
212
  msg = +"You are attempting to run a destructive action against your '#{env}' database.\n"
191
213
  msg << "If you are sure you want to continue, run the same command with the environment variable:\n"
@@ -228,7 +250,7 @@ module ActiveRecord
228
250
  #
229
251
  # Example of a simple migration:
230
252
  #
231
- # class AddSsl < ActiveRecord::Migration[6.0]
253
+ # class AddSsl < ActiveRecord::Migration[7.2]
232
254
  # def up
233
255
  # add_column :accounts, :ssl_enabled, :boolean, default: true
234
256
  # end
@@ -248,7 +270,7 @@ module ActiveRecord
248
270
  #
249
271
  # Example of a more complex migration that also needs to initialize data:
250
272
  #
251
- # class AddSystemSettings < ActiveRecord::Migration[6.0]
273
+ # class AddSystemSettings < ActiveRecord::Migration[7.2]
252
274
  # def up
253
275
  # create_table :system_settings do |t|
254
276
  # t.string :name
@@ -326,7 +348,7 @@ module ActiveRecord
326
348
  # details.
327
349
  # * <tt>change_table(name, options)</tt>: Allows to make column alterations to
328
350
  # the table called +name+. It makes the table object available to a block that
329
- # can then add/remove columns, indexes or foreign keys to it.
351
+ # can then add/remove columns, indexes, or foreign keys to it.
330
352
  # * <tt>rename_column(table_name, column_name, new_column_name)</tt>: Renames
331
353
  # a column but keeps the type and content.
332
354
  # * <tt>rename_index(table_name, old_name, new_name)</tt>: Renames an index.
@@ -356,15 +378,16 @@ module ActiveRecord
356
378
  # == Irreversible transformations
357
379
  #
358
380
  # Some transformations are destructive in a manner that cannot be reversed.
359
- # Migrations of that kind should raise an <tt>ActiveRecord::IrreversibleMigration</tt>
381
+ # Migrations of that kind should raise an ActiveRecord::IrreversibleMigration
360
382
  # exception in their +down+ method.
361
383
  #
362
- # == Running migrations from within Rails
384
+ # == Running migrations from within \Rails
363
385
  #
364
- # The Rails package has several tools to help create and apply migrations.
386
+ # The \Rails package has several tools to help create and apply migrations.
365
387
  #
366
388
  # To generate a new migration, you can use
367
- # bin/rails generate migration MyNewMigration
389
+ #
390
+ # $ bin/rails generate migration MyNewMigration
368
391
  #
369
392
  # where MyNewMigration is the name of your migration. The generator will
370
393
  # create an empty migration file <tt>timestamp_my_new_migration.rb</tt>
@@ -373,10 +396,10 @@ module ActiveRecord
373
396
  #
374
397
  # There is a special syntactic shortcut to generate migrations that add fields to a table.
375
398
  #
376
- # bin/rails generate migration add_fieldname_to_tablename fieldname:string
399
+ # $ bin/rails generate migration add_fieldname_to_tablename fieldname:string
377
400
  #
378
401
  # This will generate the file <tt>timestamp_add_fieldname_to_tablename.rb</tt>, which will look like this:
379
- # class AddFieldnameToTablename < ActiveRecord::Migration[6.0]
402
+ # class AddFieldnameToTablename < ActiveRecord::Migration[7.2]
380
403
  # def change
381
404
  # add_column :tablenames, :fieldname, :string
382
405
  # end
@@ -395,14 +418,14 @@ module ActiveRecord
395
418
  # wish to rollback last few migrations. <tt>bin/rails db:rollback STEP=2</tt> will rollback
396
419
  # the latest two migrations.
397
420
  #
398
- # If any of the migrations throw an <tt>ActiveRecord::IrreversibleMigration</tt> exception,
421
+ # If any of the migrations throw an ActiveRecord::IrreversibleMigration exception,
399
422
  # that step will fail and you'll have some manual work to do.
400
423
  #
401
424
  # == More examples
402
425
  #
403
426
  # Not all migrations change the schema. Some just fix the data:
404
427
  #
405
- # class RemoveEmptyTags < ActiveRecord::Migration[6.0]
428
+ # class RemoveEmptyTags < ActiveRecord::Migration[7.2]
406
429
  # def up
407
430
  # Tag.all.each { |tag| tag.destroy if tag.pages.empty? }
408
431
  # end
@@ -415,7 +438,7 @@ module ActiveRecord
415
438
  #
416
439
  # Others remove columns when they migrate up instead of down:
417
440
  #
418
- # class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[6.0]
441
+ # class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[7.2]
419
442
  # def up
420
443
  # remove_column :items, :incomplete_items_count
421
444
  # remove_column :items, :completed_items_count
@@ -429,7 +452,7 @@ module ActiveRecord
429
452
  #
430
453
  # And sometimes you need to do something in SQL not abstracted directly by migrations:
431
454
  #
432
- # class MakeJoinUnique < ActiveRecord::Migration[6.0]
455
+ # class MakeJoinUnique < ActiveRecord::Migration[7.2]
433
456
  # def up
434
457
  # execute "ALTER TABLE `pages_linked_pages` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`)"
435
458
  # end
@@ -446,7 +469,7 @@ module ActiveRecord
446
469
  # <tt>Base#reset_column_information</tt> in order to ensure that the model has the
447
470
  # latest column data from after the new column was added. Example:
448
471
  #
449
- # class AddPeopleSalary < ActiveRecord::Migration[6.0]
472
+ # class AddPeopleSalary < ActiveRecord::Migration[7.2]
450
473
  # def up
451
474
  # add_column :people, :salary, :integer
452
475
  # Person.reset_column_information
@@ -462,7 +485,7 @@ module ActiveRecord
462
485
  # them to the console as they happen, along with benchmarks describing how
463
486
  # long each step took.
464
487
  #
465
- # You can quiet them down by setting ActiveRecord::Migration.verbose = false.
488
+ # You can quiet them down by setting <tt>ActiveRecord::Migration.verbose = false</tt>.
466
489
  #
467
490
  # You can also insert your own messages and benchmarks by using the +say_with_time+
468
491
  # method:
@@ -482,11 +505,15 @@ module ActiveRecord
482
505
  #
483
506
  # == Timestamped Migrations
484
507
  #
485
- # By default, Rails generates migrations that look like:
508
+ # By default, \Rails generates migrations that look like:
486
509
  #
487
510
  # 20080717013526_your_migration_name.rb
488
511
  #
489
- # The prefix is a generation timestamp (in UTC).
512
+ # The prefix is a generation timestamp (in UTC). Timestamps should not be
513
+ # modified manually. To validate that migration timestamps adhere to the
514
+ # format Active Record expects, you can use the following configuration option:
515
+ #
516
+ # config.active_record.validate_migration_timestamps = true
490
517
  #
491
518
  # If you'd prefer to use numeric prefixes, you can turn timestamped migrations
492
519
  # off by setting:
@@ -504,7 +531,7 @@ module ActiveRecord
504
531
  # To define a reversible migration, define the +change+ method in your
505
532
  # migration like this:
506
533
  #
507
- # class TenderloveMigration < ActiveRecord::Migration[6.0]
534
+ # class TenderloveMigration < ActiveRecord::Migration[7.2]
508
535
  # def change
509
536
  # create_table(:horses) do |t|
510
537
  # t.column :content, :text
@@ -521,11 +548,11 @@ module ActiveRecord
521
548
  # as before.
522
549
  #
523
550
  # If a command cannot be reversed, an
524
- # <tt>ActiveRecord::IrreversibleMigration</tt> exception will be raised when
551
+ # ActiveRecord::IrreversibleMigration exception will be raised when
525
552
  # the migration is moving down.
526
553
  #
527
554
  # For a list of commands that are reversible, please see
528
- # <tt>ActiveRecord::Migration::CommandRecorder</tt>.
555
+ # +ActiveRecord::Migration::CommandRecorder+.
529
556
  #
530
557
  # == Transactional Migrations
531
558
  #
@@ -534,7 +561,7 @@ module ActiveRecord
534
561
  # can't execute inside a transaction though, and for these situations
535
562
  # you can turn the automatic transactions off.
536
563
  #
537
- # class ChangeEnum < ActiveRecord::Migration[6.0]
564
+ # class ChangeEnum < ActiveRecord::Migration[7.2]
538
565
  # disable_ddl_transaction!
539
566
  #
540
567
  # def up
@@ -548,18 +575,57 @@ module ActiveRecord
548
575
  autoload :CommandRecorder, "active_record/migration/command_recorder"
549
576
  autoload :Compatibility, "active_record/migration/compatibility"
550
577
  autoload :JoinTable, "active_record/migration/join_table"
578
+ autoload :ExecutionStrategy, "active_record/migration/execution_strategy"
579
+ autoload :DefaultStrategy, "active_record/migration/default_strategy"
551
580
 
552
581
  # This must be defined before the inherited hook, below
553
- class Current < Migration #:nodoc:
582
+ class Current < Migration # :nodoc:
583
+ def create_table(table_name, **options)
584
+ if block_given?
585
+ super { |t| yield compatible_table_definition(t) }
586
+ else
587
+ super
588
+ end
589
+ end
590
+
591
+ def change_table(table_name, **options)
592
+ if block_given?
593
+ super { |t| yield compatible_table_definition(t) }
594
+ else
595
+ super
596
+ end
597
+ end
598
+
599
+ def create_join_table(table_1, table_2, **options)
600
+ if block_given?
601
+ super { |t| yield compatible_table_definition(t) }
602
+ else
603
+ super
604
+ end
605
+ end
606
+
607
+ def drop_table(table_name, **options)
608
+ if block_given?
609
+ super { |t| yield compatible_table_definition(t) }
610
+ else
611
+ super
612
+ end
613
+ end
614
+
615
+ def compatible_table_definition(t)
616
+ t
617
+ end
554
618
  end
555
619
 
556
- def self.inherited(subclass) #:nodoc:
620
+ def self.inherited(subclass) # :nodoc:
557
621
  super
558
622
  if subclass.superclass == Migration
623
+ major = ActiveRecord::VERSION::MAJOR
624
+ minor = ActiveRecord::VERSION::MINOR
559
625
  raise StandardError, "Directly inheriting from ActiveRecord::Migration is not supported. " \
560
- "Please specify the Rails release the migration was written for:\n" \
626
+ "Please specify the Active Record release the migration was written for:\n" \
561
627
  "\n" \
562
- " class #{subclass} < ActiveRecord::Migration[4.2]"
628
+ " class #{subclass} < ActiveRecord::Migration[#{major}.#{minor}]"
563
629
  end
564
630
  end
565
631
 
@@ -571,10 +637,17 @@ module ActiveRecord
571
637
  ActiveRecord::VERSION::STRING.to_f
572
638
  end
573
639
 
574
- MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/ #:nodoc:
640
+ MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/ # :nodoc:
641
+
642
+ def self.valid_version_format?(version_string) # :nodoc:
643
+ [
644
+ MigrationFilenameRegexp,
645
+ /\A\d(_?\d)*\z/ # integer with optional underscores
646
+ ].any? { |pattern| pattern.match?(version_string) }
647
+ end
575
648
 
576
649
  # This class is used to verify that all migrations have been run before
577
- # loading a web page if <tt>config.active_record.migration_error</tt> is set to :page_load
650
+ # loading a web page if <tt>config.active_record.migration_error</tt> is set to +:page_load+.
578
651
  class CheckPending
579
652
  def initialize(app, file_watcher: ActiveSupport::FileUpdateChecker)
580
653
  @app = app
@@ -587,7 +660,7 @@ module ActiveRecord
587
660
  @mutex.synchronize do
588
661
  @watcher ||= build_watcher do
589
662
  @needs_check = true
590
- ActiveRecord::Migration.check_pending!(connection)
663
+ ActiveRecord::Migration.check_pending_migrations
591
664
  @needs_check = false
592
665
  end
593
666
 
@@ -603,61 +676,66 @@ module ActiveRecord
603
676
 
604
677
  private
605
678
  def build_watcher(&block)
606
- paths = Array(connection.migration_context.migrations_paths)
679
+ current_environment = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
680
+ all_configs = ActiveRecord::Base.configurations.configs_for(env_name: current_environment)
681
+ paths = all_configs.flat_map { |config| config.migrations_paths || Migrator.migrations_paths }.uniq
607
682
  @file_watcher.new([], paths.index_with(["rb"]), &block)
608
683
  end
609
684
 
610
685
  def connection
611
- ActiveRecord::Base.connection
686
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection
612
687
  end
613
688
  end
614
689
 
615
690
  class << self
616
- attr_accessor :delegate #:nodoc:
617
- attr_accessor :disable_ddl_transaction #:nodoc:
691
+ attr_accessor :delegate # :nodoc:
692
+ attr_accessor :disable_ddl_transaction # :nodoc:
618
693
 
619
- def nearest_delegate #:nodoc:
694
+ def nearest_delegate # :nodoc:
620
695
  delegate || superclass.nearest_delegate
621
696
  end
622
697
 
623
- # Raises <tt>ActiveRecord::PendingMigrationError</tt> error if any migrations are pending.
624
- def check_pending!(connection = Base.connection)
625
- raise ActiveRecord::PendingMigrationError if connection.migration_context.needs_migration?
626
- end
698
+ # Raises ActiveRecord::PendingMigrationError error if any migrations are pending
699
+ # for all database configurations in an environment.
700
+ def check_all_pending!
701
+ pending_migrations = []
627
702
 
628
- def load_schema_if_pending!
629
- current_db_config = Base.connection_db_config
630
- all_configs = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env)
703
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: env) do |pool|
704
+ if pending = pool.migration_context.open.pending_migrations
705
+ pending_migrations << pending
706
+ end
707
+ end
708
+
709
+ migrations = pending_migrations.flatten
631
710
 
632
- needs_update = !all_configs.all? do |db_config|
633
- Tasks::DatabaseTasks.schema_up_to_date?(db_config, ActiveRecord::Base.schema_format)
711
+ if migrations.any?
712
+ raise ActiveRecord::PendingMigrationError.new(pending_migrations: migrations)
634
713
  end
714
+ end
635
715
 
636
- if needs_update
716
+ def load_schema_if_pending!
717
+ if any_schema_needs_update?
637
718
  # Roundtrip to Rake to allow plugins to hook into database initialization.
638
719
  root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
720
+
639
721
  FileUtils.cd(root) do
640
- Base.clear_all_connections!
722
+ Base.connection_handler.clear_all_connections!(:all)
641
723
  system("bin/rails db:test:prepare")
642
724
  end
643
725
  end
644
726
 
645
- # Establish a new connection, the old database may be gone (db:test:prepare uses purge)
646
- Base.establish_connection(current_db_config)
647
-
648
- check_pending!
727
+ check_pending_migrations
649
728
  end
650
729
 
651
- def maintain_test_schema! #:nodoc:
652
- if ActiveRecord::Base.maintain_test_schema
730
+ def maintain_test_schema! # :nodoc:
731
+ if ActiveRecord.maintain_test_schema
653
732
  suppress_messages { load_schema_if_pending! }
654
733
  end
655
734
  end
656
735
 
657
- def method_missing(name, *args, &block) #:nodoc:
658
- nearest_delegate.send(name, *args, &block)
736
+ def method_missing(name, ...) # :nodoc:
737
+ nearest_delegate.send(name, ...)
659
738
  end
660
- ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
661
739
 
662
740
  def migrate(direction)
663
741
  new.migrate direction
@@ -670,12 +748,55 @@ module ActiveRecord
670
748
  def disable_ddl_transaction!
671
749
  @disable_ddl_transaction = true
672
750
  end
751
+
752
+ def check_pending_migrations # :nodoc:
753
+ migrations = pending_migrations
754
+
755
+ if migrations.any?
756
+ raise ActiveRecord::PendingMigrationError.new(pending_migrations: migrations)
757
+ end
758
+ end
759
+
760
+ private
761
+ def any_schema_needs_update?
762
+ !db_configs_in_current_env.all? do |db_config|
763
+ Tasks::DatabaseTasks.schema_up_to_date?(db_config, ActiveRecord.schema_format)
764
+ end
765
+ end
766
+
767
+ def db_configs_in_current_env
768
+ ActiveRecord::Base.configurations.configs_for(env_name: env)
769
+ end
770
+
771
+ def pending_migrations
772
+ pending_migrations = []
773
+
774
+ ActiveRecord::Base.configurations.configs_for(env_name: env).each do |db_config|
775
+ ActiveRecord::PendingMigrationConnection.with_temporary_pool(db_config) do |pool|
776
+ if pending = pool.migration_context.open.pending_migrations
777
+ pending_migrations << pending
778
+ end
779
+ end
780
+ end
781
+
782
+ pending_migrations.flatten
783
+ end
784
+
785
+ def env
786
+ ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
787
+ end
673
788
  end
674
789
 
675
- def disable_ddl_transaction #:nodoc:
790
+ def disable_ddl_transaction # :nodoc:
676
791
  self.class.disable_ddl_transaction
677
792
  end
678
793
 
794
+ ##
795
+ # :singleton-method: verbose
796
+ #
797
+ # Specifies if migrations will write the actions they are taking to the console as they
798
+ # happen, along with benchmarks describing how long each step took. Defaults to
799
+ # true.
679
800
  cattr_accessor :verbose
680
801
  attr_accessor :name, :version
681
802
 
@@ -683,6 +804,11 @@ module ActiveRecord
683
804
  @name = name
684
805
  @version = version
685
806
  @connection = nil
807
+ @pool = nil
808
+ end
809
+
810
+ def execution_strategy
811
+ @execution_strategy ||= ActiveRecord.migration_strategy.new(self)
686
812
  end
687
813
 
688
814
  self.verbose = true
@@ -696,7 +822,7 @@ module ActiveRecord
696
822
  # and create the table 'apples' on the way up, and the reverse
697
823
  # on the way down.
698
824
  #
699
- # class FixTLMigration < ActiveRecord::Migration[6.0]
825
+ # class FixTLMigration < ActiveRecord::Migration[7.2]
700
826
  # def change
701
827
  # revert do
702
828
  # create_table(:horses) do |t|
@@ -715,7 +841,7 @@ module ActiveRecord
715
841
  #
716
842
  # require_relative "20121212123456_tenderlove_migration"
717
843
  #
718
- # class FixupTLMigration < ActiveRecord::Migration[6.0]
844
+ # class FixupTLMigration < ActiveRecord::Migration[7.2]
719
845
  # def change
720
846
  # revert TenderloveMigration
721
847
  #
@@ -726,16 +852,16 @@ module ActiveRecord
726
852
  # end
727
853
  #
728
854
  # This command can be nested.
729
- def revert(*migration_classes)
855
+ def revert(*migration_classes, &block)
730
856
  run(*migration_classes.reverse, revert: true) unless migration_classes.empty?
731
857
  if block_given?
732
858
  if connection.respond_to? :revert
733
- connection.revert { yield }
859
+ connection.revert(&block)
734
860
  else
735
861
  recorder = command_recorder
736
862
  @connection = recorder
737
863
  suppress_messages do
738
- connection.revert { yield }
864
+ connection.revert(&block)
739
865
  end
740
866
  @connection = recorder.delegate
741
867
  recorder.replay(self)
@@ -747,7 +873,7 @@ module ActiveRecord
747
873
  connection.respond_to?(:reverting) && connection.reverting
748
874
  end
749
875
 
750
- ReversibleBlockHelper = Struct.new(:reverting) do #:nodoc:
876
+ ReversibleBlockHelper = Struct.new(:reverting) do # :nodoc:
751
877
  def up
752
878
  yield unless reverting
753
879
  end
@@ -766,7 +892,7 @@ module ActiveRecord
766
892
  # when the three columns 'first_name', 'last_name' and 'full_name' exist,
767
893
  # even when migrating down:
768
894
  #
769
- # class SplitNameMigration < ActiveRecord::Migration[6.0]
895
+ # class SplitNameMigration < ActiveRecord::Migration[7.2]
770
896
  # def change
771
897
  # add_column :users, :first_name, :string
772
898
  # add_column :users, :last_name, :string
@@ -794,7 +920,7 @@ module ActiveRecord
794
920
  # In the following example, the new column +published+ will be given
795
921
  # the value +true+ for all existing records.
796
922
  #
797
- # class AddPublishedToPosts < ActiveRecord::Migration[6.0]
923
+ # class AddPublishedToPosts < ActiveRecord::Migration[7.2]
798
924
  # def change
799
925
  # add_column :posts, :published, :boolean, default: false
800
926
  # up_only do
@@ -802,14 +928,15 @@ module ActiveRecord
802
928
  # end
803
929
  # end
804
930
  # end
805
- def up_only
806
- execute_block { yield } unless reverting?
931
+ def up_only(&block)
932
+ execute_block(&block) unless reverting?
807
933
  end
808
934
 
809
935
  # Runs the given migration classes.
810
936
  # Last argument can specify options:
811
- # - :direction (default is :up)
812
- # - :revert (default is false)
937
+ #
938
+ # - +:direction+ - Default is +:up+.
939
+ # - +:revert+ - Default is +false+.
813
940
  def run(*migration_classes)
814
941
  opts = migration_classes.extract_options!
815
942
  dir = opts[:direction] || :up
@@ -846,7 +973,7 @@ module ActiveRecord
846
973
  end
847
974
 
848
975
  time = nil
849
- ActiveRecord::Base.connection_pool.with_connection do |conn|
976
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection.pool.with_connection do |conn|
850
977
  time = Benchmark.measure do
851
978
  exec_migration(conn, direction)
852
979
  end
@@ -871,6 +998,7 @@ module ActiveRecord
871
998
  end
872
999
  ensure
873
1000
  @connection = nil
1001
+ @execution_strategy = nil
874
1002
  end
875
1003
 
876
1004
  def write(text = "")
@@ -909,38 +1037,41 @@ module ActiveRecord
909
1037
  end
910
1038
 
911
1039
  def connection
912
- @connection || ActiveRecord::Base.connection
1040
+ @connection || ActiveRecord::Tasks::DatabaseTasks.migration_connection
913
1041
  end
914
1042
 
915
- def method_missing(method, *arguments, &block)
916
- arg_list = arguments.map(&:inspect) * ", "
1043
+ def connection_pool
1044
+ @pool || ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool
1045
+ end
917
1046
 
918
- say_with_time "#{method}(#{arg_list})" do
1047
+ def method_missing(method, *arguments, &block)
1048
+ say_with_time "#{method}(#{format_arguments(arguments)})" do
919
1049
  unless connection.respond_to? :revert
920
1050
  unless arguments.empty? || [:execute, :enable_extension, :disable_extension].include?(method)
921
1051
  arguments[0] = proper_table_name(arguments.first, table_name_options)
922
- if [:rename_table, :add_foreign_key].include?(method) ||
1052
+ if method == :rename_table ||
923
1053
  (method == :remove_foreign_key && !arguments.second.is_a?(Hash))
924
1054
  arguments[1] = proper_table_name(arguments.second, table_name_options)
925
1055
  end
926
1056
  end
927
1057
  end
928
- return super unless connection.respond_to?(method)
929
- connection.send(method, *arguments, &block)
1058
+ return super unless execution_strategy.respond_to?(method)
1059
+ execution_strategy.send(method, *arguments, &block)
930
1060
  end
931
1061
  end
932
- ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
1062
+ ruby2_keywords(:method_missing)
933
1063
 
934
1064
  def copy(destination, sources, options = {})
935
1065
  copied = []
936
- schema_migration = options[:schema_migration] || ActiveRecord::SchemaMigration
937
1066
 
938
1067
  FileUtils.mkdir_p(destination) unless File.exist?(destination)
1068
+ schema_migration = SchemaMigration::NullSchemaMigration.new
1069
+ internal_metadata = InternalMetadata::NullInternalMetadata.new
939
1070
 
940
- destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration).migrations
1071
+ destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration, internal_metadata).migrations
941
1072
  last = destination_migrations.last
942
1073
  sources.each do |scope, path|
943
- source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration).migrations
1074
+ source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration, internal_metadata).migrations
944
1075
 
945
1076
  source_migrations.each do |migration|
946
1077
  source = File.binread(migration.filename)
@@ -955,6 +1086,12 @@ module ActiveRecord
955
1086
  magic_comments << magic_comment; ""
956
1087
  end || break
957
1088
  end
1089
+
1090
+ if !magic_comments.empty? && source.start_with?("\n")
1091
+ magic_comments << "\n"
1092
+ source = source[1..-1]
1093
+ end
1094
+
958
1095
  source = "#{magic_comments}#{inserted_comment}#{source}"
959
1096
 
960
1097
  if duplicate = destination_migrations.detect { |m| m.name == migration.name }
@@ -992,16 +1129,16 @@ module ActiveRecord
992
1129
 
993
1130
  # Determines the version number of the next migration.
994
1131
  def next_migration_number(number)
995
- if ActiveRecord::Base.timestamped_migrations
1132
+ if ActiveRecord.timestamped_migrations
996
1133
  [Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % number].max
997
1134
  else
998
- SchemaMigration.normalize_migration_number(number)
1135
+ "%.3d" % number.to_i
999
1136
  end
1000
1137
  end
1001
1138
 
1002
1139
  # Builds a hash for use in ActiveRecord::Migration#proper_table_name using
1003
1140
  # the Active Record object's table_name prefix and suffix
1004
- def table_name_options(config = ActiveRecord::Base) #:nodoc:
1141
+ def table_name_options(config = ActiveRecord::Base) # :nodoc:
1005
1142
  {
1006
1143
  table_name_prefix: config.table_name_prefix,
1007
1144
  table_name_suffix: config.table_name_suffix
@@ -1017,6 +1154,22 @@ module ActiveRecord
1017
1154
  end
1018
1155
  end
1019
1156
 
1157
+ def format_arguments(arguments)
1158
+ arg_list = arguments[0...-1].map(&:inspect)
1159
+ last_arg = arguments.last
1160
+ if last_arg.is_a?(Hash)
1161
+ last_arg = last_arg.reject { |k, _v| internal_option?(k) }
1162
+ arg_list << last_arg.inspect unless last_arg.empty?
1163
+ else
1164
+ arg_list << last_arg.inspect
1165
+ end
1166
+ arg_list.join(", ")
1167
+ end
1168
+
1169
+ def internal_option?(option_name)
1170
+ option_name.start_with?("_")
1171
+ end
1172
+
1020
1173
  def command_recorder
1021
1174
  CommandRecorder.new(connection)
1022
1175
  end
@@ -1042,19 +1195,44 @@ module ActiveRecord
1042
1195
  end
1043
1196
 
1044
1197
  def load_migration
1045
- require(File.expand_path(filename))
1198
+ Object.send(:remove_const, name) rescue nil
1199
+
1200
+ load(File.expand_path(filename))
1046
1201
  name.constantize.new(name, version)
1047
1202
  end
1048
1203
  end
1049
1204
 
1050
- class MigrationContext #:nodoc:
1051
- attr_reader :migrations_paths, :schema_migration
1205
+ # = \Migration \Context
1206
+ #
1207
+ # MigrationContext sets the context in which a migration is run.
1208
+ #
1209
+ # A migration context requires the path to the migrations is set
1210
+ # in the +migrations_paths+ parameter. Optionally a +schema_migration+
1211
+ # class can be provided. Multiple database applications will instantiate
1212
+ # a +SchemaMigration+ object per database. From the Rake tasks, \Rails will
1213
+ # handle this for you.
1214
+ class MigrationContext
1215
+ attr_reader :migrations_paths, :schema_migration, :internal_metadata
1052
1216
 
1053
- def initialize(migrations_paths, schema_migration)
1217
+ def initialize(migrations_paths, schema_migration = nil, internal_metadata = nil)
1054
1218
  @migrations_paths = migrations_paths
1055
- @schema_migration = schema_migration
1219
+ @schema_migration = schema_migration || SchemaMigration.new(connection_pool)
1220
+ @internal_metadata = internal_metadata || InternalMetadata.new(connection_pool)
1056
1221
  end
1057
1222
 
1223
+ # Runs the migrations in the +migrations_path+.
1224
+ #
1225
+ # If +target_version+ is +nil+, +migrate+ will run +up+.
1226
+ #
1227
+ # If the +current_version+ and +target_version+ are both
1228
+ # 0 then an empty array will be returned and no migrations
1229
+ # will be run.
1230
+ #
1231
+ # If the +current_version+ in the schema is greater than
1232
+ # the +target_version+, then +down+ will be run.
1233
+ #
1234
+ # If none of the conditions are met, +up+ will be run with
1235
+ # the +target_version+.
1058
1236
  def migrate(target_version = nil, &block)
1059
1237
  case
1060
1238
  when target_version.nil?
@@ -1068,67 +1246,70 @@ module ActiveRecord
1068
1246
  end
1069
1247
  end
1070
1248
 
1071
- def rollback(steps = 1)
1249
+ def rollback(steps = 1) # :nodoc:
1072
1250
  move(:down, steps)
1073
1251
  end
1074
1252
 
1075
- def forward(steps = 1)
1253
+ def forward(steps = 1) # :nodoc:
1076
1254
  move(:up, steps)
1077
1255
  end
1078
1256
 
1079
- def up(target_version = nil)
1257
+ def up(target_version = nil, &block) # :nodoc:
1080
1258
  selected_migrations = if block_given?
1081
- migrations.select { |m| yield m }
1259
+ migrations.select(&block)
1082
1260
  else
1083
1261
  migrations
1084
1262
  end
1085
1263
 
1086
- Migrator.new(:up, selected_migrations, schema_migration, target_version).migrate
1264
+ Migrator.new(:up, selected_migrations, schema_migration, internal_metadata, target_version).migrate
1087
1265
  end
1088
1266
 
1089
- def down(target_version = nil)
1267
+ def down(target_version = nil, &block) # :nodoc:
1090
1268
  selected_migrations = if block_given?
1091
- migrations.select { |m| yield m }
1269
+ migrations.select(&block)
1092
1270
  else
1093
1271
  migrations
1094
1272
  end
1095
1273
 
1096
- Migrator.new(:down, selected_migrations, schema_migration, target_version).migrate
1274
+ Migrator.new(:down, selected_migrations, schema_migration, internal_metadata, target_version).migrate
1097
1275
  end
1098
1276
 
1099
- def run(direction, target_version)
1100
- Migrator.new(direction, migrations, schema_migration, target_version).run
1277
+ def run(direction, target_version) # :nodoc:
1278
+ Migrator.new(direction, migrations, schema_migration, internal_metadata, target_version).run
1101
1279
  end
1102
1280
 
1103
- def open
1104
- Migrator.new(:up, migrations, schema_migration)
1281
+ def open # :nodoc:
1282
+ Migrator.new(:up, migrations, schema_migration, internal_metadata)
1105
1283
  end
1106
1284
 
1107
- def get_all_versions
1285
+ def get_all_versions # :nodoc:
1108
1286
  if schema_migration.table_exists?
1109
- schema_migration.all_versions.map(&:to_i)
1287
+ schema_migration.integer_versions
1110
1288
  else
1111
1289
  []
1112
1290
  end
1113
1291
  end
1114
1292
 
1115
- def current_version
1293
+ def current_version # :nodoc:
1116
1294
  get_all_versions.max || 0
1117
1295
  rescue ActiveRecord::NoDatabaseError
1118
1296
  end
1119
1297
 
1120
- def needs_migration?
1121
- (migrations.collect(&:version) - get_all_versions).size > 0
1298
+ def needs_migration? # :nodoc:
1299
+ pending_migration_versions.size > 0
1122
1300
  end
1123
1301
 
1124
- def any_migrations?
1125
- migrations.any?
1302
+ def pending_migration_versions # :nodoc:
1303
+ migrations.collect(&:version) - get_all_versions
1126
1304
  end
1127
1305
 
1128
- def migrations
1306
+ def migrations # :nodoc:
1129
1307
  migrations = migration_files.map do |file|
1130
1308
  version, name, scope = parse_migration_filename(file)
1131
1309
  raise IllegalMigrationNameError.new(file) unless version
1310
+ if validate_timestamp? && !valid_migration_timestamp?(version)
1311
+ raise InvalidMigrationTimestampError.new(version, name)
1312
+ end
1132
1313
  version = version.to_i
1133
1314
  name = name.camelize
1134
1315
 
@@ -1138,43 +1319,55 @@ module ActiveRecord
1138
1319
  migrations.sort_by(&:version)
1139
1320
  end
1140
1321
 
1141
- def migrations_status
1322
+ def migrations_status # :nodoc:
1142
1323
  db_list = schema_migration.normalized_versions
1143
1324
 
1144
- file_list = migration_files.map do |file|
1325
+ file_list = migration_files.filter_map do |file|
1145
1326
  version, name, scope = parse_migration_filename(file)
1146
1327
  raise IllegalMigrationNameError.new(file) unless version
1328
+ if validate_timestamp? && !valid_migration_timestamp?(version)
1329
+ raise InvalidMigrationTimestampError.new(version, name)
1330
+ end
1147
1331
  version = schema_migration.normalize_migration_number(version)
1148
1332
  status = db_list.delete(version) ? "up" : "down"
1149
1333
  [status, version, (name + scope).humanize]
1150
- end.compact
1334
+ end
1151
1335
 
1152
1336
  db_list.map! do |version|
1153
1337
  ["up", version, "********** NO FILE **********"]
1154
1338
  end
1155
1339
 
1156
- (db_list + file_list).sort_by { |_, version, _| version }
1340
+ (db_list + file_list).sort_by { |_, version, _| version.to_i }
1157
1341
  end
1158
1342
 
1159
- def current_environment
1343
+ def current_environment # :nodoc:
1160
1344
  ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
1161
1345
  end
1162
1346
 
1163
- def protected_environment?
1347
+ def protected_environment? # :nodoc:
1164
1348
  ActiveRecord::Base.protected_environments.include?(last_stored_environment) if last_stored_environment
1165
1349
  end
1166
1350
 
1167
- def last_stored_environment
1168
- return nil unless ActiveRecord::InternalMetadata.enabled?
1351
+ def last_stored_environment # :nodoc:
1352
+ internal_metadata = connection_pool.internal_metadata
1353
+ return nil unless internal_metadata.enabled?
1169
1354
  return nil if current_version == 0
1170
- raise NoEnvironmentInSchemaError unless ActiveRecord::InternalMetadata.table_exists?
1355
+ raise NoEnvironmentInSchemaError unless internal_metadata.table_exists?
1171
1356
 
1172
- environment = ActiveRecord::InternalMetadata[:environment]
1357
+ environment = internal_metadata[:environment]
1173
1358
  raise NoEnvironmentInSchemaError unless environment
1174
1359
  environment
1175
1360
  end
1176
1361
 
1177
1362
  private
1363
+ def connection
1364
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection
1365
+ end
1366
+
1367
+ def connection_pool
1368
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool
1369
+ end
1370
+
1178
1371
  def migration_files
1179
1372
  paths = Array(migrations_paths)
1180
1373
  Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
@@ -1184,8 +1377,16 @@ module ActiveRecord
1184
1377
  File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
1185
1378
  end
1186
1379
 
1380
+ def validate_timestamp?
1381
+ ActiveRecord.timestamped_migrations && ActiveRecord.validate_migration_timestamps
1382
+ end
1383
+
1384
+ def valid_migration_timestamp?(version)
1385
+ version.to_i < (Time.now.utc + 1.day).strftime("%Y%m%d%H%M%S").to_i
1386
+ end
1387
+
1187
1388
  def move(direction, steps)
1188
- migrator = Migrator.new(direction, migrations, schema_migration)
1389
+ migrator = Migrator.new(direction, migrations, schema_migration, internal_metadata)
1189
1390
 
1190
1391
  if current_version != 0 && !migrator.current_migration
1191
1392
  raise UnknownMigrationVersionError.new(current_version)
@@ -1210,23 +1411,28 @@ module ActiveRecord
1210
1411
 
1211
1412
  # For cases where a table doesn't exist like loading from schema cache
1212
1413
  def current_version
1213
- MigrationContext.new(migrations_paths, SchemaMigration).current_version
1414
+ connection_pool = ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool
1415
+ schema_migration = SchemaMigration.new(connection_pool)
1416
+ internal_metadata = InternalMetadata.new(connection_pool)
1417
+
1418
+ MigrationContext.new(migrations_paths, schema_migration, internal_metadata).current_version
1214
1419
  end
1215
1420
  end
1216
1421
 
1217
1422
  self.migrations_paths = ["db/migrate"]
1218
1423
 
1219
- def initialize(direction, migrations, schema_migration, target_version = nil)
1424
+ def initialize(direction, migrations, schema_migration, internal_metadata, target_version = nil)
1220
1425
  @direction = direction
1221
1426
  @target_version = target_version
1222
1427
  @migrated_versions = nil
1223
1428
  @migrations = migrations
1224
1429
  @schema_migration = schema_migration
1430
+ @internal_metadata = internal_metadata
1225
1431
 
1226
1432
  validate(@migrations)
1227
1433
 
1228
1434
  @schema_migration.create_table
1229
- ActiveRecord::InternalMetadata.create_table
1435
+ @internal_metadata.create_table
1230
1436
  end
1231
1437
 
1232
1438
  def current_version
@@ -1279,18 +1485,21 @@ module ActiveRecord
1279
1485
  end
1280
1486
 
1281
1487
  def load_migrated
1282
- @migrated_versions = Set.new(@schema_migration.all_versions.map(&:to_i))
1488
+ @migrated_versions = Set.new(@schema_migration.integer_versions)
1283
1489
  end
1284
1490
 
1285
1491
  private
1492
+ def connection
1493
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection
1494
+ end
1495
+
1286
1496
  # Used for running a specific migration.
1287
1497
  def run_without_lock
1288
1498
  migration = migrations.detect { |m| m.version == @target_version }
1289
1499
  raise UnknownMigrationVersionError.new(@target_version) if migration.nil?
1290
- result = execute_migration_in_transaction(migration)
1291
1500
 
1292
1501
  record_environment
1293
- result
1502
+ execute_migration_in_transaction(migration)
1294
1503
  end
1295
1504
 
1296
1505
  # Used for running multiple migrations up to or down to a certain value.
@@ -1299,15 +1508,15 @@ module ActiveRecord
1299
1508
  raise UnknownMigrationVersionError.new(@target_version)
1300
1509
  end
1301
1510
 
1302
- result = runnable.each(&method(:execute_migration_in_transaction))
1303
1511
  record_environment
1304
- result
1512
+ runnable.each(&method(:execute_migration_in_transaction))
1305
1513
  end
1306
1514
 
1307
1515
  # Stores the current environment in the database.
1308
1516
  def record_environment
1309
1517
  return if down?
1310
- ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Base.connection.migration_context.current_environment
1518
+
1519
+ @internal_metadata[:environment] = connection.pool.db_config.env_name
1311
1520
  end
1312
1521
 
1313
1522
  def ran?(migration)
@@ -1359,10 +1568,10 @@ module ActiveRecord
1359
1568
  def record_version_state_after_migrating(version)
1360
1569
  if down?
1361
1570
  migrated.delete(version)
1362
- @schema_migration.delete_by(version: version.to_s)
1571
+ @schema_migration.delete_version(version.to_s)
1363
1572
  else
1364
1573
  migrated << version
1365
- @schema_migration.create!(version: version.to_s)
1574
+ @schema_migration.create_version(version.to_s)
1366
1575
  end
1367
1576
  end
1368
1577
 
@@ -1375,52 +1584,40 @@ module ActiveRecord
1375
1584
  end
1376
1585
 
1377
1586
  # Wrap the migration in a transaction only if supported by the adapter.
1378
- def ddl_transaction(migration)
1587
+ def ddl_transaction(migration, &block)
1379
1588
  if use_transaction?(migration)
1380
- Base.transaction { yield }
1589
+ connection.transaction(&block)
1381
1590
  else
1382
1591
  yield
1383
1592
  end
1384
1593
  end
1385
1594
 
1386
1595
  def use_transaction?(migration)
1387
- !migration.disable_ddl_transaction && Base.connection.supports_ddl_transactions?
1596
+ !migration.disable_ddl_transaction && connection.supports_ddl_transactions?
1388
1597
  end
1389
1598
 
1390
1599
  def use_advisory_lock?
1391
- Base.connection.advisory_locks_enabled?
1600
+ connection.advisory_locks_enabled?
1392
1601
  end
1393
1602
 
1394
1603
  def with_advisory_lock
1395
1604
  lock_id = generate_migrator_advisory_lock_id
1396
1605
 
1397
- with_advisory_lock_connection do |connection|
1398
- got_lock = connection.get_advisory_lock(lock_id)
1399
- raise ConcurrentMigrationError unless got_lock
1400
- load_migrated # reload schema_migrations to be sure it wasn't changed by another process before we got the lock
1401
- yield
1402
- ensure
1403
- if got_lock && !connection.release_advisory_lock(lock_id)
1404
- raise ConcurrentMigrationError.new(
1405
- ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE
1406
- )
1407
- end
1408
- end
1409
- end
1410
-
1411
- def with_advisory_lock_connection
1412
- pool = ActiveRecord::ConnectionAdapters::ConnectionHandler.new.establish_connection(
1413
- ActiveRecord::Base.connection_db_config
1414
- )
1415
-
1416
- pool.with_connection { |connection| yield(connection) }
1606
+ got_lock = connection.get_advisory_lock(lock_id)
1607
+ raise ConcurrentMigrationError unless got_lock
1608
+ load_migrated # reload schema_migrations to be sure it wasn't changed by another process before we got the lock
1609
+ yield
1417
1610
  ensure
1418
- pool&.disconnect!
1611
+ if got_lock && !connection.release_advisory_lock(lock_id)
1612
+ raise ConcurrentMigrationError.new(
1613
+ ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE
1614
+ )
1615
+ end
1419
1616
  end
1420
1617
 
1421
1618
  MIGRATOR_SALT = 2053462845
1422
1619
  def generate_migrator_advisory_lock_id
1423
- db_name_hash = Zlib.crc32(Base.connection.current_database)
1620
+ db_name_hash = Zlib.crc32(connection.current_database)
1424
1621
  MIGRATOR_SALT * db_name_hash
1425
1622
  end
1426
1623
  end