activerecord 6.1.7 → 7.1.0

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