activerecord 7.2.2.1 → 8.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +564 -753
  3. data/README.rdoc +2 -2
  4. data/lib/active_record/association_relation.rb +2 -1
  5. data/lib/active_record/associations/alias_tracker.rb +6 -4
  6. data/lib/active_record/associations/association.rb +35 -11
  7. data/lib/active_record/associations/belongs_to_association.rb +18 -2
  8. data/lib/active_record/associations/builder/association.rb +23 -11
  9. data/lib/active_record/associations/builder/belongs_to.rb +17 -4
  10. data/lib/active_record/associations/builder/collection_association.rb +7 -3
  11. data/lib/active_record/associations/builder/has_one.rb +1 -1
  12. data/lib/active_record/associations/builder/singular_association.rb +33 -5
  13. data/lib/active_record/associations/collection_association.rb +10 -8
  14. data/lib/active_record/associations/collection_proxy.rb +22 -4
  15. data/lib/active_record/associations/deprecation.rb +88 -0
  16. data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
  17. data/lib/active_record/associations/errors.rb +3 -0
  18. data/lib/active_record/associations/has_many_through_association.rb +3 -2
  19. data/lib/active_record/associations/join_dependency/join_association.rb +25 -27
  20. data/lib/active_record/associations/join_dependency.rb +4 -2
  21. data/lib/active_record/associations/preloader/association.rb +2 -2
  22. data/lib/active_record/associations/preloader/batch.rb +7 -1
  23. data/lib/active_record/associations/preloader/branch.rb +1 -0
  24. data/lib/active_record/associations/singular_association.rb +8 -3
  25. data/lib/active_record/associations.rb +192 -24
  26. data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
  27. data/lib/active_record/attribute_methods/primary_key.rb +4 -8
  28. data/lib/active_record/attribute_methods/query.rb +34 -0
  29. data/lib/active_record/attribute_methods/serialization.rb +17 -4
  30. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -14
  31. data/lib/active_record/attribute_methods.rb +24 -19
  32. data/lib/active_record/attributes.rb +40 -26
  33. data/lib/active_record/autosave_association.rb +91 -39
  34. data/lib/active_record/base.rb +3 -4
  35. data/lib/active_record/coders/json.rb +14 -5
  36. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +35 -28
  37. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +16 -4
  38. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +51 -13
  39. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +458 -117
  40. data/lib/active_record/connection_adapters/abstract/database_statements.rb +136 -74
  41. data/lib/active_record/connection_adapters/abstract/query_cache.rb +44 -11
  42. data/lib/active_record/connection_adapters/abstract/quoting.rb +16 -25
  43. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +11 -7
  44. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +37 -36
  45. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -1
  46. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +122 -29
  47. data/lib/active_record/connection_adapters/abstract/transaction.rb +40 -8
  48. data/lib/active_record/connection_adapters/abstract_adapter.rb +175 -87
  49. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +77 -58
  50. data/lib/active_record/connection_adapters/column.rb +17 -4
  51. data/lib/active_record/connection_adapters/mysql/database_statements.rb +4 -4
  52. data/lib/active_record/connection_adapters/mysql/quoting.rb +7 -9
  53. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +2 -0
  54. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +41 -10
  55. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +73 -46
  56. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +89 -94
  57. data/lib/active_record/connection_adapters/mysql2_adapter.rb +10 -11
  58. data/lib/active_record/connection_adapters/pool_config.rb +7 -7
  59. data/lib/active_record/connection_adapters/postgresql/column.rb +4 -0
  60. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +76 -45
  61. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +3 -3
  62. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
  63. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +1 -1
  64. data/lib/active_record/connection_adapters/postgresql/quoting.rb +21 -10
  65. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -4
  66. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +9 -17
  67. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +28 -45
  68. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +69 -32
  69. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +140 -64
  70. data/lib/active_record/connection_adapters/postgresql_adapter.rb +83 -105
  71. data/lib/active_record/connection_adapters/schema_cache.rb +3 -5
  72. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +90 -98
  73. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +13 -8
  74. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +0 -6
  75. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +27 -2
  76. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +13 -13
  77. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +112 -42
  78. data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
  79. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +38 -67
  80. data/lib/active_record/connection_adapters/trilogy_adapter.rb +2 -19
  81. data/lib/active_record/connection_adapters.rb +1 -56
  82. data/lib/active_record/connection_handling.rb +37 -10
  83. data/lib/active_record/core.rb +61 -25
  84. data/lib/active_record/counter_cache.rb +34 -9
  85. data/lib/active_record/database_configurations/connection_url_resolver.rb +3 -1
  86. data/lib/active_record/database_configurations/database_config.rb +9 -1
  87. data/lib/active_record/database_configurations/hash_config.rb +67 -9
  88. data/lib/active_record/database_configurations/url_config.rb +13 -3
  89. data/lib/active_record/database_configurations.rb +7 -3
  90. data/lib/active_record/delegated_type.rb +19 -19
  91. data/lib/active_record/dynamic_matchers.rb +54 -69
  92. data/lib/active_record/encryption/config.rb +3 -1
  93. data/lib/active_record/encryption/encryptable_record.rb +9 -9
  94. data/lib/active_record/encryption/encrypted_attribute_type.rb +12 -3
  95. data/lib/active_record/encryption/encryptor.rb +49 -28
  96. data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
  97. data/lib/active_record/encryption/scheme.rb +9 -2
  98. data/lib/active_record/enum.rb +46 -42
  99. data/lib/active_record/errors.rb +36 -12
  100. data/lib/active_record/explain.rb +1 -1
  101. data/lib/active_record/explain_registry.rb +51 -2
  102. data/lib/active_record/filter_attribute_handler.rb +73 -0
  103. data/lib/active_record/fixture_set/table_row.rb +19 -2
  104. data/lib/active_record/fixtures.rb +2 -4
  105. data/lib/active_record/future_result.rb +13 -9
  106. data/lib/active_record/gem_version.rb +3 -3
  107. data/lib/active_record/inheritance.rb +1 -1
  108. data/lib/active_record/insert_all.rb +12 -7
  109. data/lib/active_record/locking/optimistic.rb +8 -1
  110. data/lib/active_record/locking/pessimistic.rb +5 -0
  111. data/lib/active_record/log_subscriber.rb +3 -13
  112. data/lib/active_record/middleware/shard_selector.rb +34 -17
  113. data/lib/active_record/migration/command_recorder.rb +44 -11
  114. data/lib/active_record/migration/compatibility.rb +37 -24
  115. data/lib/active_record/migration/default_schema_versions_formatter.rb +30 -0
  116. data/lib/active_record/migration.rb +50 -43
  117. data/lib/active_record/model_schema.rb +38 -13
  118. data/lib/active_record/nested_attributes.rb +6 -6
  119. data/lib/active_record/persistence.rb +162 -133
  120. data/lib/active_record/query_cache.rb +22 -15
  121. data/lib/active_record/query_logs.rb +104 -52
  122. data/lib/active_record/query_logs_formatter.rb +17 -28
  123. data/lib/active_record/querying.rb +12 -12
  124. data/lib/active_record/railtie.rb +37 -32
  125. data/lib/active_record/railties/controller_runtime.rb +11 -6
  126. data/lib/active_record/railties/databases.rake +26 -37
  127. data/lib/active_record/railties/job_checkpoints.rb +15 -0
  128. data/lib/active_record/railties/job_runtime.rb +10 -11
  129. data/lib/active_record/reflection.rb +53 -21
  130. data/lib/active_record/relation/batches/batch_enumerator.rb +4 -3
  131. data/lib/active_record/relation/batches.rb +147 -73
  132. data/lib/active_record/relation/calculations.rb +80 -63
  133. data/lib/active_record/relation/delegation.rb +25 -15
  134. data/lib/active_record/relation/finder_methods.rb +54 -37
  135. data/lib/active_record/relation/merger.rb +8 -8
  136. data/lib/active_record/relation/predicate_builder/association_query_value.rb +11 -9
  137. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +8 -8
  138. data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
  139. data/lib/active_record/relation/predicate_builder.rb +22 -7
  140. data/lib/active_record/relation/query_attribute.rb +4 -2
  141. data/lib/active_record/relation/query_methods.rb +156 -95
  142. data/lib/active_record/relation/spawn_methods.rb +7 -7
  143. data/lib/active_record/relation/where_clause.rb +10 -11
  144. data/lib/active_record/relation.rb +122 -80
  145. data/lib/active_record/result.rb +109 -24
  146. data/lib/active_record/runtime_registry.rb +42 -58
  147. data/lib/active_record/sanitization.rb +9 -6
  148. data/lib/active_record/schema_dumper.rb +47 -22
  149. data/lib/active_record/schema_migration.rb +2 -1
  150. data/lib/active_record/scoping/named.rb +5 -2
  151. data/lib/active_record/scoping.rb +0 -1
  152. data/lib/active_record/secure_token.rb +3 -3
  153. data/lib/active_record/signed_id.rb +47 -18
  154. data/lib/active_record/statement_cache.rb +24 -20
  155. data/lib/active_record/store.rb +51 -22
  156. data/lib/active_record/structured_event_subscriber.rb +85 -0
  157. data/lib/active_record/table_metadata.rb +6 -23
  158. data/lib/active_record/tasks/abstract_tasks.rb +76 -0
  159. data/lib/active_record/tasks/database_tasks.rb +85 -85
  160. data/lib/active_record/tasks/mysql_database_tasks.rb +3 -42
  161. data/lib/active_record/tasks/postgresql_database_tasks.rb +14 -40
  162. data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -28
  163. data/lib/active_record/test_databases.rb +14 -4
  164. data/lib/active_record/test_fixtures.rb +39 -2
  165. data/lib/active_record/testing/query_assertions.rb +8 -2
  166. data/lib/active_record/timestamp.rb +4 -2
  167. data/lib/active_record/token_for.rb +1 -1
  168. data/lib/active_record/transaction.rb +2 -5
  169. data/lib/active_record/transactions.rb +39 -16
  170. data/lib/active_record/type/hash_lookup_type_map.rb +2 -1
  171. data/lib/active_record/type/internal/timezone.rb +7 -0
  172. data/lib/active_record/type/json.rb +15 -2
  173. data/lib/active_record/type/serialized.rb +11 -4
  174. data/lib/active_record/type/type_map.rb +1 -1
  175. data/lib/active_record/type_caster/connection.rb +2 -1
  176. data/lib/active_record/validations/associated.rb +1 -1
  177. data/lib/active_record/validations/uniqueness.rb +8 -8
  178. data/lib/active_record.rb +85 -50
  179. data/lib/arel/alias_predication.rb +2 -0
  180. data/lib/arel/collectors/bind.rb +2 -2
  181. data/lib/arel/collectors/sql_string.rb +1 -1
  182. data/lib/arel/collectors/substitute_binds.rb +2 -2
  183. data/lib/arel/crud.rb +8 -11
  184. data/lib/arel/delete_manager.rb +5 -0
  185. data/lib/arel/nodes/binary.rb +1 -1
  186. data/lib/arel/nodes/count.rb +2 -2
  187. data/lib/arel/nodes/delete_statement.rb +4 -2
  188. data/lib/arel/nodes/function.rb +4 -10
  189. data/lib/arel/nodes/named_function.rb +2 -2
  190. data/lib/arel/nodes/node.rb +2 -2
  191. data/lib/arel/nodes/sql_literal.rb +1 -1
  192. data/lib/arel/nodes/update_statement.rb +4 -2
  193. data/lib/arel/nodes.rb +0 -2
  194. data/lib/arel/select_manager.rb +13 -4
  195. data/lib/arel/table.rb +3 -7
  196. data/lib/arel/update_manager.rb +5 -0
  197. data/lib/arel/visitors/dot.rb +2 -3
  198. data/lib/arel/visitors/postgresql.rb +55 -0
  199. data/lib/arel/visitors/sqlite.rb +55 -8
  200. data/lib/arel/visitors/to_sql.rb +6 -22
  201. data/lib/arel.rb +3 -1
  202. data/lib/rails/generators/active_record/application_record/USAGE +1 -1
  203. metadata +17 -17
  204. data/lib/active_record/explain_subscriber.rb +0 -34
  205. data/lib/active_record/normalization.rb +0 -163
  206. data/lib/active_record/relation/record_fetch_warning.rb +0 -52
@@ -9,25 +9,40 @@ module ActiveRecord
9
9
  # shard to switch to and allows for applications to write custom strategies
10
10
  # for swapping if needed.
11
11
  #
12
- # The ShardSelector takes a set of options (currently only +lock+ is supported)
13
- # that can be used by the middleware to alter behavior. +lock+ is
14
- # true by default and will prohibit the request from switching shards once
15
- # inside the block. If +lock+ is false, then shard swapping will be allowed.
16
- # For tenant based sharding, +lock+ should always be true to prevent application
17
- # code from mistakenly switching between tenants.
12
+ # == Setup
18
13
  #
19
- # Options can be set in the config:
14
+ # Applications must provide a resolver that will provide application-specific logic for
15
+ # selecting the appropriate shard. Setting +config.active_record.shard_resolver+ will cause
16
+ # Rails to add ShardSelector to the default middleware stack.
20
17
  #
21
- # config.active_record.shard_selector = { lock: true }
18
+ # The resolver, along with any configuration options, can be set in the application
19
+ # configuration using an initializer like so:
22
20
  #
23
- # Applications must also provide the code for the resolver as it depends on application
24
- # specific models. An example resolver would look like this:
21
+ # Rails.application.configure do
22
+ # config.active_record.shard_selector = { lock: false, class_name: "AnimalsRecord" }
23
+ # config.active_record.shard_resolver = ->(request) {
24
+ # subdomain = request.subdomain
25
+ # tenant = Tenant.find_by_subdomain!(subdomain)
26
+ # tenant.shard
27
+ # }
28
+ # end
29
+ #
30
+ # == Configuration
31
+ #
32
+ # The behavior of ShardSelector can be altered through some configuration options.
33
+ #
34
+ # [+lock:+]
35
+ # +lock+ is true by default and will prohibit the request from switching shards once inside
36
+ # the block. If +lock+ is false, then shard switching will be allowed. For tenant based
37
+ # sharding, +lock+ should always be true to prevent application code from mistakenly switching
38
+ # between tenants.
39
+ #
40
+ # [+class_name:+]
41
+ # +class_name+ is the name of the abstract connection class to switch. By
42
+ # default, the ShardSelector will use ActiveRecord::Base, but if the
43
+ # application has multiple databases, then this option should be set to
44
+ # the name of the sharded database's abstract connection class.
25
45
  #
26
- # config.active_record.shard_resolver = ->(request) {
27
- # subdomain = request.subdomain
28
- # tenant = Tenant.find_by_subdomain!(subdomain)
29
- # tenant.shard
30
- # }
31
46
  class ShardSelector
32
47
  def initialize(app, resolver, options = {})
33
48
  @app = app
@@ -53,8 +68,10 @@ module ActiveRecord
53
68
  end
54
69
 
55
70
  def set_shard(shard, &block)
56
- ActiveRecord::Base.connected_to(shard: shard.to_sym) do
57
- ActiveRecord::Base.prohibit_shard_swapping(options.fetch(:lock, true), &block)
71
+ klass = options[:class_name]&.constantize || ActiveRecord::Base
72
+
73
+ klass.connected_to(shard: shard.to_sym) do
74
+ klass.prohibit_shard_swapping(options.fetch(:lock, true), &block)
58
75
  end
59
76
  end
60
77
  end
@@ -22,10 +22,12 @@ module ActiveRecord
22
22
  # * change_table_comment (must supply a +:from+ and +:to+ option)
23
23
  # * create_enum
24
24
  # * create_join_table
25
+ # * create_virtual_table
25
26
  # * create_table
26
27
  # * disable_extension
27
28
  # * drop_enum (must supply a list of values)
28
29
  # * drop_join_table
30
+ # * drop_virtual_table (must supply options)
29
31
  # * drop_table (must supply a block)
30
32
  # * enable_extension
31
33
  # * remove_column (must supply a type)
@@ -38,10 +40,12 @@ module ActiveRecord
38
40
  # * remove_reference
39
41
  # * remove_timestamps
40
42
  # * rename_column
41
- # * rename_enum (must supply a +:to+ option)
43
+ # * rename_enum
42
44
  # * rename_enum_value (must supply a +:from+ and +:to+ option)
43
45
  # * rename_index
44
46
  # * rename_table
47
+ # * enable_index
48
+ # * disable_index
45
49
  class CommandRecorder
46
50
  ReversibleAndIrreversibleMethods = [
47
51
  :create_table, :create_join_table, :rename_table, :add_column, :remove_column,
@@ -55,6 +59,9 @@ module ActiveRecord
55
59
  :add_exclusion_constraint, :remove_exclusion_constraint,
56
60
  :add_unique_constraint, :remove_unique_constraint,
57
61
  :create_enum, :drop_enum, :rename_enum, :add_enum_value, :rename_enum_value,
62
+ :create_schema, :drop_schema,
63
+ :create_virtual_table, :drop_virtual_table,
64
+ :enable_index, :disable_index
58
65
  ]
59
66
  include JoinTable
60
67
 
@@ -163,7 +170,9 @@ module ActiveRecord
163
170
  add_exclusion_constraint: :remove_exclusion_constraint,
164
171
  add_unique_constraint: :remove_unique_constraint,
165
172
  enable_extension: :disable_extension,
166
- create_enum: :drop_enum
173
+ create_enum: :drop_enum,
174
+ create_schema: :drop_schema,
175
+ create_virtual_table: :drop_virtual_table
167
176
  }.each do |cmd, inv|
168
177
  [[inv, cmd], [cmd, inv]].uniq.each do |method, inverse|
169
178
  class_eval <<-EOV, __FILE__, __LINE__ + 1
@@ -177,6 +186,16 @@ module ActiveRecord
177
186
 
178
187
  include StraightReversions
179
188
 
189
+ def invert_enable_index(args)
190
+ table_name, index_name = args
191
+ [:disable_index, [table_name, index_name]]
192
+ end
193
+
194
+ def invert_disable_index(args)
195
+ table_name, index_name = args
196
+ [:enable_index, [table_name, index_name]]
197
+ end
198
+
180
199
  def invert_transaction(args, &block)
181
200
  sub_recorder = CommandRecorder.new(delegate)
182
201
  sub_recorder.revert(&block)
@@ -196,13 +215,20 @@ module ActiveRecord
196
215
  end
197
216
 
198
217
  def invert_drop_table(args, &block)
199
- if args.last.is_a?(Hash)
200
- args.last.delete(:if_exists)
218
+ options = args.extract_options!
219
+ options.delete(:if_exists)
220
+
221
+ if args.size > 1
222
+ raise ActiveRecord::IrreversibleMigration, "To avoid mistakes, drop_table is only reversible if given a single table name."
201
223
  end
202
- if args.size == 1 && block == nil
224
+
225
+ if args.size == 1 && options == {} && block == nil
203
226
  raise ActiveRecord::IrreversibleMigration, "To avoid mistakes, drop_table is only reversible if given options or a block (can be empty)."
204
227
  end
205
- super
228
+
229
+ args << options unless options.empty?
230
+
231
+ super(args, &block)
206
232
  end
207
233
 
208
234
  def invert_rename_table(args)
@@ -353,13 +379,13 @@ module ActiveRecord
353
379
  end
354
380
 
355
381
  def invert_rename_enum(args)
356
- name, options = args
382
+ name, new_name, = args
357
383
 
358
- unless options.is_a?(Hash) && options.has_key?(:to)
359
- raise ActiveRecord::IrreversibleMigration, "rename_enum is only reversible if given a :to option."
384
+ if new_name.is_a?(Hash) && new_name.key?(:to)
385
+ new_name = new_name[:to]
360
386
  end
361
387
 
362
- [:rename_enum, [options[:to], to: name]]
388
+ [:rename_enum, [new_name, name]]
363
389
  end
364
390
 
365
391
  def invert_rename_enum_value(args)
@@ -369,7 +395,14 @@ module ActiveRecord
369
395
  raise ActiveRecord::IrreversibleMigration, "rename_enum_value is only reversible if given a :from and :to option."
370
396
  end
371
397
 
372
- [:rename_enum_value, [type_name, from: options[:to], to: options[:from]]]
398
+ options[:to], options[:from] = options[:from], options[:to]
399
+ [:rename_enum_value, [type_name, options]]
400
+ end
401
+
402
+ def invert_drop_virtual_table(args)
403
+ _enum, values = args.dup.tap(&:extract_options!)
404
+ raise ActiveRecord::IrreversibleMigration, "drop_virtual_table is only reversible if given options." unless values
405
+ super
373
406
  end
374
407
 
375
408
  def respond_to_missing?(method, _)
@@ -21,7 +21,7 @@ module ActiveRecord
21
21
  # New migration functionality that will never be backward compatible should be added directly to `ActiveRecord::Migration`.
22
22
  #
23
23
  # There are classes for each prior Rails version. Each class descends from the *next* Rails version, so:
24
- # 5.2 < 6.0 < 6.1 < 7.0 < 7.1 < 7.2
24
+ # 5.2 < 6.0 < 6.1 < 7.0 < 7.1 < 7.2 < 8.0 < 8.1
25
25
  #
26
26
  # If you are introducing new migration functionality that should only apply from Rails 7 onward, then you should
27
27
  # find the class that immediately precedes it (6.1), and override the relevant migration methods to undo your changes.
@@ -29,7 +29,34 @@ module ActiveRecord
29
29
  # For example, Rails 6 added a default value for the `precision` option on datetime columns. So in this file, the `V5_2`
30
30
  # class sets the value of `precision` to `nil` if it's not explicitly provided. This way, the default value will not apply
31
31
  # for migrations written for 5.2, but will for migrations written for 6.0.
32
- V7_2 = Current
32
+ V8_1 = Current
33
+
34
+ class V8_0 < V8_1
35
+ module RemoveForeignKeyColumnMatch
36
+ def remove_foreign_key(*args, **options)
37
+ options[:_skip_column_match] = true
38
+ super
39
+ end
40
+ end
41
+
42
+ module TableDefinition
43
+ def remove_foreign_key(to_table = nil, **options)
44
+ options[:_skip_column_match] = true
45
+ super
46
+ end
47
+ end
48
+
49
+ include RemoveForeignKeyColumnMatch
50
+
51
+ private
52
+ def compatible_table_definition(t)
53
+ t.singleton_class.prepend(TableDefinition)
54
+ super
55
+ end
56
+ end
57
+
58
+ class V7_2 < V8_0
59
+ end
33
60
 
34
61
  class V7_1 < V7_2
35
62
  end
@@ -151,9 +178,7 @@ module ActiveRecord
151
178
 
152
179
  private
153
180
  def compatible_table_definition(t)
154
- class << t
155
- prepend TableDefinition
156
- end
181
+ t.singleton_class.prepend(TableDefinition)
157
182
  super
158
183
  end
159
184
  end
@@ -214,9 +239,7 @@ module ActiveRecord
214
239
 
215
240
  private
216
241
  def compatible_table_definition(t)
217
- class << t
218
- prepend TableDefinition
219
- end
242
+ t.singleton_class.prepend(TableDefinition)
220
243
  super
221
244
  end
222
245
  end
@@ -257,9 +280,7 @@ module ActiveRecord
257
280
 
258
281
  private
259
282
  def compatible_table_definition(t)
260
- class << t
261
- prepend TableDefinition
262
- end
283
+ t.singleton_class.prepend(TableDefinition)
263
284
  super
264
285
  end
265
286
  end
@@ -305,17 +326,13 @@ module ActiveRecord
305
326
 
306
327
  private
307
328
  def compatible_table_definition(t)
308
- class << t
309
- prepend TableDefinition
310
- end
329
+ t.singleton_class.prepend(TableDefinition)
311
330
  super
312
331
  end
313
332
 
314
333
  def command_recorder
315
334
  recorder = super
316
- class << recorder
317
- prepend CommandRecorder
318
- end
335
+ recorder.singleton_class.prepend(CommandRecorder)
319
336
  recorder
320
337
  end
321
338
  end
@@ -403,9 +420,7 @@ module ActiveRecord
403
420
 
404
421
  private
405
422
  def compatible_table_definition(t)
406
- class << t
407
- prepend TableDefinition
408
- end
423
+ t.singleton_class.prepend(TableDefinition)
409
424
  super
410
425
  end
411
426
  end
@@ -439,7 +454,7 @@ module ActiveRecord
439
454
  super
440
455
  end
441
456
 
442
- def index_exists?(table_name, column_name, **options)
457
+ def index_exists?(table_name, column_name = nil, **options)
443
458
  column_names = Array(column_name).map(&:to_s)
444
459
  options[:name] =
445
460
  if options[:name].present?
@@ -457,9 +472,7 @@ module ActiveRecord
457
472
 
458
473
  private
459
474
  def compatible_table_definition(t)
460
- class << t
461
- prepend TableDefinition
462
- end
475
+ t.singleton_class.prepend(TableDefinition)
463
476
  super
464
477
  end
465
478
 
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ class Migration
5
+ # This class is used by the schema dumper to format versions information.
6
+ #
7
+ # The class receives the current +connection+ when initialized.
8
+ class DefaultSchemaVersionsFormatter # :nodoc:
9
+ def initialize(connection)
10
+ @connection = connection
11
+ end
12
+
13
+ def format(versions)
14
+ sm_table = connection.quote_table_name(connection.pool.schema_migration.table_name)
15
+
16
+ if versions.is_a?(Array)
17
+ sql = +"INSERT INTO #{sm_table} (version) VALUES\n"
18
+ sql << versions.reverse.map { |v| "(#{connection.quote(v)})" }.join(",\n")
19
+ sql << ";"
20
+ sql
21
+ else
22
+ "INSERT INTO #{sm_table} (version) VALUES (#{connection.quote(versions)});"
23
+ end
24
+ end
25
+
26
+ private
27
+ attr_reader :connection
28
+ end
29
+ end
30
+ end
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "benchmark"
4
- require "set"
5
- require "zlib"
6
3
  require "active_support/core_ext/array/access"
7
4
  require "active_support/core_ext/enumerable"
8
5
  require "active_support/core_ext/module/attribute_accessors"
@@ -21,7 +18,7 @@ module ActiveRecord
21
18
  # For example the following migration is not reversible.
22
19
  # Rolling back this migration will raise an ActiveRecord::IrreversibleMigration error.
23
20
  #
24
- # class IrreversibleMigrationExample < ActiveRecord::Migration[7.2]
21
+ # class IrreversibleMigrationExample < ActiveRecord::Migration[8.1]
25
22
  # def change
26
23
  # create_table :distributors do |t|
27
24
  # t.string :zipcode
@@ -39,7 +36,7 @@ module ActiveRecord
39
36
  #
40
37
  # 1. Define <tt>#up</tt> and <tt>#down</tt> methods instead of <tt>#change</tt>:
41
38
  #
42
- # class ReversibleMigrationExample < ActiveRecord::Migration[7.2]
39
+ # class ReversibleMigrationExample < ActiveRecord::Migration[8.1]
43
40
  # def up
44
41
  # create_table :distributors do |t|
45
42
  # t.string :zipcode
@@ -64,7 +61,7 @@ module ActiveRecord
64
61
  #
65
62
  # 2. Use the #reversible method in <tt>#change</tt> method:
66
63
  #
67
- # class ReversibleMigrationExample < ActiveRecord::Migration[7.2]
64
+ # class ReversibleMigrationExample < ActiveRecord::Migration[8.1]
68
65
  # def change
69
66
  # create_table :distributors do |t|
70
67
  # t.string :zipcode
@@ -151,11 +148,10 @@ module ActiveRecord
151
148
  include ActiveSupport::ActionableError
152
149
 
153
150
  action "Run pending migrations" do
154
- ActiveRecord::Tasks::DatabaseTasks.migrate
151
+ ActiveRecord::Tasks::DatabaseTasks.migrate_all
155
152
 
156
153
  if ActiveRecord.dump_schema_after_migration
157
- connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection
158
- ActiveRecord::Tasks::DatabaseTasks.dump_schema(connection.pool.db_config)
154
+ ActiveRecord::Tasks::DatabaseTasks.dump_all
159
155
  end
160
156
  end
161
157
 
@@ -250,7 +246,7 @@ module ActiveRecord
250
246
  #
251
247
  # Example of a simple migration:
252
248
  #
253
- # class AddSsl < ActiveRecord::Migration[7.2]
249
+ # class AddSsl < ActiveRecord::Migration[8.1]
254
250
  # def up
255
251
  # add_column :accounts, :ssl_enabled, :boolean, default: true
256
252
  # end
@@ -270,7 +266,7 @@ module ActiveRecord
270
266
  #
271
267
  # Example of a more complex migration that also needs to initialize data:
272
268
  #
273
- # class AddSystemSettings < ActiveRecord::Migration[7.2]
269
+ # class AddSystemSettings < ActiveRecord::Migration[8.1]
274
270
  # def up
275
271
  # create_table :system_settings do |t|
276
272
  # t.string :name
@@ -357,7 +353,7 @@ module ActiveRecord
357
353
  #
358
354
  # === Deletion
359
355
  #
360
- # * <tt>drop_table(name)</tt>: Drops the table called +name+.
356
+ # * <tt>drop_table(*names)</tt>: Drops the given tables.
361
357
  # * <tt>drop_join_table(table_1, table_2, options)</tt>: Drops the join table
362
358
  # specified by the given arguments.
363
359
  # * <tt>remove_column(table_name, column_name, type, options)</tt>: Removes the column
@@ -399,7 +395,7 @@ module ActiveRecord
399
395
  # $ bin/rails generate migration add_fieldname_to_tablename fieldname:string
400
396
  #
401
397
  # This will generate the file <tt>timestamp_add_fieldname_to_tablename.rb</tt>, which will look like this:
402
- # class AddFieldnameToTablename < ActiveRecord::Migration[7.2]
398
+ # class AddFieldnameToTablename < ActiveRecord::Migration[8.1]
403
399
  # def change
404
400
  # add_column :tablenames, :fieldname, :string
405
401
  # end
@@ -425,7 +421,7 @@ module ActiveRecord
425
421
  #
426
422
  # Not all migrations change the schema. Some just fix the data:
427
423
  #
428
- # class RemoveEmptyTags < ActiveRecord::Migration[7.2]
424
+ # class RemoveEmptyTags < ActiveRecord::Migration[8.1]
429
425
  # def up
430
426
  # Tag.all.each { |tag| tag.destroy if tag.pages.empty? }
431
427
  # end
@@ -438,7 +434,7 @@ module ActiveRecord
438
434
  #
439
435
  # Others remove columns when they migrate up instead of down:
440
436
  #
441
- # class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[7.2]
437
+ # class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[8.1]
442
438
  # def up
443
439
  # remove_column :items, :incomplete_items_count
444
440
  # remove_column :items, :completed_items_count
@@ -452,7 +448,7 @@ module ActiveRecord
452
448
  #
453
449
  # And sometimes you need to do something in SQL not abstracted directly by migrations:
454
450
  #
455
- # class MakeJoinUnique < ActiveRecord::Migration[7.2]
451
+ # class MakeJoinUnique < ActiveRecord::Migration[8.1]
456
452
  # def up
457
453
  # execute "ALTER TABLE `pages_linked_pages` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`)"
458
454
  # end
@@ -469,7 +465,7 @@ module ActiveRecord
469
465
  # <tt>Base#reset_column_information</tt> in order to ensure that the model has the
470
466
  # latest column data from after the new column was added. Example:
471
467
  #
472
- # class AddPeopleSalary < ActiveRecord::Migration[7.2]
468
+ # class AddPeopleSalary < ActiveRecord::Migration[8.1]
473
469
  # def up
474
470
  # add_column :people, :salary, :integer
475
471
  # Person.reset_column_information
@@ -531,7 +527,7 @@ module ActiveRecord
531
527
  # To define a reversible migration, define the +change+ method in your
532
528
  # migration like this:
533
529
  #
534
- # class TenderloveMigration < ActiveRecord::Migration[7.2]
530
+ # class TenderloveMigration < ActiveRecord::Migration[8.1]
535
531
  # def change
536
532
  # create_table(:horses) do |t|
537
533
  # t.column :content, :text
@@ -561,7 +557,7 @@ module ActiveRecord
561
557
  # can't execute inside a transaction though, and for these situations
562
558
  # you can turn the automatic transactions off.
563
559
  #
564
- # class ChangeEnum < ActiveRecord::Migration[7.2]
560
+ # class ChangeEnum < ActiveRecord::Migration[8.1]
565
561
  # disable_ddl_transaction!
566
562
  #
567
563
  # def up
@@ -574,6 +570,7 @@ module ActiveRecord
574
570
  class Migration
575
571
  autoload :CommandRecorder, "active_record/migration/command_recorder"
576
572
  autoload :Compatibility, "active_record/migration/compatibility"
573
+ autoload :DefaultSchemaVersionsFormatter, "active_record/migration/default_schema_versions_formatter"
577
574
  autoload :JoinTable, "active_record/migration/join_table"
578
575
  autoload :ExecutionStrategy, "active_record/migration/execution_strategy"
579
576
  autoload :DefaultStrategy, "active_record/migration/default_strategy"
@@ -604,7 +601,7 @@ module ActiveRecord
604
601
  end
605
602
  end
606
603
 
607
- def drop_table(table_name, **options)
604
+ def drop_table(*table_names, **options)
608
605
  if block_given?
609
606
  super { |t| yield compatible_table_definition(t) }
610
607
  else
@@ -681,10 +678,6 @@ module ActiveRecord
681
678
  paths = all_configs.flat_map { |config| config.migrations_paths || Migrator.migrations_paths }.uniq
682
679
  @file_watcher.new([], paths.index_with(["rb"]), &block)
683
680
  end
684
-
685
- def connection
686
- ActiveRecord::Tasks::DatabaseTasks.migration_connection
687
- end
688
681
  end
689
682
 
690
683
  class << self
@@ -715,13 +708,7 @@ module ActiveRecord
715
708
 
716
709
  def load_schema_if_pending!
717
710
  if any_schema_needs_update?
718
- # Roundtrip to Rake to allow plugins to hook into database initialization.
719
- root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
720
-
721
- FileUtils.cd(root) do
722
- Base.connection_handler.clear_all_connections!(:all)
723
- system("bin/rails db:test:prepare")
724
- end
711
+ load_schema!
725
712
  end
726
713
 
727
714
  check_pending_migrations
@@ -760,7 +747,7 @@ module ActiveRecord
760
747
  private
761
748
  def any_schema_needs_update?
762
749
  !db_configs_in_current_env.all? do |db_config|
763
- Tasks::DatabaseTasks.schema_up_to_date?(db_config, ActiveRecord.schema_format)
750
+ Tasks::DatabaseTasks.schema_up_to_date?(db_config)
764
751
  end
765
752
  end
766
753
 
@@ -785,6 +772,21 @@ module ActiveRecord
785
772
  def env
786
773
  ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
787
774
  end
775
+
776
+ def load_schema!
777
+ # Roundtrip to Rake to allow plugins to hook into database initialization.
778
+ root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
779
+
780
+ FileUtils.cd(root) do
781
+ Base.connection_handler.clear_all_connections!(:all)
782
+ system("bin/rails db:test:prepare")
783
+ end
784
+ end
785
+
786
+ def respond_to_missing?(method, include_private = false)
787
+ return false if nearest_delegate == delegate
788
+ nearest_delegate.respond_to?(method, include_private)
789
+ end
788
790
  end
789
791
 
790
792
  def disable_ddl_transaction # :nodoc:
@@ -822,7 +824,7 @@ module ActiveRecord
822
824
  # and create the table 'apples' on the way up, and the reverse
823
825
  # on the way down.
824
826
  #
825
- # class FixTLMigration < ActiveRecord::Migration[7.2]
827
+ # class FixTLMigration < ActiveRecord::Migration[8.1]
826
828
  # def change
827
829
  # revert do
828
830
  # create_table(:horses) do |t|
@@ -841,7 +843,7 @@ module ActiveRecord
841
843
  #
842
844
  # require_relative "20121212123456_tenderlove_migration"
843
845
  #
844
- # class FixupTLMigration < ActiveRecord::Migration[7.2]
846
+ # class FixupTLMigration < ActiveRecord::Migration[8.1]
845
847
  # def change
846
848
  # revert TenderloveMigration
847
849
  #
@@ -892,7 +894,7 @@ module ActiveRecord
892
894
  # when the three columns 'first_name', 'last_name' and 'full_name' exist,
893
895
  # even when migrating down:
894
896
  #
895
- # class SplitNameMigration < ActiveRecord::Migration[7.2]
897
+ # class SplitNameMigration < ActiveRecord::Migration[8.1]
896
898
  # def change
897
899
  # add_column :users, :first_name, :string
898
900
  # add_column :users, :last_name, :string
@@ -920,7 +922,7 @@ module ActiveRecord
920
922
  # In the following example, the new column +published+ will be given
921
923
  # the value +true+ for all existing records.
922
924
  #
923
- # class AddPublishedToPosts < ActiveRecord::Migration[7.2]
925
+ # class AddPublishedToPosts < ActiveRecord::Migration[8.1]
924
926
  # def change
925
927
  # add_column :posts, :published, :boolean, default: false
926
928
  # up_only do
@@ -972,16 +974,16 @@ module ActiveRecord
972
974
  when :down then announce "reverting"
973
975
  end
974
976
 
975
- time = nil
977
+ time_elapsed = nil
976
978
  ActiveRecord::Tasks::DatabaseTasks.migration_connection.pool.with_connection do |conn|
977
- time = Benchmark.measure do
979
+ time_elapsed = ActiveSupport::Benchmark.realtime do
978
980
  exec_migration(conn, direction)
979
981
  end
980
982
  end
981
983
 
982
984
  case direction
983
- when :up then announce "migrated (%.4fs)" % time.real; write
984
- when :down then announce "reverted (%.4fs)" % time.real; write
985
+ when :up then announce "migrated (%.4fs)" % time_elapsed; write
986
+ when :down then announce "reverted (%.4fs)" % time_elapsed; write
985
987
  end
986
988
  end
987
989
 
@@ -1022,8 +1024,8 @@ module ActiveRecord
1022
1024
  def say_with_time(message)
1023
1025
  say(message)
1024
1026
  result = nil
1025
- time = Benchmark.measure { result = yield }
1026
- say "%.4fs" % time.real, :subitem
1027
+ time_elapsed = ActiveSupport::Benchmark.realtime { result = yield }
1028
+ say "%.4fs" % time_elapsed, :subitem
1027
1029
  say("#{result} rows", :subitem) if result.is_a?(Integer)
1028
1030
  result
1029
1031
  end
@@ -1173,6 +1175,10 @@ module ActiveRecord
1173
1175
  def command_recorder
1174
1176
  CommandRecorder.new(connection)
1175
1177
  end
1178
+
1179
+ def respond_to_missing?(method, include_private = false)
1180
+ execution_strategy.respond_to?(method, include_private) || super
1181
+ end
1176
1182
  end
1177
1183
 
1178
1184
  # MigrationProxy is used to defer loading of the actual migration classes
@@ -1532,7 +1538,8 @@ module ActiveRecord
1532
1538
  return if down? && !migrated.include?(migration.version.to_i)
1533
1539
  return if up? && migrated.include?(migration.version.to_i)
1534
1540
 
1535
- Base.logger.info "Migrating to #{migration.name} (#{migration.version})" if Base.logger
1541
+ message = up? ? "Migrating to" : "Reverting"
1542
+ Base.logger.info "#{message} #{migration.name} (#{migration.version})" if Base.logger
1536
1543
 
1537
1544
  ddl_transaction(migration) do
1538
1545
  migration.migrate(@direction)