activerecord 5.2.8.1 → 6.1.7.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (316) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1347 -624
  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 +16 -7
  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 +107 -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 +73 -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 +225 -121
  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 +341 -99
  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 +4 -4
  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 +113 -74
  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 +478 -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 +94 -10
  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 +291 -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 +118 -32
  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)