activerecord 5.2.8.1 → 6.1.6.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (316) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1255 -596
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +7 -5
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record/aggregations.rb +9 -8
  7. data/lib/active_record/association_relation.rb +30 -10
  8. data/lib/active_record/associations/alias_tracker.rb +19 -16
  9. data/lib/active_record/associations/association.rb +100 -41
  10. data/lib/active_record/associations/association_scope.rb +23 -21
  11. data/lib/active_record/associations/belongs_to_association.rb +55 -48
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +7 -6
  13. data/lib/active_record/associations/builder/association.rb +45 -22
  14. data/lib/active_record/associations/builder/belongs_to.rb +29 -59
  15. data/lib/active_record/associations/builder/collection_association.rb +8 -17
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -41
  17. data/lib/active_record/associations/builder/has_many.rb +8 -2
  18. data/lib/active_record/associations/builder/has_one.rb +33 -2
  19. data/lib/active_record/associations/builder/singular_association.rb +3 -1
  20. data/lib/active_record/associations/collection_association.rb +44 -34
  21. data/lib/active_record/associations/collection_proxy.rb +25 -21
  22. data/lib/active_record/associations/foreign_association.rb +20 -0
  23. data/lib/active_record/associations/has_many_association.rb +26 -13
  24. data/lib/active_record/associations/has_many_through_association.rb +24 -18
  25. data/lib/active_record/associations/has_one_association.rb +43 -31
  26. data/lib/active_record/associations/has_one_through_association.rb +5 -5
  27. data/lib/active_record/associations/join_dependency/join_association.rb +44 -22
  28. data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
  29. data/lib/active_record/associations/join_dependency.rb +91 -60
  30. data/lib/active_record/associations/preloader/association.rb +69 -43
  31. data/lib/active_record/associations/preloader/through_association.rb +49 -40
  32. data/lib/active_record/associations/preloader.rb +47 -34
  33. data/lib/active_record/associations/singular_association.rb +3 -17
  34. data/lib/active_record/associations/through_association.rb +1 -1
  35. data/lib/active_record/associations.rb +137 -25
  36. data/lib/active_record/attribute_assignment.rb +17 -19
  37. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -7
  38. data/lib/active_record/attribute_methods/dirty.rb +101 -40
  39. data/lib/active_record/attribute_methods/primary_key.rb +20 -25
  40. data/lib/active_record/attribute_methods/query.rb +4 -8
  41. data/lib/active_record/attribute_methods/read.rb +14 -56
  42. data/lib/active_record/attribute_methods/serialization.rb +12 -7
  43. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
  44. data/lib/active_record/attribute_methods/write.rb +18 -34
  45. data/lib/active_record/attribute_methods.rb +81 -143
  46. data/lib/active_record/attributes.rb +46 -9
  47. data/lib/active_record/autosave_association.rb +57 -42
  48. data/lib/active_record/base.rb +4 -17
  49. data/lib/active_record/callbacks.rb +158 -43
  50. data/lib/active_record/coders/yaml_column.rb +1 -2
  51. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +272 -130
  52. data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -36
  53. data/lib/active_record/connection_adapters/abstract/database_statements.rb +167 -146
  54. data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -14
  55. data/lib/active_record/connection_adapters/abstract/quoting.rb +98 -47
  56. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  57. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -110
  58. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +211 -90
  59. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -4
  60. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +385 -144
  61. data/lib/active_record/connection_adapters/abstract/transaction.rb +167 -69
  62. data/lib/active_record/connection_adapters/abstract_adapter.rb +229 -99
  63. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +243 -275
  64. data/lib/active_record/connection_adapters/column.rb +30 -12
  65. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  66. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
  67. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  68. data/lib/active_record/connection_adapters/mysql/database_statements.rb +88 -32
  69. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
  70. data/lib/active_record/connection_adapters/mysql/quoting.rb +59 -7
  71. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +34 -10
  72. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +48 -32
  73. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +18 -7
  74. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +142 -19
  75. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
  76. data/lib/active_record/connection_adapters/mysql2_adapter.rb +53 -18
  77. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  78. data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
  79. data/lib/active_record/connection_adapters/postgresql/column.rb +37 -28
  80. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +40 -54
  81. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
  82. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
  83. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  84. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
  85. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
  86. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  87. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +3 -4
  90. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +3 -4
  93. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
  94. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  95. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
  96. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +15 -3
  97. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  98. data/lib/active_record/connection_adapters/postgresql/quoting.rb +47 -10
  99. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
  100. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +19 -4
  101. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
  102. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
  103. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +120 -100
  104. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +31 -26
  105. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  106. data/lib/active_record/connection_adapters/postgresql_adapter.rb +224 -120
  107. data/lib/active_record/connection_adapters/schema_cache.rb +159 -21
  108. data/lib/active_record/connection_adapters/sql_type_metadata.rb +17 -6
  109. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +146 -0
  110. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
  111. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  112. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +77 -13
  113. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +174 -186
  114. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  115. data/lib/active_record/connection_adapters.rb +52 -0
  116. data/lib/active_record/connection_handling.rb +293 -33
  117. data/lib/active_record/core.rb +333 -98
  118. data/lib/active_record/counter_cache.rb +8 -30
  119. data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -0
  120. data/lib/active_record/database_configurations/database_config.rb +80 -0
  121. data/lib/active_record/database_configurations/hash_config.rb +96 -0
  122. data/lib/active_record/database_configurations/url_config.rb +53 -0
  123. data/lib/active_record/database_configurations.rb +273 -0
  124. data/lib/active_record/delegated_type.rb +209 -0
  125. data/lib/active_record/destroy_association_async_job.rb +36 -0
  126. data/lib/active_record/dynamic_matchers.rb +3 -4
  127. data/lib/active_record/enum.rb +108 -36
  128. data/lib/active_record/errors.rb +62 -19
  129. data/lib/active_record/explain.rb +10 -6
  130. data/lib/active_record/explain_subscriber.rb +1 -1
  131. data/lib/active_record/fixture_set/file.rb +10 -17
  132. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  133. data/lib/active_record/fixture_set/render_context.rb +17 -0
  134. data/lib/active_record/fixture_set/table_row.rb +152 -0
  135. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  136. data/lib/active_record/fixtures.rb +200 -481
  137. data/lib/active_record/gem_version.rb +3 -3
  138. data/lib/active_record/inheritance.rb +53 -24
  139. data/lib/active_record/insert_all.rb +212 -0
  140. data/lib/active_record/integration.rb +67 -17
  141. data/lib/active_record/internal_metadata.rb +28 -9
  142. data/lib/active_record/legacy_yaml_adapter.rb +7 -3
  143. data/lib/active_record/locking/optimistic.rb +37 -23
  144. data/lib/active_record/locking/pessimistic.rb +9 -5
  145. data/lib/active_record/log_subscriber.rb +35 -35
  146. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  147. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  148. data/lib/active_record/middleware/database_selector.rb +77 -0
  149. data/lib/active_record/migration/command_recorder.rb +96 -44
  150. data/lib/active_record/migration/compatibility.rb +145 -64
  151. data/lib/active_record/migration/join_table.rb +0 -1
  152. data/lib/active_record/migration.rb +206 -157
  153. data/lib/active_record/model_schema.rb +148 -22
  154. data/lib/active_record/nested_attributes.rb +4 -7
  155. data/lib/active_record/no_touching.rb +8 -1
  156. data/lib/active_record/null_relation.rb +0 -1
  157. data/lib/active_record/persistence.rb +267 -59
  158. data/lib/active_record/query_cache.rb +21 -4
  159. data/lib/active_record/querying.rb +40 -23
  160. data/lib/active_record/railtie.rb +116 -59
  161. data/lib/active_record/railties/console_sandbox.rb +2 -4
  162. data/lib/active_record/railties/controller_runtime.rb +30 -35
  163. data/lib/active_record/railties/databases.rake +411 -80
  164. data/lib/active_record/readonly_attributes.rb +4 -0
  165. data/lib/active_record/reflection.rb +109 -93
  166. data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
  167. data/lib/active_record/relation/batches.rb +44 -35
  168. data/lib/active_record/relation/calculations.rb +157 -90
  169. data/lib/active_record/relation/delegation.rb +35 -50
  170. data/lib/active_record/relation/finder_methods.rb +64 -39
  171. data/lib/active_record/relation/from_clause.rb +5 -1
  172. data/lib/active_record/relation/merger.rb +32 -40
  173. data/lib/active_record/relation/predicate_builder/array_handler.rb +13 -13
  174. data/lib/active_record/relation/predicate_builder/association_query_value.rb +5 -9
  175. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
  176. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +11 -10
  177. data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
  178. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  179. data/lib/active_record/relation/predicate_builder.rb +62 -45
  180. data/lib/active_record/relation/query_attribute.rb +13 -8
  181. data/lib/active_record/relation/query_methods.rb +476 -187
  182. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  183. data/lib/active_record/relation/spawn_methods.rb +9 -9
  184. data/lib/active_record/relation/where_clause.rb +115 -62
  185. data/lib/active_record/relation.rb +379 -115
  186. data/lib/active_record/result.rb +64 -38
  187. data/lib/active_record/runtime_registry.rb +2 -2
  188. data/lib/active_record/sanitization.rb +22 -41
  189. data/lib/active_record/schema.rb +2 -11
  190. data/lib/active_record/schema_dumper.rb +54 -9
  191. data/lib/active_record/schema_migration.rb +7 -9
  192. data/lib/active_record/scoping/default.rb +4 -8
  193. data/lib/active_record/scoping/named.rb +17 -24
  194. data/lib/active_record/scoping.rb +8 -9
  195. data/lib/active_record/secure_token.rb +16 -8
  196. data/lib/active_record/serialization.rb +5 -3
  197. data/lib/active_record/signed_id.rb +116 -0
  198. data/lib/active_record/statement_cache.rb +49 -6
  199. data/lib/active_record/store.rb +88 -9
  200. data/lib/active_record/suppressor.rb +2 -2
  201. data/lib/active_record/table_metadata.rb +42 -43
  202. data/lib/active_record/tasks/database_tasks.rb +277 -81
  203. data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
  204. data/lib/active_record/tasks/postgresql_database_tasks.rb +27 -32
  205. data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -17
  206. data/lib/active_record/test_databases.rb +24 -0
  207. data/lib/active_record/test_fixtures.rb +287 -0
  208. data/lib/active_record/timestamp.rb +43 -32
  209. data/lib/active_record/touch_later.rb +23 -22
  210. data/lib/active_record/transactions.rb +62 -118
  211. data/lib/active_record/translation.rb +1 -1
  212. data/lib/active_record/type/adapter_specific_registry.rb +3 -13
  213. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  214. data/lib/active_record/type/serialized.rb +6 -3
  215. data/lib/active_record/type/time.rb +10 -0
  216. data/lib/active_record/type/type_map.rb +0 -1
  217. data/lib/active_record/type/unsigned_integer.rb +0 -1
  218. data/lib/active_record/type.rb +10 -5
  219. data/lib/active_record/type_caster/connection.rb +15 -15
  220. data/lib/active_record/type_caster/map.rb +8 -8
  221. data/lib/active_record/validations/associated.rb +1 -2
  222. data/lib/active_record/validations/numericality.rb +35 -0
  223. data/lib/active_record/validations/uniqueness.rb +38 -30
  224. data/lib/active_record/validations.rb +4 -3
  225. data/lib/active_record.rb +13 -12
  226. data/lib/arel/alias_predication.rb +9 -0
  227. data/lib/arel/attributes/attribute.rb +41 -0
  228. data/lib/arel/collectors/bind.rb +29 -0
  229. data/lib/arel/collectors/composite.rb +39 -0
  230. data/lib/arel/collectors/plain_string.rb +20 -0
  231. data/lib/arel/collectors/sql_string.rb +27 -0
  232. data/lib/arel/collectors/substitute_binds.rb +35 -0
  233. data/lib/arel/crud.rb +42 -0
  234. data/lib/arel/delete_manager.rb +18 -0
  235. data/lib/arel/errors.rb +9 -0
  236. data/lib/arel/expressions.rb +29 -0
  237. data/lib/arel/factory_methods.rb +49 -0
  238. data/lib/arel/insert_manager.rb +49 -0
  239. data/lib/arel/math.rb +45 -0
  240. data/lib/arel/nodes/and.rb +32 -0
  241. data/lib/arel/nodes/ascending.rb +23 -0
  242. data/lib/arel/nodes/binary.rb +126 -0
  243. data/lib/arel/nodes/bind_param.rb +44 -0
  244. data/lib/arel/nodes/case.rb +55 -0
  245. data/lib/arel/nodes/casted.rb +62 -0
  246. data/lib/arel/nodes/comment.rb +29 -0
  247. data/lib/arel/nodes/count.rb +12 -0
  248. data/lib/arel/nodes/delete_statement.rb +45 -0
  249. data/lib/arel/nodes/descending.rb +23 -0
  250. data/lib/arel/nodes/equality.rb +15 -0
  251. data/lib/arel/nodes/extract.rb +24 -0
  252. data/lib/arel/nodes/false.rb +16 -0
  253. data/lib/arel/nodes/full_outer_join.rb +8 -0
  254. data/lib/arel/nodes/function.rb +44 -0
  255. data/lib/arel/nodes/grouping.rb +11 -0
  256. data/lib/arel/nodes/homogeneous_in.rb +76 -0
  257. data/lib/arel/nodes/in.rb +15 -0
  258. data/lib/arel/nodes/infix_operation.rb +92 -0
  259. data/lib/arel/nodes/inner_join.rb +8 -0
  260. data/lib/arel/nodes/insert_statement.rb +37 -0
  261. data/lib/arel/nodes/join_source.rb +20 -0
  262. data/lib/arel/nodes/matches.rb +18 -0
  263. data/lib/arel/nodes/named_function.rb +23 -0
  264. data/lib/arel/nodes/node.rb +51 -0
  265. data/lib/arel/nodes/node_expression.rb +13 -0
  266. data/lib/arel/nodes/ordering.rb +27 -0
  267. data/lib/arel/nodes/outer_join.rb +8 -0
  268. data/lib/arel/nodes/over.rb +15 -0
  269. data/lib/arel/nodes/regexp.rb +16 -0
  270. data/lib/arel/nodes/right_outer_join.rb +8 -0
  271. data/lib/arel/nodes/select_core.rb +67 -0
  272. data/lib/arel/nodes/select_statement.rb +41 -0
  273. data/lib/arel/nodes/sql_literal.rb +19 -0
  274. data/lib/arel/nodes/string_join.rb +11 -0
  275. data/lib/arel/nodes/table_alias.rb +31 -0
  276. data/lib/arel/nodes/terminal.rb +16 -0
  277. data/lib/arel/nodes/true.rb +16 -0
  278. data/lib/arel/nodes/unary.rb +44 -0
  279. data/lib/arel/nodes/unary_operation.rb +20 -0
  280. data/lib/arel/nodes/unqualified_column.rb +22 -0
  281. data/lib/arel/nodes/update_statement.rb +41 -0
  282. data/lib/arel/nodes/values_list.rb +9 -0
  283. data/lib/arel/nodes/window.rb +126 -0
  284. data/lib/arel/nodes/with.rb +11 -0
  285. data/lib/arel/nodes.rb +70 -0
  286. data/lib/arel/order_predications.rb +13 -0
  287. data/lib/arel/predications.rb +250 -0
  288. data/lib/arel/select_manager.rb +270 -0
  289. data/lib/arel/table.rb +118 -0
  290. data/lib/arel/tree_manager.rb +72 -0
  291. data/lib/arel/update_manager.rb +34 -0
  292. data/lib/arel/visitors/dot.rb +308 -0
  293. data/lib/arel/visitors/mysql.rb +93 -0
  294. data/lib/arel/visitors/postgresql.rb +120 -0
  295. data/lib/arel/visitors/sqlite.rb +38 -0
  296. data/lib/arel/visitors/to_sql.rb +899 -0
  297. data/lib/arel/visitors/visitor.rb +45 -0
  298. data/lib/arel/visitors.rb +13 -0
  299. data/lib/arel/window_predications.rb +9 -0
  300. data/lib/arel.rb +54 -0
  301. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  302. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -5
  303. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +3 -1
  304. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +7 -5
  305. data/lib/rails/generators/active_record/migration.rb +19 -2
  306. data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
  307. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  308. data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
  309. metadata +116 -30
  310. data/lib/active_record/attribute_decorators.rb +0 -90
  311. data/lib/active_record/collection_cache_key.rb +0 -53
  312. data/lib/active_record/connection_adapters/connection_specification.rb +0 -287
  313. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -33
  314. data/lib/active_record/define_callbacks.rb +0 -22
  315. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -19
  316. data/lib/active_record/relation/where_clause_factory.rb +0 -34
@@ -1,11 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "benchmark"
3
4
  require "set"
4
5
  require "zlib"
6
+ require "active_support/core_ext/array/access"
7
+ require "active_support/core_ext/enumerable"
5
8
  require "active_support/core_ext/module/attribute_accessors"
9
+ require "active_support/actionable_error"
6
10
 
7
11
  module ActiveRecord
8
- class MigrationError < ActiveRecordError#:nodoc:
12
+ class MigrationError < ActiveRecordError #:nodoc:
9
13
  def initialize(message = nil)
10
14
  message = "\n\n#{message}\n\n" if message
11
15
  super
@@ -16,13 +20,13 @@ module ActiveRecord
16
20
  # For example the following migration is not reversible.
17
21
  # Rolling back this migration will raise an ActiveRecord::IrreversibleMigration error.
18
22
  #
19
- # class IrreversibleMigrationExample < ActiveRecord::Migration[5.0]
23
+ # class IrreversibleMigrationExample < ActiveRecord::Migration[6.0]
20
24
  # def change
21
25
  # create_table :distributors do |t|
22
26
  # t.string :zipcode
23
27
  # end
24
28
  #
25
- # execute <<-SQL
29
+ # execute <<~SQL
26
30
  # ALTER TABLE distributors
27
31
  # ADD CONSTRAINT zipchk
28
32
  # CHECK (char_length(zipcode) = 5) NO INHERIT;
@@ -34,13 +38,13 @@ module ActiveRecord
34
38
  #
35
39
  # 1. Define <tt>#up</tt> and <tt>#down</tt> methods instead of <tt>#change</tt>:
36
40
  #
37
- # class ReversibleMigrationExample < ActiveRecord::Migration[5.0]
41
+ # class ReversibleMigrationExample < ActiveRecord::Migration[6.0]
38
42
  # def up
39
43
  # create_table :distributors do |t|
40
44
  # t.string :zipcode
41
45
  # end
42
46
  #
43
- # execute <<-SQL
47
+ # execute <<~SQL
44
48
  # ALTER TABLE distributors
45
49
  # ADD CONSTRAINT zipchk
46
50
  # CHECK (char_length(zipcode) = 5) NO INHERIT;
@@ -48,7 +52,7 @@ module ActiveRecord
48
52
  # end
49
53
  #
50
54
  # def down
51
- # execute <<-SQL
55
+ # execute <<~SQL
52
56
  # ALTER TABLE distributors
53
57
  # DROP CONSTRAINT zipchk
54
58
  # SQL
@@ -59,7 +63,7 @@ module ActiveRecord
59
63
  #
60
64
  # 2. Use the #reversible method in <tt>#change</tt> method:
61
65
  #
62
- # class ReversibleMigrationExample < ActiveRecord::Migration[5.0]
66
+ # class ReversibleMigrationExample < ActiveRecord::Migration[6.0]
63
67
  # def change
64
68
  # create_table :distributors do |t|
65
69
  # t.string :zipcode
@@ -67,7 +71,7 @@ module ActiveRecord
67
71
  #
68
72
  # reversible do |dir|
69
73
  # dir.up do
70
- # execute <<-SQL
74
+ # execute <<~SQL
71
75
  # ALTER TABLE distributors
72
76
  # ADD CONSTRAINT zipchk
73
77
  # CHECK (char_length(zipcode) = 5) NO INHERIT;
@@ -75,7 +79,7 @@ module ActiveRecord
75
79
  # end
76
80
  #
77
81
  # dir.down do
78
- # execute <<-SQL
82
+ # execute <<~SQL
79
83
  # ALTER TABLE distributors
80
84
  # DROP CONSTRAINT zipchk
81
85
  # SQL
@@ -86,7 +90,7 @@ module ActiveRecord
86
90
  class IrreversibleMigration < MigrationError
87
91
  end
88
92
 
89
- class DuplicateMigrationVersionError < MigrationError#:nodoc:
93
+ class DuplicateMigrationVersionError < MigrationError #:nodoc:
90
94
  def initialize(version = nil)
91
95
  if version
92
96
  super("Multiple migrations have the version number #{version}.")
@@ -96,7 +100,7 @@ module ActiveRecord
96
100
  end
97
101
  end
98
102
 
99
- class DuplicateMigrationNameError < MigrationError#:nodoc:
103
+ class DuplicateMigrationNameError < MigrationError #:nodoc:
100
104
  def initialize(name = nil)
101
105
  if name
102
106
  super("Multiple migrations have the name #{name}.")
@@ -116,7 +120,7 @@ module ActiveRecord
116
120
  end
117
121
  end
118
122
 
119
- class IllegalMigrationNameError < MigrationError#:nodoc:
123
+ class IllegalMigrationNameError < MigrationError #:nodoc:
120
124
  def initialize(name = nil)
121
125
  if name
122
126
  super("Illegal name for migration file: #{name}\n\t(only lower case letters, numbers, and '_' allowed).")
@@ -126,21 +130,44 @@ module ActiveRecord
126
130
  end
127
131
  end
128
132
 
129
- class PendingMigrationError < MigrationError#:nodoc:
130
- def initialize(message = nil)
131
- if !message && defined?(Rails.env)
132
- super("Migrations are pending. To resolve this issue, run:\n\n bin/rails db:migrate RAILS_ENV=#{::Rails.env}")
133
- elsif !message
134
- super("Migrations are pending. To resolve this issue, run:\n\n bin/rails db:migrate")
135
- else
136
- super
133
+ class PendingMigrationError < MigrationError #:nodoc:
134
+ include ActiveSupport::ActionableError
135
+
136
+ action "Run pending migrations" do
137
+ ActiveRecord::Tasks::DatabaseTasks.migrate
138
+
139
+ if ActiveRecord::Base.dump_schema_after_migration
140
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema(
141
+ ActiveRecord::Base.connection_db_config
142
+ )
137
143
  end
138
144
  end
145
+
146
+ def initialize(message = nil)
147
+ super(message || detailed_migration_message)
148
+ end
149
+
150
+ private
151
+ def detailed_migration_message
152
+ 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)
154
+ message += "\n\n"
155
+
156
+ pending_migrations = ActiveRecord::Base.connection.migration_context.open.pending_migrations
157
+
158
+ message += "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}\n\n"
159
+
160
+ pending_migrations.each do |pending_migration|
161
+ message += "#{pending_migration.basename}\n"
162
+ end
163
+
164
+ message
165
+ end
139
166
  end
140
167
 
141
168
  class ConcurrentMigrationError < MigrationError #:nodoc:
142
- DEFAULT_MESSAGE = "Cannot run migrations because another migration process is currently running.".freeze
143
- RELEASE_LOCK_FAILED_MESSAGE = "Failed to release advisory lock".freeze
169
+ DEFAULT_MESSAGE = "Cannot run migrations because another migration process is currently running."
170
+ RELEASE_LOCK_FAILED_MESSAGE = "Failed to release advisory lock"
144
171
 
145
172
  def initialize(message = DEFAULT_MESSAGE)
146
173
  super
@@ -160,7 +187,7 @@ module ActiveRecord
160
187
 
161
188
  class ProtectedEnvironmentError < ActiveRecordError #:nodoc:
162
189
  def initialize(env = "production")
163
- msg = "You are attempting to run a destructive action against your '#{env}' database.\n".dup
190
+ msg = +"You are attempting to run a destructive action against your '#{env}' database.\n"
164
191
  msg << "If you are sure you want to continue, run the same command with the environment variable:\n"
165
192
  msg << "DISABLE_DATABASE_ENVIRONMENT_CHECK=1"
166
193
  super(msg)
@@ -169,7 +196,7 @@ module ActiveRecord
169
196
 
170
197
  class EnvironmentMismatchError < ActiveRecordError
171
198
  def initialize(current: nil, stored: nil)
172
- msg = "You are attempting to modify a database that was last run in `#{ stored }` environment.\n".dup
199
+ msg = +"You are attempting to modify a database that was last run in `#{ stored }` environment.\n"
173
200
  msg << "You are running in `#{ current }` environment. "
174
201
  msg << "If you are sure you want to continue, first set the environment using:\n\n"
175
202
  msg << " bin/rails db:environment:set"
@@ -181,6 +208,14 @@ module ActiveRecord
181
208
  end
182
209
  end
183
210
 
211
+ class EnvironmentStorageError < ActiveRecordError # :nodoc:
212
+ def initialize
213
+ msg = +"You are attempting to store the environment in a database where metadata is disabled.\n"
214
+ msg << "Check your database configuration to see if this is intended."
215
+ super(msg)
216
+ end
217
+ end
218
+
184
219
  # = Active Record Migrations
185
220
  #
186
221
  # Migrations can manage the evolution of a schema used by several physical
@@ -193,7 +228,7 @@ module ActiveRecord
193
228
  #
194
229
  # Example of a simple migration:
195
230
  #
196
- # class AddSsl < ActiveRecord::Migration[5.0]
231
+ # class AddSsl < ActiveRecord::Migration[6.0]
197
232
  # def up
198
233
  # add_column :accounts, :ssl_enabled, :boolean, default: true
199
234
  # end
@@ -213,7 +248,7 @@ module ActiveRecord
213
248
  #
214
249
  # Example of a more complex migration that also needs to initialize data:
215
250
  #
216
- # class AddSystemSettings < ActiveRecord::Migration[5.0]
251
+ # class AddSystemSettings < ActiveRecord::Migration[6.0]
217
252
  # def up
218
253
  # create_table :system_settings do |t|
219
254
  # t.string :name
@@ -285,7 +320,7 @@ module ActiveRecord
285
320
  # +table_name+. Passing a hash containing <tt>:from</tt> and <tt>:to</tt>
286
321
  # as +default_or_changes+ will make this change reversible in the migration.
287
322
  # * <tt>change_column_null(table_name, column_name, null, default = nil)</tt>:
288
- # Sets or removes a +NOT NULL+ constraint on +column_name+. The +null+ flag
323
+ # Sets or removes a <tt>NOT NULL</tt> constraint on +column_name+. The +null+ flag
289
324
  # indicates whether the value can be +NULL+. See
290
325
  # ActiveRecord::ConnectionAdapters::SchemaStatements#change_column_null for
291
326
  # details.
@@ -307,7 +342,7 @@ module ActiveRecord
307
342
  # named +column_name+ from the table called +table_name+.
308
343
  # * <tt>remove_columns(table_name, *column_names)</tt>: Removes the given
309
344
  # columns from the table definition.
310
- # * <tt>remove_foreign_key(from_table, options_or_to_table)</tt>: Removes the
345
+ # * <tt>remove_foreign_key(from_table, to_table = nil, **options)</tt>: Removes the
311
346
  # given foreign key from the table called +table_name+.
312
347
  # * <tt>remove_index(table_name, column: column_names)</tt>: Removes the index
313
348
  # specified by +column_names+.
@@ -329,7 +364,7 @@ module ActiveRecord
329
364
  # The Rails package has several tools to help create and apply migrations.
330
365
  #
331
366
  # To generate a new migration, you can use
332
- # rails generate migration MyNewMigration
367
+ # bin/rails generate migration MyNewMigration
333
368
  #
334
369
  # where MyNewMigration is the name of your migration. The generator will
335
370
  # create an empty migration file <tt>timestamp_my_new_migration.rb</tt>
@@ -338,41 +373,36 @@ module ActiveRecord
338
373
  #
339
374
  # There is a special syntactic shortcut to generate migrations that add fields to a table.
340
375
  #
341
- # rails generate migration add_fieldname_to_tablename fieldname:string
376
+ # bin/rails generate migration add_fieldname_to_tablename fieldname:string
342
377
  #
343
378
  # This will generate the file <tt>timestamp_add_fieldname_to_tablename.rb</tt>, which will look like this:
344
- # class AddFieldnameToTablename < ActiveRecord::Migration[5.0]
379
+ # class AddFieldnameToTablename < ActiveRecord::Migration[6.0]
345
380
  # def change
346
381
  # add_column :tablenames, :fieldname, :string
347
382
  # end
348
383
  # end
349
384
  #
350
385
  # To run migrations against the currently configured database, use
351
- # <tt>rails db:migrate</tt>. This will update the database by running all of the
386
+ # <tt>bin/rails db:migrate</tt>. This will update the database by running all of the
352
387
  # pending migrations, creating the <tt>schema_migrations</tt> table
353
388
  # (see "About the schema_migrations table" section below) if missing. It will also
354
- # invoke the db:schema:dump task, which will update your db/schema.rb file
389
+ # invoke the db:schema:dump command, which will update your db/schema.rb file
355
390
  # to match the structure of your database.
356
391
  #
357
392
  # To roll the database back to a previous migration version, use
358
- # <tt>rails db:rollback VERSION=X</tt> where <tt>X</tt> is the version to which
393
+ # <tt>bin/rails db:rollback VERSION=X</tt> where <tt>X</tt> is the version to which
359
394
  # you wish to downgrade. Alternatively, you can also use the STEP option if you
360
- # wish to rollback last few migrations. <tt>rails db:rollback STEP=2</tt> will rollback
395
+ # wish to rollback last few migrations. <tt>bin/rails db:rollback STEP=2</tt> will rollback
361
396
  # the latest two migrations.
362
397
  #
363
398
  # If any of the migrations throw an <tt>ActiveRecord::IrreversibleMigration</tt> exception,
364
399
  # that step will fail and you'll have some manual work to do.
365
400
  #
366
- # == Database support
367
- #
368
- # Migrations are currently supported in MySQL, PostgreSQL, SQLite,
369
- # SQL Server, and Oracle (all supported databases except DB2).
370
- #
371
401
  # == More examples
372
402
  #
373
403
  # Not all migrations change the schema. Some just fix the data:
374
404
  #
375
- # class RemoveEmptyTags < ActiveRecord::Migration[5.0]
405
+ # class RemoveEmptyTags < ActiveRecord::Migration[6.0]
376
406
  # def up
377
407
  # Tag.all.each { |tag| tag.destroy if tag.pages.empty? }
378
408
  # end
@@ -385,7 +415,7 @@ module ActiveRecord
385
415
  #
386
416
  # Others remove columns when they migrate up instead of down:
387
417
  #
388
- # class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[5.0]
418
+ # class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[6.0]
389
419
  # def up
390
420
  # remove_column :items, :incomplete_items_count
391
421
  # remove_column :items, :completed_items_count
@@ -399,7 +429,7 @@ module ActiveRecord
399
429
  #
400
430
  # And sometimes you need to do something in SQL not abstracted directly by migrations:
401
431
  #
402
- # class MakeJoinUnique < ActiveRecord::Migration[5.0]
432
+ # class MakeJoinUnique < ActiveRecord::Migration[6.0]
403
433
  # def up
404
434
  # execute "ALTER TABLE `pages_linked_pages` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`)"
405
435
  # end
@@ -416,7 +446,7 @@ module ActiveRecord
416
446
  # <tt>Base#reset_column_information</tt> in order to ensure that the model has the
417
447
  # latest column data from after the new column was added. Example:
418
448
  #
419
- # class AddPeopleSalary < ActiveRecord::Migration[5.0]
449
+ # class AddPeopleSalary < ActiveRecord::Migration[6.0]
420
450
  # def up
421
451
  # add_column :people, :salary, :integer
422
452
  # Person.reset_column_information
@@ -474,7 +504,7 @@ module ActiveRecord
474
504
  # To define a reversible migration, define the +change+ method in your
475
505
  # migration like this:
476
506
  #
477
- # class TenderloveMigration < ActiveRecord::Migration[5.0]
507
+ # class TenderloveMigration < ActiveRecord::Migration[6.0]
478
508
  # def change
479
509
  # create_table(:horses) do |t|
480
510
  # t.column :content, :text
@@ -486,9 +516,9 @@ module ActiveRecord
486
516
  # This migration will create the horses table for you on the way up, and
487
517
  # automatically figure out how to drop the table on the way down.
488
518
  #
489
- # Some commands like +remove_column+ cannot be reversed. If you care to
490
- # define how to move up and down in these cases, you should define the +up+
491
- # and +down+ methods as before.
519
+ # Some commands cannot be reversed. If you care to define how to move up
520
+ # and down in these cases, you should define the +up+ and +down+ methods
521
+ # as before.
492
522
  #
493
523
  # If a command cannot be reversed, an
494
524
  # <tt>ActiveRecord::IrreversibleMigration</tt> exception will be raised when
@@ -504,7 +534,7 @@ module ActiveRecord
504
534
  # can't execute inside a transaction though, and for these situations
505
535
  # you can turn the automatic transactions off.
506
536
  #
507
- # class ChangeEnum < ActiveRecord::Migration[5.0]
537
+ # class ChangeEnum < ActiveRecord::Migration[6.0]
508
538
  # disable_ddl_transaction!
509
539
  #
510
540
  # def up
@@ -517,12 +547,13 @@ module ActiveRecord
517
547
  class Migration
518
548
  autoload :CommandRecorder, "active_record/migration/command_recorder"
519
549
  autoload :Compatibility, "active_record/migration/compatibility"
550
+ autoload :JoinTable, "active_record/migration/join_table"
520
551
 
521
552
  # This must be defined before the inherited hook, below
522
- class Current < Migration # :nodoc:
553
+ class Current < Migration #:nodoc:
523
554
  end
524
555
 
525
- def self.inherited(subclass) # :nodoc:
556
+ def self.inherited(subclass) #:nodoc:
526
557
  super
527
558
  if subclass.superclass == Migration
528
559
  raise StandardError, "Directly inheriting from ActiveRecord::Migration is not supported. " \
@@ -540,26 +571,41 @@ module ActiveRecord
540
571
  ActiveRecord::VERSION::STRING.to_f
541
572
  end
542
573
 
543
- MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/ # :nodoc:
574
+ MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/ #:nodoc:
544
575
 
545
576
  # This class is used to verify that all migrations have been run before
546
577
  # loading a web page if <tt>config.active_record.migration_error</tt> is set to :page_load
547
578
  class CheckPending
548
- def initialize(app)
579
+ def initialize(app, file_watcher: ActiveSupport::FileUpdateChecker)
549
580
  @app = app
550
- @last_check = 0
581
+ @needs_check = true
582
+ @mutex = Mutex.new
583
+ @file_watcher = file_watcher
551
584
  end
552
585
 
553
586
  def call(env)
554
- mtime = ActiveRecord::Base.connection.migration_context.last_migration.mtime.to_i
555
- if @last_check < mtime
556
- ActiveRecord::Migration.check_pending!(connection)
557
- @last_check = mtime
587
+ @mutex.synchronize do
588
+ @watcher ||= build_watcher do
589
+ @needs_check = true
590
+ ActiveRecord::Migration.check_pending!(connection)
591
+ @needs_check = false
592
+ end
593
+
594
+ if @needs_check
595
+ @watcher.execute
596
+ else
597
+ @watcher.execute_if_updated
598
+ end
558
599
  end
600
+
559
601
  @app.call(env)
560
602
  end
561
603
 
562
604
  private
605
+ def build_watcher(&block)
606
+ paths = Array(connection.migration_context.migrations_paths)
607
+ @file_watcher.new([], paths.index_with(["rb"]), &block)
608
+ end
563
609
 
564
610
  def connection
565
611
  ActiveRecord::Base.connection
@@ -567,10 +613,10 @@ module ActiveRecord
567
613
  end
568
614
 
569
615
  class << self
570
- attr_accessor :delegate # :nodoc:
571
- attr_accessor :disable_ddl_transaction # :nodoc:
616
+ attr_accessor :delegate #:nodoc:
617
+ attr_accessor :disable_ddl_transaction #:nodoc:
572
618
 
573
- def nearest_delegate # :nodoc:
619
+ def nearest_delegate #:nodoc:
574
620
  delegate || superclass.nearest_delegate
575
621
  end
576
622
 
@@ -580,29 +626,38 @@ module ActiveRecord
580
626
  end
581
627
 
582
628
  def load_schema_if_pending!
583
- if Base.connection.migration_context.needs_migration? || !Base.connection.migration_context.any_migrations?
629
+ current_db_config = Base.connection_db_config
630
+ all_configs = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env)
631
+
632
+ needs_update = !all_configs.all? do |db_config|
633
+ Tasks::DatabaseTasks.schema_up_to_date?(db_config, ActiveRecord::Base.schema_format)
634
+ end
635
+
636
+ if needs_update
584
637
  # Roundtrip to Rake to allow plugins to hook into database initialization.
585
638
  root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
586
639
  FileUtils.cd(root) do
587
- current_config = Base.connection_config
588
640
  Base.clear_all_connections!
589
641
  system("bin/rails db:test:prepare")
590
- # Establish a new connection, the old database may be gone (db:test:prepare uses purge)
591
- Base.establish_connection(current_config)
592
642
  end
593
- check_pending!
594
643
  end
644
+
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!
595
649
  end
596
650
 
597
- def maintain_test_schema! # :nodoc:
651
+ def maintain_test_schema! #:nodoc:
598
652
  if ActiveRecord::Base.maintain_test_schema
599
653
  suppress_messages { load_schema_if_pending! }
600
654
  end
601
655
  end
602
656
 
603
- def method_missing(name, *args, &block) # :nodoc:
657
+ def method_missing(name, *args, &block) #:nodoc:
604
658
  nearest_delegate.send(name, *args, &block)
605
659
  end
660
+ ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
606
661
 
607
662
  def migrate(direction)
608
663
  new.migrate direction
@@ -617,7 +672,7 @@ module ActiveRecord
617
672
  end
618
673
  end
619
674
 
620
- def disable_ddl_transaction # :nodoc:
675
+ def disable_ddl_transaction #:nodoc:
621
676
  self.class.disable_ddl_transaction
622
677
  end
623
678
 
@@ -641,7 +696,7 @@ module ActiveRecord
641
696
  # and create the table 'apples' on the way up, and the reverse
642
697
  # on the way down.
643
698
  #
644
- # class FixTLMigration < ActiveRecord::Migration[5.0]
699
+ # class FixTLMigration < ActiveRecord::Migration[6.0]
645
700
  # def change
646
701
  # revert do
647
702
  # create_table(:horses) do |t|
@@ -658,9 +713,9 @@ module ActiveRecord
658
713
  # Or equivalently, if +TenderloveMigration+ is defined as in the
659
714
  # documentation for Migration:
660
715
  #
661
- # require_relative '20121212123456_tenderlove_migration'
716
+ # require_relative "20121212123456_tenderlove_migration"
662
717
  #
663
- # class FixupTLMigration < ActiveRecord::Migration[5.0]
718
+ # class FixupTLMigration < ActiveRecord::Migration[6.0]
664
719
  # def change
665
720
  # revert TenderloveMigration
666
721
  #
@@ -677,15 +732,13 @@ module ActiveRecord
677
732
  if connection.respond_to? :revert
678
733
  connection.revert { yield }
679
734
  else
680
- recorder = CommandRecorder.new(connection)
735
+ recorder = command_recorder
681
736
  @connection = recorder
682
737
  suppress_messages do
683
738
  connection.revert { yield }
684
739
  end
685
740
  @connection = recorder.delegate
686
- recorder.commands.each do |cmd, args, block|
687
- send(cmd, *args, &block)
688
- end
741
+ recorder.replay(self)
689
742
  end
690
743
  end
691
744
  end
@@ -694,7 +747,7 @@ module ActiveRecord
694
747
  connection.respond_to?(:reverting) && connection.reverting
695
748
  end
696
749
 
697
- ReversibleBlockHelper = Struct.new(:reverting) do # :nodoc:
750
+ ReversibleBlockHelper = Struct.new(:reverting) do #:nodoc:
698
751
  def up
699
752
  yield unless reverting
700
753
  end
@@ -713,7 +766,7 @@ module ActiveRecord
713
766
  # when the three columns 'first_name', 'last_name' and 'full_name' exist,
714
767
  # even when migrating down:
715
768
  #
716
- # class SplitNameMigration < ActiveRecord::Migration[5.0]
769
+ # class SplitNameMigration < ActiveRecord::Migration[6.0]
717
770
  # def change
718
771
  # add_column :users, :first_name, :string
719
772
  # add_column :users, :last_name, :string
@@ -741,7 +794,7 @@ module ActiveRecord
741
794
  # In the following example, the new column +published+ will be given
742
795
  # the value +true+ for all existing records.
743
796
  #
744
- # class AddPublishedToPosts < ActiveRecord::Migration[5.2]
797
+ # class AddPublishedToPosts < ActiveRecord::Migration[6.0]
745
798
  # def change
746
799
  # add_column :posts, :published, :boolean, default: false
747
800
  # up_only do
@@ -814,7 +867,7 @@ module ActiveRecord
814
867
  change
815
868
  end
816
869
  else
817
- send(direction)
870
+ public_send(direction)
818
871
  end
819
872
  ensure
820
873
  @connection = nil
@@ -830,10 +883,14 @@ module ActiveRecord
830
883
  write "== %s %s" % [text, "=" * length]
831
884
  end
832
885
 
886
+ # Takes a message argument and outputs it as is.
887
+ # A second boolean argument can be passed to specify whether to indent or not.
833
888
  def say(message, subitem = false)
834
889
  write "#{subitem ? " ->" : "--"} #{message}"
835
890
  end
836
891
 
892
+ # Outputs text along with how long it took to run its block.
893
+ # If the block returns an integer it assumes it is the number of rows affected.
837
894
  def say_with_time(message)
838
895
  say(message)
839
896
  result = nil
@@ -843,6 +900,7 @@ module ActiveRecord
843
900
  result
844
901
  end
845
902
 
903
+ # Takes a block as an argument and suppresses any output generated by the block.
846
904
  def suppress_messages
847
905
  save, self.verbose = verbose, false
848
906
  yield
@@ -871,21 +929,23 @@ module ActiveRecord
871
929
  connection.send(method, *arguments, &block)
872
930
  end
873
931
  end
932
+ ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
874
933
 
875
934
  def copy(destination, sources, options = {})
876
935
  copied = []
936
+ schema_migration = options[:schema_migration] || ActiveRecord::SchemaMigration
877
937
 
878
938
  FileUtils.mkdir_p(destination) unless File.exist?(destination)
879
939
 
880
- destination_migrations = ActiveRecord::MigrationContext.new(destination).migrations
940
+ destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration).migrations
881
941
  last = destination_migrations.last
882
942
  sources.each do |scope, path|
883
- source_migrations = ActiveRecord::MigrationContext.new(path).migrations
943
+ source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration).migrations
884
944
 
885
945
  source_migrations.each do |migration|
886
946
  source = File.binread(migration.filename)
887
947
  inserted_comment = "# This migration comes from #{scope} (originally #{migration.version})\n"
888
- magic_comments = "".dup
948
+ magic_comments = +""
889
949
  loop do
890
950
  # If we have a magic comment in the original migration,
891
951
  # insert our comment after the first newline(end of the magic comment line)
@@ -956,6 +1016,10 @@ module ActiveRecord
956
1016
  yield
957
1017
  end
958
1018
  end
1019
+
1020
+ def command_recorder
1021
+ CommandRecorder.new(connection)
1022
+ end
959
1023
  end
960
1024
 
961
1025
  # MigrationProxy is used to defer loading of the actual migration classes
@@ -970,14 +1034,9 @@ module ActiveRecord
970
1034
  File.basename(filename)
971
1035
  end
972
1036
 
973
- def mtime
974
- File.mtime filename
975
- end
976
-
977
1037
  delegate :migrate, :announce, :write, :disable_ddl_transaction, to: :migration
978
1038
 
979
1039
  private
980
-
981
1040
  def migration
982
1041
  @migration ||= load_migration
983
1042
  end
@@ -988,21 +1047,12 @@ module ActiveRecord
988
1047
  end
989
1048
  end
990
1049
 
991
- class NullMigration < MigrationProxy #:nodoc:
992
- def initialize
993
- super(nil, 0, nil, nil)
994
- end
1050
+ class MigrationContext #:nodoc:
1051
+ attr_reader :migrations_paths, :schema_migration
995
1052
 
996
- def mtime
997
- 0
998
- end
999
- end
1000
-
1001
- class MigrationContext # :nodoc:
1002
- attr_reader :migrations_paths
1003
-
1004
- def initialize(migrations_paths)
1053
+ def initialize(migrations_paths, schema_migration)
1005
1054
  @migrations_paths = migrations_paths
1055
+ @schema_migration = schema_migration
1006
1056
  end
1007
1057
 
1008
1058
  def migrate(target_version = nil, &block)
@@ -1033,7 +1083,7 @@ module ActiveRecord
1033
1083
  migrations
1034
1084
  end
1035
1085
 
1036
- Migrator.new(:up, selected_migrations, target_version).migrate
1086
+ Migrator.new(:up, selected_migrations, schema_migration, target_version).migrate
1037
1087
  end
1038
1088
 
1039
1089
  def down(target_version = nil)
@@ -1043,20 +1093,20 @@ module ActiveRecord
1043
1093
  migrations
1044
1094
  end
1045
1095
 
1046
- Migrator.new(:down, selected_migrations, target_version).migrate
1096
+ Migrator.new(:down, selected_migrations, schema_migration, target_version).migrate
1047
1097
  end
1048
1098
 
1049
1099
  def run(direction, target_version)
1050
- Migrator.new(direction, migrations, target_version).run
1100
+ Migrator.new(direction, migrations, schema_migration, target_version).run
1051
1101
  end
1052
1102
 
1053
1103
  def open
1054
- Migrator.new(:up, migrations, nil)
1104
+ Migrator.new(:up, migrations, schema_migration)
1055
1105
  end
1056
1106
 
1057
1107
  def get_all_versions
1058
- if SchemaMigration.table_exists?
1059
- SchemaMigration.all_versions.map(&:to_i)
1108
+ if schema_migration.table_exists?
1109
+ schema_migration.all_versions.map(&:to_i)
1060
1110
  else
1061
1111
  []
1062
1112
  end
@@ -1075,14 +1125,6 @@ module ActiveRecord
1075
1125
  migrations.any?
1076
1126
  end
1077
1127
 
1078
- def last_migration #:nodoc:
1079
- migrations.last || NullMigration.new
1080
- end
1081
-
1082
- def parse_migration_filename(filename) # :nodoc:
1083
- File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
1084
- end
1085
-
1086
1128
  def migrations
1087
1129
  migrations = migration_files.map do |file|
1088
1130
  version, name, scope = parse_migration_filename(file)
@@ -1097,12 +1139,12 @@ module ActiveRecord
1097
1139
  end
1098
1140
 
1099
1141
  def migrations_status
1100
- db_list = ActiveRecord::SchemaMigration.normalized_versions
1142
+ db_list = schema_migration.normalized_versions
1101
1143
 
1102
1144
  file_list = migration_files.map do |file|
1103
1145
  version, name, scope = parse_migration_filename(file)
1104
1146
  raise IllegalMigrationNameError.new(file) unless version
1105
- version = ActiveRecord::SchemaMigration.normalize_migration_number(version)
1147
+ version = schema_migration.normalize_migration_number(version)
1106
1148
  status = db_list.delete(version) ? "up" : "down"
1107
1149
  [status, version, (name + scope).humanize]
1108
1150
  end.compact
@@ -1114,11 +1156,6 @@ module ActiveRecord
1114
1156
  (db_list + file_list).sort_by { |_, version, _| version }
1115
1157
  end
1116
1158
 
1117
- def migration_files
1118
- paths = Array(migrations_paths)
1119
- Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
1120
- end
1121
-
1122
1159
  def current_environment
1123
1160
  ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
1124
1161
  end
@@ -1128,6 +1165,7 @@ module ActiveRecord
1128
1165
  end
1129
1166
 
1130
1167
  def last_stored_environment
1168
+ return nil unless ActiveRecord::InternalMetadata.enabled?
1131
1169
  return nil if current_version == 0
1132
1170
  raise NoEnvironmentInSchemaError unless ActiveRecord::InternalMetadata.table_exists?
1133
1171
 
@@ -1137,8 +1175,17 @@ module ActiveRecord
1137
1175
  end
1138
1176
 
1139
1177
  private
1178
+ def migration_files
1179
+ paths = Array(migrations_paths)
1180
+ Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
1181
+ end
1182
+
1183
+ def parse_migration_filename(filename)
1184
+ File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
1185
+ end
1186
+
1140
1187
  def move(direction, steps)
1141
- migrator = Migrator.new(direction, migrations)
1188
+ migrator = Migrator.new(direction, migrations, schema_migration)
1142
1189
 
1143
1190
  if current_version != 0 && !migrator.current_migration
1144
1191
  raise UnknownMigrationVersionError.new(current_version)
@@ -1153,7 +1200,7 @@ module ActiveRecord
1153
1200
 
1154
1201
  finish = migrator.migrations[start_index + steps]
1155
1202
  version = finish ? finish.version : 0
1156
- send(direction, version)
1203
+ public_send(direction, version)
1157
1204
  end
1158
1205
  end
1159
1206
 
@@ -1161,30 +1208,24 @@ module ActiveRecord
1161
1208
  class << self
1162
1209
  attr_accessor :migrations_paths
1163
1210
 
1164
- def migrations_path=(path)
1165
- ActiveSupport::Deprecation.warn \
1166
- "`ActiveRecord::Migrator.migrations_path=` is now deprecated and will be removed in Rails 6.0. " \
1167
- "You can set the `migrations_paths` on the `connection` instead through the `database.yml`."
1168
- self.migrations_paths = [path]
1169
- end
1170
-
1171
1211
  # For cases where a table doesn't exist like loading from schema cache
1172
1212
  def current_version
1173
- MigrationContext.new(migrations_paths).current_version
1213
+ MigrationContext.new(migrations_paths, SchemaMigration).current_version
1174
1214
  end
1175
1215
  end
1176
1216
 
1177
1217
  self.migrations_paths = ["db/migrate"]
1178
1218
 
1179
- def initialize(direction, migrations, target_version = nil)
1219
+ def initialize(direction, migrations, schema_migration, target_version = nil)
1180
1220
  @direction = direction
1181
1221
  @target_version = target_version
1182
1222
  @migrated_versions = nil
1183
1223
  @migrations = migrations
1224
+ @schema_migration = schema_migration
1184
1225
 
1185
1226
  validate(@migrations)
1186
1227
 
1187
- ActiveRecord::SchemaMigration.create_table
1228
+ @schema_migration.create_table
1188
1229
  ActiveRecord::InternalMetadata.create_table
1189
1230
  end
1190
1231
 
@@ -1238,16 +1279,15 @@ module ActiveRecord
1238
1279
  end
1239
1280
 
1240
1281
  def load_migrated
1241
- @migrated_versions = Set.new(Base.connection.migration_context.get_all_versions)
1282
+ @migrated_versions = Set.new(@schema_migration.all_versions.map(&:to_i))
1242
1283
  end
1243
1284
 
1244
1285
  private
1245
-
1246
1286
  # Used for running a specific migration.
1247
1287
  def run_without_lock
1248
1288
  migration = migrations.detect { |m| m.version == @target_version }
1249
1289
  raise UnknownMigrationVersionError.new(@target_version) if migration.nil?
1250
- result = execute_migration_in_transaction(migration, @direction)
1290
+ result = execute_migration_in_transaction(migration)
1251
1291
 
1252
1292
  record_environment
1253
1293
  result
@@ -1259,10 +1299,7 @@ module ActiveRecord
1259
1299
  raise UnknownMigrationVersionError.new(@target_version)
1260
1300
  end
1261
1301
 
1262
- result = runnable.each do |migration|
1263
- execute_migration_in_transaction(migration, @direction)
1264
- end
1265
-
1302
+ result = runnable.each(&method(:execute_migration_in_transaction))
1266
1303
  record_environment
1267
1304
  result
1268
1305
  end
@@ -1282,18 +1319,18 @@ module ActiveRecord
1282
1319
  @target_version && @target_version != 0 && !target
1283
1320
  end
1284
1321
 
1285
- def execute_migration_in_transaction(migration, direction)
1322
+ def execute_migration_in_transaction(migration)
1286
1323
  return if down? && !migrated.include?(migration.version.to_i)
1287
1324
  return if up? && migrated.include?(migration.version.to_i)
1288
1325
 
1289
1326
  Base.logger.info "Migrating to #{migration.name} (#{migration.version})" if Base.logger
1290
1327
 
1291
1328
  ddl_transaction(migration) do
1292
- migration.migrate(direction)
1329
+ migration.migrate(@direction)
1293
1330
  record_version_state_after_migrating(migration.version)
1294
1331
  end
1295
1332
  rescue => e
1296
- msg = "An error has occurred, ".dup
1333
+ msg = +"An error has occurred, "
1297
1334
  msg << "this and " if use_transaction?(migration)
1298
1335
  msg << "all later migrations canceled:\n\n#{e}"
1299
1336
  raise StandardError, msg, e.backtrace
@@ -1322,10 +1359,10 @@ module ActiveRecord
1322
1359
  def record_version_state_after_migrating(version)
1323
1360
  if down?
1324
1361
  migrated.delete(version)
1325
- ActiveRecord::SchemaMigration.where(version: version.to_s).delete_all
1362
+ @schema_migration.delete_by(version: version.to_s)
1326
1363
  else
1327
1364
  migrated << version
1328
- ActiveRecord::SchemaMigration.create!(version: version.to_s)
1365
+ @schema_migration.create!(version: version.to_s)
1329
1366
  end
1330
1367
  end
1331
1368
 
@@ -1351,24 +1388,36 @@ module ActiveRecord
1351
1388
  end
1352
1389
 
1353
1390
  def use_advisory_lock?
1354
- Base.connection.supports_advisory_locks?
1391
+ Base.connection.advisory_locks_enabled?
1355
1392
  end
1356
1393
 
1357
1394
  def with_advisory_lock
1358
1395
  lock_id = generate_migrator_advisory_lock_id
1359
- connection = Base.connection
1360
- got_lock = connection.get_advisory_lock(lock_id)
1361
- raise ConcurrentMigrationError unless got_lock
1362
- load_migrated # reload schema_migrations to be sure it wasn't changed by another process before we got the lock
1363
- yield
1364
- ensure
1365
- if got_lock && !connection.release_advisory_lock(lock_id)
1366
- raise ConcurrentMigrationError.new(
1367
- ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE
1368
- )
1396
+
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
1369
1408
  end
1370
1409
  end
1371
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) }
1417
+ ensure
1418
+ pool&.disconnect!
1419
+ end
1420
+
1372
1421
  MIGRATOR_SALT = 2053462845
1373
1422
  def generate_migrator_advisory_lock_id
1374
1423
  db_name_hash = Zlib.crc32(Base.connection.current_database)