activerecord 7.1.4.1 → 7.2.2.1

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 (189) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +643 -2274
  3. data/README.rdoc +15 -15
  4. data/examples/performance.rb +2 -2
  5. data/lib/active_record/association_relation.rb +1 -1
  6. data/lib/active_record/associations/alias_tracker.rb +25 -19
  7. data/lib/active_record/associations/association.rb +15 -8
  8. data/lib/active_record/associations/belongs_to_association.rb +14 -7
  9. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
  10. data/lib/active_record/associations/builder/belongs_to.rb +1 -0
  11. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +2 -2
  12. data/lib/active_record/associations/builder/has_many.rb +3 -4
  13. data/lib/active_record/associations/builder/has_one.rb +3 -4
  14. data/lib/active_record/associations/collection_association.rb +7 -1
  15. data/lib/active_record/associations/collection_proxy.rb +14 -1
  16. data/lib/active_record/associations/errors.rb +265 -0
  17. data/lib/active_record/associations/has_many_association.rb +1 -1
  18. data/lib/active_record/associations/has_many_through_association.rb +7 -1
  19. data/lib/active_record/associations/join_dependency/join_association.rb +30 -27
  20. data/lib/active_record/associations/join_dependency.rb +4 -4
  21. data/lib/active_record/associations/nested_error.rb +47 -0
  22. data/lib/active_record/associations/preloader/association.rb +2 -1
  23. data/lib/active_record/associations/preloader/branch.rb +7 -1
  24. data/lib/active_record/associations/preloader/through_association.rb +1 -3
  25. data/lib/active_record/associations/singular_association.rb +6 -0
  26. data/lib/active_record/associations/through_association.rb +1 -1
  27. data/lib/active_record/associations.rb +59 -292
  28. data/lib/active_record/attribute_assignment.rb +0 -2
  29. data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
  30. data/lib/active_record/attribute_methods/primary_key.rb +23 -55
  31. data/lib/active_record/attribute_methods/read.rb +1 -13
  32. data/lib/active_record/attribute_methods/serialization.rb +4 -24
  33. data/lib/active_record/attribute_methods/time_zone_conversion.rb +11 -6
  34. data/lib/active_record/attribute_methods.rb +54 -63
  35. data/lib/active_record/attributes.rb +61 -47
  36. data/lib/active_record/autosave_association.rb +12 -29
  37. data/lib/active_record/base.rb +2 -3
  38. data/lib/active_record/callbacks.rb +1 -1
  39. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +24 -107
  40. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +1 -0
  41. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +270 -65
  42. data/lib/active_record/connection_adapters/abstract/database_statements.rb +34 -17
  43. data/lib/active_record/connection_adapters/abstract/query_cache.rb +189 -74
  44. data/lib/active_record/connection_adapters/abstract/quoting.rb +65 -91
  45. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +1 -1
  46. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +15 -6
  47. data/lib/active_record/connection_adapters/abstract/transaction.rb +125 -62
  48. data/lib/active_record/connection_adapters/abstract_adapter.rb +24 -44
  49. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +40 -10
  50. data/lib/active_record/connection_adapters/mysql/database_statements.rb +9 -1
  51. data/lib/active_record/connection_adapters/mysql/quoting.rb +43 -48
  52. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +6 -0
  53. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +16 -15
  54. data/lib/active_record/connection_adapters/mysql2_adapter.rb +5 -23
  55. data/lib/active_record/connection_adapters/pool_config.rb +7 -6
  56. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +27 -4
  57. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
  58. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
  59. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
  60. data/lib/active_record/connection_adapters/postgresql/quoting.rb +58 -58
  61. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +20 -0
  62. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +17 -11
  63. data/lib/active_record/connection_adapters/postgresql_adapter.rb +29 -24
  64. data/lib/active_record/connection_adapters/schema_cache.rb +123 -128
  65. data/lib/active_record/connection_adapters/sqlite3/column.rb +14 -1
  66. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +10 -6
  67. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +44 -46
  68. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  69. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +13 -0
  70. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
  71. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +25 -2
  72. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +125 -75
  73. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +15 -15
  74. data/lib/active_record/connection_adapters/trilogy_adapter.rb +19 -48
  75. data/lib/active_record/connection_adapters.rb +121 -0
  76. data/lib/active_record/connection_handling.rb +56 -41
  77. data/lib/active_record/core.rb +86 -38
  78. data/lib/active_record/counter_cache.rb +18 -9
  79. data/lib/active_record/database_configurations/connection_url_resolver.rb +8 -3
  80. data/lib/active_record/database_configurations/database_config.rb +19 -4
  81. data/lib/active_record/database_configurations/hash_config.rb +38 -34
  82. data/lib/active_record/database_configurations/url_config.rb +20 -1
  83. data/lib/active_record/database_configurations.rb +1 -1
  84. data/lib/active_record/delegated_type.rb +24 -0
  85. data/lib/active_record/dynamic_matchers.rb +2 -2
  86. data/lib/active_record/encryption/encryptable_record.rb +3 -3
  87. data/lib/active_record/encryption/encrypted_attribute_type.rb +24 -4
  88. data/lib/active_record/encryption/encryptor.rb +18 -3
  89. data/lib/active_record/encryption/key_provider.rb +1 -1
  90. data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
  91. data/lib/active_record/encryption/message_serializer.rb +4 -0
  92. data/lib/active_record/encryption/null_encryptor.rb +4 -0
  93. data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
  94. data/lib/active_record/encryption.rb +2 -0
  95. data/lib/active_record/enum.rb +19 -2
  96. data/lib/active_record/errors.rb +46 -20
  97. data/lib/active_record/explain.rb +13 -24
  98. data/lib/active_record/fixtures.rb +37 -31
  99. data/lib/active_record/future_result.rb +8 -4
  100. data/lib/active_record/gem_version.rb +2 -2
  101. data/lib/active_record/inheritance.rb +4 -2
  102. data/lib/active_record/insert_all.rb +18 -15
  103. data/lib/active_record/integration.rb +4 -1
  104. data/lib/active_record/internal_metadata.rb +48 -34
  105. data/lib/active_record/locking/optimistic.rb +7 -6
  106. data/lib/active_record/log_subscriber.rb +0 -21
  107. data/lib/active_record/marshalling.rb +4 -1
  108. data/lib/active_record/message_pack.rb +1 -1
  109. data/lib/active_record/migration/command_recorder.rb +2 -3
  110. data/lib/active_record/migration/compatibility.rb +5 -3
  111. data/lib/active_record/migration/default_strategy.rb +4 -5
  112. data/lib/active_record/migration/pending_migration_connection.rb +2 -2
  113. data/lib/active_record/migration.rb +85 -76
  114. data/lib/active_record/model_schema.rb +32 -68
  115. data/lib/active_record/nested_attributes.rb +24 -5
  116. data/lib/active_record/normalization.rb +3 -7
  117. data/lib/active_record/persistence.rb +30 -352
  118. data/lib/active_record/query_cache.rb +19 -8
  119. data/lib/active_record/query_logs.rb +15 -0
  120. data/lib/active_record/querying.rb +21 -9
  121. data/lib/active_record/railtie.rb +42 -57
  122. data/lib/active_record/railties/controller_runtime.rb +13 -4
  123. data/lib/active_record/railties/databases.rake +40 -43
  124. data/lib/active_record/reflection.rb +98 -36
  125. data/lib/active_record/relation/batches/batch_enumerator.rb +15 -2
  126. data/lib/active_record/relation/batches.rb +14 -8
  127. data/lib/active_record/relation/calculations.rb +96 -63
  128. data/lib/active_record/relation/delegation.rb +8 -11
  129. data/lib/active_record/relation/finder_methods.rb +16 -2
  130. data/lib/active_record/relation/merger.rb +4 -6
  131. data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
  132. data/lib/active_record/relation/predicate_builder/association_query_value.rb +9 -3
  133. data/lib/active_record/relation/predicate_builder.rb +3 -3
  134. data/lib/active_record/relation/query_methods.rb +224 -58
  135. data/lib/active_record/relation/record_fetch_warning.rb +3 -0
  136. data/lib/active_record/relation/spawn_methods.rb +2 -18
  137. data/lib/active_record/relation/where_clause.rb +7 -19
  138. data/lib/active_record/relation.rb +496 -72
  139. data/lib/active_record/result.rb +31 -44
  140. data/lib/active_record/runtime_registry.rb +39 -0
  141. data/lib/active_record/sanitization.rb +24 -19
  142. data/lib/active_record/schema.rb +8 -6
  143. data/lib/active_record/schema_dumper.rb +19 -9
  144. data/lib/active_record/schema_migration.rb +30 -14
  145. data/lib/active_record/scoping/named.rb +1 -0
  146. data/lib/active_record/signed_id.rb +20 -1
  147. data/lib/active_record/statement_cache.rb +7 -7
  148. data/lib/active_record/table_metadata.rb +1 -10
  149. data/lib/active_record/tasks/database_tasks.rb +81 -42
  150. data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
  151. data/lib/active_record/tasks/postgresql_database_tasks.rb +1 -1
  152. data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -1
  153. data/lib/active_record/test_fixtures.rb +86 -89
  154. data/lib/active_record/testing/query_assertions.rb +121 -0
  155. data/lib/active_record/timestamp.rb +2 -2
  156. data/lib/active_record/token_for.rb +22 -12
  157. data/lib/active_record/touch_later.rb +1 -1
  158. data/lib/active_record/transaction.rb +132 -0
  159. data/lib/active_record/transactions.rb +70 -14
  160. data/lib/active_record/translation.rb +0 -2
  161. data/lib/active_record/type/serialized.rb +1 -3
  162. data/lib/active_record/type_caster/connection.rb +4 -4
  163. data/lib/active_record/validations/associated.rb +9 -3
  164. data/lib/active_record/validations/uniqueness.rb +15 -10
  165. data/lib/active_record/validations.rb +4 -1
  166. data/lib/active_record.rb +148 -39
  167. data/lib/arel/alias_predication.rb +1 -1
  168. data/lib/arel/collectors/bind.rb +2 -0
  169. data/lib/arel/collectors/composite.rb +7 -0
  170. data/lib/arel/collectors/sql_string.rb +1 -1
  171. data/lib/arel/collectors/substitute_binds.rb +1 -1
  172. data/lib/arel/nodes/binary.rb +0 -6
  173. data/lib/arel/nodes/bound_sql_literal.rb +9 -5
  174. data/lib/arel/nodes/{and.rb → nary.rb} +5 -2
  175. data/lib/arel/nodes/node.rb +4 -3
  176. data/lib/arel/nodes/sql_literal.rb +7 -0
  177. data/lib/arel/nodes.rb +2 -2
  178. data/lib/arel/predications.rb +1 -1
  179. data/lib/arel/select_manager.rb +1 -1
  180. data/lib/arel/tree_manager.rb +3 -2
  181. data/lib/arel/update_manager.rb +2 -1
  182. data/lib/arel/visitors/dot.rb +1 -0
  183. data/lib/arel/visitors/mysql.rb +9 -4
  184. data/lib/arel/visitors/postgresql.rb +1 -12
  185. data/lib/arel/visitors/sqlite.rb +25 -0
  186. data/lib/arel/visitors/to_sql.rb +29 -16
  187. data/lib/arel.rb +7 -3
  188. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
  189. metadata +18 -12
@@ -21,7 +21,7 @@ module ActiveRecord
21
21
  # For example the following migration is not reversible.
22
22
  # Rolling back this migration will raise an ActiveRecord::IrreversibleMigration error.
23
23
  #
24
- # class IrreversibleMigrationExample < ActiveRecord::Migration[7.1]
24
+ # class IrreversibleMigrationExample < ActiveRecord::Migration[7.2]
25
25
  # def change
26
26
  # create_table :distributors do |t|
27
27
  # t.string :zipcode
@@ -39,7 +39,7 @@ module ActiveRecord
39
39
  #
40
40
  # 1. Define <tt>#up</tt> and <tt>#down</tt> methods instead of <tt>#change</tt>:
41
41
  #
42
- # class ReversibleMigrationExample < ActiveRecord::Migration[7.1]
42
+ # class ReversibleMigrationExample < ActiveRecord::Migration[7.2]
43
43
  # def up
44
44
  # create_table :distributors do |t|
45
45
  # t.string :zipcode
@@ -64,7 +64,7 @@ module ActiveRecord
64
64
  #
65
65
  # 2. Use the #reversible method in <tt>#change</tt> method:
66
66
  #
67
- # class ReversibleMigrationExample < ActiveRecord::Migration[7.1]
67
+ # class ReversibleMigrationExample < ActiveRecord::Migration[7.2]
68
68
  # def change
69
69
  # create_table :distributors do |t|
70
70
  # t.string :zipcode
@@ -131,6 +131,22 @@ module ActiveRecord
131
131
  end
132
132
  end
133
133
 
134
+ class InvalidMigrationTimestampError < MigrationError # :nodoc:
135
+ def initialize(version = nil, name = nil)
136
+ if version && name
137
+ super(<<~MSG)
138
+ Invalid timestamp #{version} for migration file: #{name}.
139
+ Timestamp must be in form YYYYMMDDHHMMSS, and less than #{(Time.now.utc + 1.day).strftime("%Y%m%d%H%M%S")}.
140
+ MSG
141
+ else
142
+ super(<<~MSG)
143
+ Invalid timestamp for migration.
144
+ Timestamp must be in form YYYYMMDDHHMMSS, and less than #{(Time.now.utc + 1.day).strftime("%Y%m%d%H%M%S")}.
145
+ MSG
146
+ end
147
+ end
148
+ end
149
+
134
150
  class PendingMigrationError < MigrationError # :nodoc:
135
151
  include ActiveSupport::ActionableError
136
152
 
@@ -145,8 +161,7 @@ module ActiveRecord
145
161
 
146
162
  def initialize(message = nil, pending_migrations: nil)
147
163
  if pending_migrations.nil?
148
- connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection
149
- pending_migrations = connection.migration_context.open.pending_migrations
164
+ pending_migrations = connection_pool.migration_context.open.pending_migrations
150
165
  end
151
166
 
152
167
  super(message || detailed_migration_message(pending_migrations))
@@ -167,8 +182,8 @@ module ActiveRecord
167
182
  message
168
183
  end
169
184
 
170
- def connection
171
- ActiveRecord::Tasks::DatabaseTasks.migration_connection
185
+ def connection_pool
186
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool
172
187
  end
173
188
  end
174
189
 
@@ -235,7 +250,7 @@ module ActiveRecord
235
250
  #
236
251
  # Example of a simple migration:
237
252
  #
238
- # class AddSsl < ActiveRecord::Migration[7.1]
253
+ # class AddSsl < ActiveRecord::Migration[7.2]
239
254
  # def up
240
255
  # add_column :accounts, :ssl_enabled, :boolean, default: true
241
256
  # end
@@ -255,7 +270,7 @@ module ActiveRecord
255
270
  #
256
271
  # Example of a more complex migration that also needs to initialize data:
257
272
  #
258
- # class AddSystemSettings < ActiveRecord::Migration[7.1]
273
+ # class AddSystemSettings < ActiveRecord::Migration[7.2]
259
274
  # def up
260
275
  # create_table :system_settings do |t|
261
276
  # t.string :name
@@ -384,7 +399,7 @@ module ActiveRecord
384
399
  # $ bin/rails generate migration add_fieldname_to_tablename fieldname:string
385
400
  #
386
401
  # This will generate the file <tt>timestamp_add_fieldname_to_tablename.rb</tt>, which will look like this:
387
- # class AddFieldnameToTablename < ActiveRecord::Migration[7.1]
402
+ # class AddFieldnameToTablename < ActiveRecord::Migration[7.2]
388
403
  # def change
389
404
  # add_column :tablenames, :fieldname, :string
390
405
  # end
@@ -410,7 +425,7 @@ module ActiveRecord
410
425
  #
411
426
  # Not all migrations change the schema. Some just fix the data:
412
427
  #
413
- # class RemoveEmptyTags < ActiveRecord::Migration[7.1]
428
+ # class RemoveEmptyTags < ActiveRecord::Migration[7.2]
414
429
  # def up
415
430
  # Tag.all.each { |tag| tag.destroy if tag.pages.empty? }
416
431
  # end
@@ -423,7 +438,7 @@ module ActiveRecord
423
438
  #
424
439
  # Others remove columns when they migrate up instead of down:
425
440
  #
426
- # class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[7.1]
441
+ # class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[7.2]
427
442
  # def up
428
443
  # remove_column :items, :incomplete_items_count
429
444
  # remove_column :items, :completed_items_count
@@ -437,7 +452,7 @@ module ActiveRecord
437
452
  #
438
453
  # And sometimes you need to do something in SQL not abstracted directly by migrations:
439
454
  #
440
- # class MakeJoinUnique < ActiveRecord::Migration[7.1]
455
+ # class MakeJoinUnique < ActiveRecord::Migration[7.2]
441
456
  # def up
442
457
  # execute "ALTER TABLE `pages_linked_pages` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`)"
443
458
  # end
@@ -454,7 +469,7 @@ module ActiveRecord
454
469
  # <tt>Base#reset_column_information</tt> in order to ensure that the model has the
455
470
  # latest column data from after the new column was added. Example:
456
471
  #
457
- # class AddPeopleSalary < ActiveRecord::Migration[7.1]
472
+ # class AddPeopleSalary < ActiveRecord::Migration[7.2]
458
473
  # def up
459
474
  # add_column :people, :salary, :integer
460
475
  # Person.reset_column_information
@@ -470,7 +485,7 @@ module ActiveRecord
470
485
  # them to the console as they happen, along with benchmarks describing how
471
486
  # long each step took.
472
487
  #
473
- # You can quiet them down by setting ActiveRecord::Migration.verbose = false.
488
+ # You can quiet them down by setting <tt>ActiveRecord::Migration.verbose = false</tt>.
474
489
  #
475
490
  # You can also insert your own messages and benchmarks by using the +say_with_time+
476
491
  # method:
@@ -494,7 +509,11 @@ module ActiveRecord
494
509
  #
495
510
  # 20080717013526_your_migration_name.rb
496
511
  #
497
- # The prefix is a generation timestamp (in UTC).
512
+ # The prefix is a generation timestamp (in UTC). Timestamps should not be
513
+ # modified manually. To validate that migration timestamps adhere to the
514
+ # format Active Record expects, you can use the following configuration option:
515
+ #
516
+ # config.active_record.validate_migration_timestamps = true
498
517
  #
499
518
  # If you'd prefer to use numeric prefixes, you can turn timestamped migrations
500
519
  # off by setting:
@@ -512,7 +531,7 @@ module ActiveRecord
512
531
  # To define a reversible migration, define the +change+ method in your
513
532
  # migration like this:
514
533
  #
515
- # class TenderloveMigration < ActiveRecord::Migration[7.1]
534
+ # class TenderloveMigration < ActiveRecord::Migration[7.2]
516
535
  # def change
517
536
  # create_table(:horses) do |t|
518
537
  # t.column :content, :text
@@ -542,7 +561,7 @@ module ActiveRecord
542
561
  # can't execute inside a transaction though, and for these situations
543
562
  # you can turn the automatic transactions off.
544
563
  #
545
- # class ChangeEnum < ActiveRecord::Migration[7.1]
564
+ # class ChangeEnum < ActiveRecord::Migration[7.2]
546
565
  # disable_ddl_transaction!
547
566
  #
548
567
  # def up
@@ -676,30 +695,13 @@ module ActiveRecord
676
695
  delegate || superclass.nearest_delegate
677
696
  end
678
697
 
679
- # Raises ActiveRecord::PendingMigrationError error if any migrations are pending.
680
- #
681
- # This is deprecated in favor of +check_all_pending!+
682
- def check_pending!(connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection)
683
- ActiveRecord.deprecator.warn(<<-MSG.squish)
684
- The `check_pending!` method is deprecated in favor of `check_all_pending!`. The
685
- new implementation will loop through all available database configurations and find
686
- pending migrations. The prior implementation did not permit this.
687
- MSG
688
-
689
- pending_migrations = connection.migration_context.open.pending_migrations
690
-
691
- if pending_migrations.any?
692
- raise ActiveRecord::PendingMigrationError.new(pending_migrations: pending_migrations)
693
- end
694
- end
695
-
696
698
  # Raises ActiveRecord::PendingMigrationError error if any migrations are pending
697
699
  # for all database configurations in an environment.
698
700
  def check_all_pending!
699
701
  pending_migrations = []
700
702
 
701
- ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: env) do |connection|
702
- if pending = connection.migration_context.open.pending_migrations
703
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: env) do |pool|
704
+ if pending = pool.migration_context.open.pending_migrations
703
705
  pending_migrations << pending
704
706
  end
705
707
  end
@@ -731,10 +733,9 @@ module ActiveRecord
731
733
  end
732
734
  end
733
735
 
734
- def method_missing(name, *args, &block) # :nodoc:
735
- nearest_delegate.send(name, *args, &block)
736
+ def method_missing(name, ...) # :nodoc:
737
+ nearest_delegate.send(name, ...)
736
738
  end
737
- ruby2_keywords(:method_missing)
738
739
 
739
740
  def migrate(direction)
740
741
  new.migrate direction
@@ -771,8 +772,8 @@ module ActiveRecord
771
772
  pending_migrations = []
772
773
 
773
774
  ActiveRecord::Base.configurations.configs_for(env_name: env).each do |db_config|
774
- ActiveRecord::PendingMigrationConnection.establish_temporary_connection(db_config) do |conn|
775
- if pending = conn.migration_context.open.pending_migrations
775
+ ActiveRecord::PendingMigrationConnection.with_temporary_pool(db_config) do |pool|
776
+ if pending = pool.migration_context.open.pending_migrations
776
777
  pending_migrations << pending
777
778
  end
778
779
  end
@@ -790,6 +791,12 @@ module ActiveRecord
790
791
  self.class.disable_ddl_transaction
791
792
  end
792
793
 
794
+ ##
795
+ # :singleton-method: verbose
796
+ #
797
+ # Specifies if migrations will write the actions they are taking to the console as they
798
+ # happen, along with benchmarks describing how long each step took. Defaults to
799
+ # true.
793
800
  cattr_accessor :verbose
794
801
  attr_accessor :name, :version
795
802
 
@@ -797,6 +804,7 @@ module ActiveRecord
797
804
  @name = name
798
805
  @version = version
799
806
  @connection = nil
807
+ @pool = nil
800
808
  end
801
809
 
802
810
  def execution_strategy
@@ -814,7 +822,7 @@ module ActiveRecord
814
822
  # and create the table 'apples' on the way up, and the reverse
815
823
  # on the way down.
816
824
  #
817
- # class FixTLMigration < ActiveRecord::Migration[7.1]
825
+ # class FixTLMigration < ActiveRecord::Migration[7.2]
818
826
  # def change
819
827
  # revert do
820
828
  # create_table(:horses) do |t|
@@ -833,7 +841,7 @@ module ActiveRecord
833
841
  #
834
842
  # require_relative "20121212123456_tenderlove_migration"
835
843
  #
836
- # class FixupTLMigration < ActiveRecord::Migration[7.1]
844
+ # class FixupTLMigration < ActiveRecord::Migration[7.2]
837
845
  # def change
838
846
  # revert TenderloveMigration
839
847
  #
@@ -884,7 +892,7 @@ module ActiveRecord
884
892
  # when the three columns 'first_name', 'last_name' and 'full_name' exist,
885
893
  # even when migrating down:
886
894
  #
887
- # class SplitNameMigration < ActiveRecord::Migration[7.1]
895
+ # class SplitNameMigration < ActiveRecord::Migration[7.2]
888
896
  # def change
889
897
  # add_column :users, :first_name, :string
890
898
  # add_column :users, :last_name, :string
@@ -912,7 +920,7 @@ module ActiveRecord
912
920
  # In the following example, the new column +published+ will be given
913
921
  # the value +true+ for all existing records.
914
922
  #
915
- # class AddPublishedToPosts < ActiveRecord::Migration[7.1]
923
+ # class AddPublishedToPosts < ActiveRecord::Migration[7.2]
916
924
  # def change
917
925
  # add_column :posts, :published, :boolean, default: false
918
926
  # up_only do
@@ -1032,6 +1040,10 @@ module ActiveRecord
1032
1040
  @connection || ActiveRecord::Tasks::DatabaseTasks.migration_connection
1033
1041
  end
1034
1042
 
1043
+ def connection_pool
1044
+ @pool || ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool
1045
+ end
1046
+
1035
1047
  def method_missing(method, *arguments, &block)
1036
1048
  say_with_time "#{method}(#{format_arguments(arguments)})" do
1037
1049
  unless connection.respond_to? :revert
@@ -1203,31 +1215,9 @@ module ActiveRecord
1203
1215
  attr_reader :migrations_paths, :schema_migration, :internal_metadata
1204
1216
 
1205
1217
  def initialize(migrations_paths, schema_migration = nil, internal_metadata = nil)
1206
- if schema_migration == SchemaMigration
1207
- ActiveRecord.deprecator.warn(<<-MSG.squish)
1208
- SchemaMigration no longer inherits from ActiveRecord::Base. If you want
1209
- to use the default connection, remove this argument. If you want to use a
1210
- specific connection, instantiate MigrationContext with the connection's schema
1211
- migration, for example `MigrationContext.new(path, Dog.connection.schema_migration)`.
1212
- MSG
1213
-
1214
- schema_migration = nil
1215
- end
1216
-
1217
- if internal_metadata == InternalMetadata
1218
- ActiveRecord.deprecator.warn(<<-MSG.squish)
1219
- SchemaMigration no longer inherits from ActiveRecord::Base. If you want
1220
- to use the default connection, remove this argument. If you want to use a
1221
- specific connection, instantiate MigrationContext with the connection's internal
1222
- metadata, for example `MigrationContext.new(path, nil, Dog.connection.internal_metadata)`.
1223
- MSG
1224
-
1225
- internal_metadata = nil
1226
- end
1227
-
1228
1218
  @migrations_paths = migrations_paths
1229
- @schema_migration = schema_migration || SchemaMigration.new(connection)
1230
- @internal_metadata = internal_metadata || InternalMetadata.new(connection)
1219
+ @schema_migration = schema_migration || SchemaMigration.new(connection_pool)
1220
+ @internal_metadata = internal_metadata || InternalMetadata.new(connection_pool)
1231
1221
  end
1232
1222
 
1233
1223
  # Runs the migrations in the +migrations_path+.
@@ -1317,6 +1307,9 @@ module ActiveRecord
1317
1307
  migrations = migration_files.map do |file|
1318
1308
  version, name, scope = parse_migration_filename(file)
1319
1309
  raise IllegalMigrationNameError.new(file) unless version
1310
+ if validate_timestamp? && !valid_migration_timestamp?(version)
1311
+ raise InvalidMigrationTimestampError.new(version, name)
1312
+ end
1320
1313
  version = version.to_i
1321
1314
  name = name.camelize
1322
1315
 
@@ -1332,6 +1325,9 @@ module ActiveRecord
1332
1325
  file_list = migration_files.filter_map do |file|
1333
1326
  version, name, scope = parse_migration_filename(file)
1334
1327
  raise IllegalMigrationNameError.new(file) unless version
1328
+ if validate_timestamp? && !valid_migration_timestamp?(version)
1329
+ raise InvalidMigrationTimestampError.new(version, name)
1330
+ end
1335
1331
  version = schema_migration.normalize_migration_number(version)
1336
1332
  status = db_list.delete(version) ? "up" : "down"
1337
1333
  [status, version, (name + scope).humanize]
@@ -1353,11 +1349,12 @@ module ActiveRecord
1353
1349
  end
1354
1350
 
1355
1351
  def last_stored_environment # :nodoc:
1356
- return nil unless connection.internal_metadata.enabled?
1352
+ internal_metadata = connection_pool.internal_metadata
1353
+ return nil unless internal_metadata.enabled?
1357
1354
  return nil if current_version == 0
1358
- raise NoEnvironmentInSchemaError unless connection.internal_metadata.table_exists?
1355
+ raise NoEnvironmentInSchemaError unless internal_metadata.table_exists?
1359
1356
 
1360
- environment = connection.internal_metadata[:environment]
1357
+ environment = internal_metadata[:environment]
1361
1358
  raise NoEnvironmentInSchemaError unless environment
1362
1359
  environment
1363
1360
  end
@@ -1367,6 +1364,10 @@ module ActiveRecord
1367
1364
  ActiveRecord::Tasks::DatabaseTasks.migration_connection
1368
1365
  end
1369
1366
 
1367
+ def connection_pool
1368
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool
1369
+ end
1370
+
1370
1371
  def migration_files
1371
1372
  paths = Array(migrations_paths)
1372
1373
  Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
@@ -1376,6 +1377,14 @@ module ActiveRecord
1376
1377
  File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
1377
1378
  end
1378
1379
 
1380
+ def validate_timestamp?
1381
+ ActiveRecord.timestamped_migrations && ActiveRecord.validate_migration_timestamps
1382
+ end
1383
+
1384
+ def valid_migration_timestamp?(version)
1385
+ version.to_i < (Time.now.utc + 1.day).strftime("%Y%m%d%H%M%S").to_i
1386
+ end
1387
+
1379
1388
  def move(direction, steps)
1380
1389
  migrator = Migrator.new(direction, migrations, schema_migration, internal_metadata)
1381
1390
 
@@ -1402,9 +1411,9 @@ module ActiveRecord
1402
1411
 
1403
1412
  # For cases where a table doesn't exist like loading from schema cache
1404
1413
  def current_version
1405
- connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection
1406
- schema_migration = SchemaMigration.new(connection)
1407
- internal_metadata = InternalMetadata.new(connection)
1414
+ connection_pool = ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool
1415
+ schema_migration = SchemaMigration.new(connection_pool)
1416
+ internal_metadata = InternalMetadata.new(connection_pool)
1408
1417
 
1409
1418
  MigrationContext.new(migrations_paths, schema_migration, internal_metadata).current_version
1410
1419
  end
@@ -146,6 +146,11 @@ module ActiveRecord
146
146
  # your own model for something else, you can set +inheritance_column+:
147
147
  #
148
148
  # self.inheritance_column = 'zoink'
149
+ #
150
+ # If you wish to disable single-table inheritance altogether you can set
151
+ # +inheritance_column+ to +nil+
152
+ #
153
+ # self.inheritance_column = nil
149
154
 
150
155
  ##
151
156
  # :singleton-method: inheritance_column=
@@ -273,13 +278,13 @@ module ActiveRecord
273
278
  @table_name = value
274
279
  @quoted_table_name = nil
275
280
  @arel_table = nil
276
- @sequence_name = nil unless defined?(@explicit_sequence_name) && @explicit_sequence_name
281
+ @sequence_name = nil unless @explicit_sequence_name
277
282
  @predicate_builder = nil
278
283
  end
279
284
 
280
285
  # Returns a quoted version of the table name, used to construct SQL statements.
281
286
  def quoted_table_name
282
- @quoted_table_name ||= connection.quote_table_name(table_name)
287
+ @quoted_table_name ||= adapter_class.quote_table_name(table_name)
283
288
  end
284
289
 
285
290
  # Computes the table name, (re)sets it internally, and returns it.
@@ -374,7 +379,7 @@ module ActiveRecord
374
379
 
375
380
  def reset_sequence_name # :nodoc:
376
381
  @explicit_sequence_name = false
377
- @sequence_name = connection.default_sequence_name(table_name, primary_key)
382
+ @sequence_name = with_connection { |c| c.default_sequence_name(table_name, primary_key) }
378
383
  end
379
384
 
380
385
  # Sets the name of the sequence to use when generating ids to the given
@@ -399,39 +404,37 @@ module ActiveRecord
399
404
  # Determines if the primary key values should be selected from their
400
405
  # corresponding sequence before the insert statement.
401
406
  def prefetch_primary_key?
402
- connection.prefetch_primary_key?(table_name)
407
+ with_connection { |c| c.prefetch_primary_key?(table_name) }
403
408
  end
404
409
 
405
410
  # Returns the next value that will be used as the primary key on
406
411
  # an insert statement.
407
412
  def next_sequence_value
408
- connection.next_sequence_value(sequence_name)
413
+ with_connection { |c| c.next_sequence_value(sequence_name) }
409
414
  end
410
415
 
411
416
  # Indicates whether the table associated with this class exists
412
417
  def table_exists?
413
- connection.schema_cache.data_source_exists?(table_name)
418
+ schema_cache.data_source_exists?(table_name)
414
419
  end
415
420
 
416
421
  def attributes_builder # :nodoc:
417
- unless defined?(@attributes_builder) && @attributes_builder
422
+ @attributes_builder ||= begin
418
423
  defaults = _default_attributes.except(*(column_names - [primary_key]))
419
- @attributes_builder = ActiveModel::AttributeSet::Builder.new(attribute_types, defaults)
424
+ ActiveModel::AttributeSet::Builder.new(attribute_types, defaults)
420
425
  end
421
- @attributes_builder
422
426
  end
423
427
 
424
428
  def columns_hash # :nodoc:
425
- load_schema
429
+ load_schema unless @columns_hash
426
430
  @columns_hash
427
431
  end
428
432
 
429
433
  def columns
430
- load_schema
431
434
  @columns ||= columns_hash.values.freeze
432
435
  end
433
436
 
434
- def _returning_columns_for_insert # :nodoc:
437
+ def _returning_columns_for_insert(connection) # :nodoc:
435
438
  @_returning_columns_for_insert ||= begin
436
439
  auto_populated_columns = columns.filter_map do |c|
437
440
  c.name if connection.return_value_after_insert?(c)
@@ -441,37 +444,10 @@ module ActiveRecord
441
444
  end
442
445
  end
443
446
 
444
- def attribute_types # :nodoc:
445
- load_schema
446
- @attribute_types ||= Hash.new(Type.default_value)
447
- end
448
-
449
447
  def yaml_encoder # :nodoc:
450
448
  @yaml_encoder ||= ActiveModel::AttributeSet::YAMLEncoder.new(attribute_types)
451
449
  end
452
450
 
453
- # Returns the type of the attribute with the given name, after applying
454
- # all modifiers. This method is the only valid source of information for
455
- # anything related to the types of a model's attributes. This method will
456
- # access the database and load the model's schema if it is required.
457
- #
458
- # The return value of this method will implement the interface described
459
- # by ActiveModel::Type::Value (though the object itself may not subclass
460
- # it).
461
- #
462
- # +attr_name+ The name of the attribute to retrieve the type for. Must be
463
- # a string or a symbol.
464
- def type_for_attribute(attr_name, &block)
465
- attr_name = attr_name.to_s
466
- attr_name = attribute_aliases[attr_name] || attr_name
467
-
468
- if block
469
- attribute_types.fetch(attr_name, &block)
470
- else
471
- attribute_types[attr_name]
472
- end
473
- end
474
-
475
451
  # Returns the column object for the named attribute.
476
452
  # Returns an ActiveRecord::ConnectionAdapters::NullColumn if the
477
453
  # named attribute does not exist.
@@ -499,11 +475,6 @@ module ActiveRecord
499
475
  @column_defaults ||= _default_attributes.deep_dup.to_hash.freeze
500
476
  end
501
477
 
502
- def _default_attributes # :nodoc:
503
- load_schema
504
- @default_attributes ||= ActiveModel::AttributeSet.new({})
505
- end
506
-
507
478
  # Returns an array of column names as strings.
508
479
  def column_names
509
480
  @column_names ||= columns.map(&:name).freeze
@@ -531,7 +502,7 @@ module ActiveRecord
531
502
  # when just after creating a table you want to populate it with some default
532
503
  # values, e.g.:
533
504
  #
534
- # class CreateJobLevels < ActiveRecord::Migration[7.1]
505
+ # class CreateJobLevels < ActiveRecord::Migration[7.2]
535
506
  # def up
536
507
  # create_table :job_levels do |t|
537
508
  # t.integer :id
@@ -551,18 +522,20 @@ module ActiveRecord
551
522
  # end
552
523
  # end
553
524
  def reset_column_information
554
- connection.clear_cache!
525
+ connection_pool.active_connection&.clear_cache!
555
526
  ([self] + descendants).each(&:undefine_attribute_methods)
556
- connection.schema_cache.clear_data_source_cache!(table_name)
527
+ schema_cache.clear_data_source_cache!(table_name)
557
528
 
558
529
  reload_schema_from_cache
559
530
  initialize_find_by_cache
560
531
  end
561
532
 
562
- def load_schema # :nodoc:
533
+ # Load the model's schema information either from the schema cache
534
+ # or directly from the database.
535
+ def load_schema
563
536
  return if schema_loaded?
564
537
  @load_schema_monitor.synchronize do
565
- return if @columns_hash
538
+ return if schema_loaded?
566
539
 
567
540
  load_schema!
568
541
 
@@ -583,9 +556,7 @@ module ActiveRecord
583
556
  @arel_table = nil
584
557
  @column_names = nil
585
558
  @symbol_column_to_string_name_hash = nil
586
- @attribute_types = nil
587
559
  @content_columns = nil
588
- @default_attributes = nil
589
560
  @column_defaults = nil
590
561
  @attributes_builder = nil
591
562
  @columns = nil
@@ -611,7 +582,7 @@ module ActiveRecord
611
582
  end
612
583
 
613
584
  def schema_loaded?
614
- defined?(@schema_loaded) && @schema_loaded
585
+ @schema_loaded
615
586
  end
616
587
 
617
588
  def load_schema!
@@ -619,20 +590,11 @@ module ActiveRecord
619
590
  raise ActiveRecord::TableNotSpecified, "#{self} has no table configured. Set one with #{self}.table_name="
620
591
  end
621
592
 
622
- columns_hash = connection.schema_cache.columns_hash(table_name)
593
+ columns_hash = schema_cache.columns_hash(table_name)
623
594
  columns_hash = columns_hash.except(*ignored_columns) unless ignored_columns.empty?
624
595
  @columns_hash = columns_hash.freeze
625
- @columns_hash.each do |name, column|
626
- type = connection.lookup_cast_type_from_column(column)
627
- type = _convert_type_from_options(type)
628
- define_attribute(
629
- name,
630
- type,
631
- default: column.default,
632
- user_provided_default: false
633
- )
634
- alias_attribute :id_value, :id if name == "id"
635
- end
596
+
597
+ _default_attributes # Precompute to cache DB-dependent attribute types
636
598
  end
637
599
 
638
600
  # Guesses the table name, but does not decorate it with prefix and suffix information.
@@ -658,12 +620,14 @@ module ActiveRecord
658
620
  end
659
621
  end
660
622
 
661
- def _convert_type_from_options(type)
623
+ def type_for_column(connection, column)
624
+ type = connection.lookup_cast_type_from_column(column)
625
+
662
626
  if immutable_strings_by_default && type.respond_to?(:to_immutable_string)
663
- type.to_immutable_string
664
- else
665
- type
627
+ type = type.to_immutable_string
666
628
  end
629
+
630
+ type
667
631
  end
668
632
  end
669
633
  end