activerecord 7.1.3.2 → 7.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (191) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +570 -2094
  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 +18 -11
  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 +11 -5
  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 +3 -3
  18. data/lib/active_record/associations/has_one_association.rb +2 -2
  19. data/lib/active_record/associations/join_dependency/join_association.rb +27 -25
  20. data/lib/active_record/associations/join_dependency.rb +6 -8
  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 +34 -273
  28. data/lib/active_record/attribute_assignment.rb +1 -11
  29. data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
  30. data/lib/active_record/attribute_methods/dirty.rb +2 -2
  31. data/lib/active_record/attribute_methods/primary_key.rb +23 -55
  32. data/lib/active_record/attribute_methods/read.rb +4 -16
  33. data/lib/active_record/attribute_methods/serialization.rb +4 -24
  34. data/lib/active_record/attribute_methods/time_zone_conversion.rb +7 -6
  35. data/lib/active_record/attribute_methods/write.rb +3 -3
  36. data/lib/active_record/attribute_methods.rb +89 -58
  37. data/lib/active_record/attributes.rb +60 -45
  38. data/lib/active_record/autosave_association.rb +17 -31
  39. data/lib/active_record/base.rb +2 -3
  40. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +24 -107
  41. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +1 -0
  42. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +244 -58
  43. data/lib/active_record/connection_adapters/abstract/database_statements.rb +35 -18
  44. data/lib/active_record/connection_adapters/abstract/query_cache.rb +188 -75
  45. data/lib/active_record/connection_adapters/abstract/quoting.rb +65 -91
  46. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +1 -1
  47. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +22 -9
  48. data/lib/active_record/connection_adapters/abstract/transaction.rb +125 -62
  49. data/lib/active_record/connection_adapters/abstract_adapter.rb +38 -59
  50. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +69 -19
  51. data/lib/active_record/connection_adapters/mysql/database_statements.rb +9 -1
  52. data/lib/active_record/connection_adapters/mysql/quoting.rb +43 -48
  53. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +8 -1
  54. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +16 -15
  55. data/lib/active_record/connection_adapters/mysql2_adapter.rb +20 -32
  56. data/lib/active_record/connection_adapters/pool_config.rb +7 -6
  57. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +27 -4
  58. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
  59. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
  60. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
  61. data/lib/active_record/connection_adapters/postgresql/quoting.rb +58 -58
  62. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +20 -0
  63. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +16 -12
  64. data/lib/active_record/connection_adapters/postgresql_adapter.rb +26 -21
  65. data/lib/active_record/connection_adapters/schema_cache.rb +123 -128
  66. data/lib/active_record/connection_adapters/sqlite3/column.rb +14 -1
  67. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +10 -6
  68. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +44 -46
  69. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  70. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +13 -0
  71. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
  72. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +25 -2
  73. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +127 -77
  74. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +15 -15
  75. data/lib/active_record/connection_adapters/trilogy_adapter.rb +32 -65
  76. data/lib/active_record/connection_adapters.rb +121 -0
  77. data/lib/active_record/connection_handling.rb +56 -41
  78. data/lib/active_record/core.rb +60 -39
  79. data/lib/active_record/counter_cache.rb +23 -10
  80. data/lib/active_record/database_configurations/connection_url_resolver.rb +7 -2
  81. data/lib/active_record/database_configurations/database_config.rb +19 -4
  82. data/lib/active_record/database_configurations/hash_config.rb +44 -36
  83. data/lib/active_record/database_configurations/url_config.rb +20 -1
  84. data/lib/active_record/database_configurations.rb +1 -1
  85. data/lib/active_record/delegated_type.rb +30 -6
  86. data/lib/active_record/destroy_association_async_job.rb +1 -1
  87. data/lib/active_record/dynamic_matchers.rb +2 -2
  88. data/lib/active_record/encryption/encryptable_record.rb +3 -3
  89. data/lib/active_record/encryption/encrypted_attribute_type.rb +26 -6
  90. data/lib/active_record/encryption/encryptor.rb +18 -3
  91. data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
  92. data/lib/active_record/encryption/message_serializer.rb +4 -0
  93. data/lib/active_record/encryption/null_encryptor.rb +4 -0
  94. data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
  95. data/lib/active_record/encryption/scheme.rb +8 -4
  96. data/lib/active_record/enum.rb +26 -6
  97. data/lib/active_record/errors.rb +46 -20
  98. data/lib/active_record/explain.rb +13 -24
  99. data/lib/active_record/fixtures.rb +37 -31
  100. data/lib/active_record/future_result.rb +17 -4
  101. data/lib/active_record/gem_version.rb +3 -3
  102. data/lib/active_record/inheritance.rb +4 -2
  103. data/lib/active_record/insert_all.rb +18 -15
  104. data/lib/active_record/integration.rb +4 -1
  105. data/lib/active_record/internal_metadata.rb +48 -34
  106. data/lib/active_record/locking/optimistic.rb +8 -7
  107. data/lib/active_record/log_subscriber.rb +0 -21
  108. data/lib/active_record/marshalling.rb +1 -1
  109. data/lib/active_record/message_pack.rb +2 -2
  110. data/lib/active_record/migration/command_recorder.rb +2 -3
  111. data/lib/active_record/migration/compatibility.rb +11 -3
  112. data/lib/active_record/migration/default_strategy.rb +4 -5
  113. data/lib/active_record/migration/pending_migration_connection.rb +2 -2
  114. data/lib/active_record/migration.rb +85 -76
  115. data/lib/active_record/model_schema.rb +39 -70
  116. data/lib/active_record/nested_attributes.rb +11 -3
  117. data/lib/active_record/normalization.rb +3 -7
  118. data/lib/active_record/persistence.rb +32 -354
  119. data/lib/active_record/query_cache.rb +18 -6
  120. data/lib/active_record/query_logs.rb +15 -0
  121. data/lib/active_record/query_logs_formatter.rb +1 -1
  122. data/lib/active_record/querying.rb +21 -9
  123. data/lib/active_record/railtie.rb +54 -67
  124. data/lib/active_record/railties/controller_runtime.rb +13 -4
  125. data/lib/active_record/railties/databases.rake +42 -45
  126. data/lib/active_record/reflection.rb +102 -37
  127. data/lib/active_record/relation/batches/batch_enumerator.rb +15 -2
  128. data/lib/active_record/relation/batches.rb +14 -8
  129. data/lib/active_record/relation/calculations.rb +95 -62
  130. data/lib/active_record/relation/delegation.rb +8 -11
  131. data/lib/active_record/relation/finder_methods.rb +16 -2
  132. data/lib/active_record/relation/merger.rb +4 -6
  133. data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
  134. data/lib/active_record/relation/predicate_builder/association_query_value.rb +9 -3
  135. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +6 -1
  136. data/lib/active_record/relation/predicate_builder.rb +3 -3
  137. data/lib/active_record/relation/query_methods.rb +212 -47
  138. data/lib/active_record/relation/record_fetch_warning.rb +3 -0
  139. data/lib/active_record/relation/spawn_methods.rb +2 -18
  140. data/lib/active_record/relation/where_clause.rb +7 -19
  141. data/lib/active_record/relation.rb +500 -66
  142. data/lib/active_record/result.rb +32 -45
  143. data/lib/active_record/runtime_registry.rb +39 -0
  144. data/lib/active_record/sanitization.rb +24 -19
  145. data/lib/active_record/schema.rb +8 -6
  146. data/lib/active_record/schema_dumper.rb +19 -9
  147. data/lib/active_record/schema_migration.rb +30 -14
  148. data/lib/active_record/scoping/named.rb +1 -0
  149. data/lib/active_record/signed_id.rb +20 -1
  150. data/lib/active_record/statement_cache.rb +7 -7
  151. data/lib/active_record/table_metadata.rb +1 -10
  152. data/lib/active_record/tasks/database_tasks.rb +87 -48
  153. data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
  154. data/lib/active_record/tasks/postgresql_database_tasks.rb +1 -1
  155. data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -1
  156. data/lib/active_record/test_fixtures.rb +87 -89
  157. data/lib/active_record/testing/query_assertions.rb +121 -0
  158. data/lib/active_record/timestamp.rb +5 -3
  159. data/lib/active_record/token_for.rb +22 -12
  160. data/lib/active_record/touch_later.rb +1 -1
  161. data/lib/active_record/transaction.rb +132 -0
  162. data/lib/active_record/transactions.rb +70 -14
  163. data/lib/active_record/translation.rb +0 -2
  164. data/lib/active_record/type/serialized.rb +1 -3
  165. data/lib/active_record/type_caster/connection.rb +4 -4
  166. data/lib/active_record/validations/associated.rb +9 -3
  167. data/lib/active_record/validations/uniqueness.rb +14 -10
  168. data/lib/active_record/validations.rb +4 -1
  169. data/lib/active_record.rb +150 -41
  170. data/lib/arel/alias_predication.rb +1 -1
  171. data/lib/arel/collectors/bind.rb +2 -0
  172. data/lib/arel/collectors/composite.rb +7 -0
  173. data/lib/arel/collectors/sql_string.rb +1 -1
  174. data/lib/arel/collectors/substitute_binds.rb +1 -1
  175. data/lib/arel/nodes/binary.rb +0 -6
  176. data/lib/arel/nodes/bound_sql_literal.rb +9 -5
  177. data/lib/arel/nodes/{and.rb → nary.rb} +5 -2
  178. data/lib/arel/nodes/node.rb +4 -3
  179. data/lib/arel/nodes/sql_literal.rb +7 -0
  180. data/lib/arel/nodes.rb +2 -2
  181. data/lib/arel/predications.rb +1 -1
  182. data/lib/arel/select_manager.rb +1 -1
  183. data/lib/arel/tree_manager.rb +8 -3
  184. data/lib/arel/update_manager.rb +2 -1
  185. data/lib/arel/visitors/dot.rb +1 -0
  186. data/lib/arel/visitors/mysql.rb +9 -4
  187. data/lib/arel/visitors/postgresql.rb +1 -12
  188. data/lib/arel/visitors/to_sql.rb +31 -17
  189. data/lib/arel.rb +7 -3
  190. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
  191. 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,75 +404,51 @@ 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
434
+ load_schema unless @columns
431
435
  @columns ||= columns_hash.values.freeze
432
436
  end
433
437
 
434
- def _returning_columns_for_insert # :nodoc:
435
- @_returning_columns_for_insert ||= columns.filter_map do |c|
436
- c.name if connection.return_value_after_insert?(c)
437
- end
438
- end
438
+ def _returning_columns_for_insert(connection) # :nodoc:
439
+ @_returning_columns_for_insert ||= begin
440
+ auto_populated_columns = columns.filter_map do |c|
441
+ c.name if connection.return_value_after_insert?(c)
442
+ end
439
443
 
440
- def attribute_types # :nodoc:
441
- load_schema
442
- @attribute_types ||= Hash.new(Type.default_value)
444
+ auto_populated_columns.empty? ? Array(primary_key) : auto_populated_columns
445
+ end
443
446
  end
444
447
 
445
448
  def yaml_encoder # :nodoc:
446
449
  @yaml_encoder ||= ActiveModel::AttributeSet::YAMLEncoder.new(attribute_types)
447
450
  end
448
451
 
449
- # Returns the type of the attribute with the given name, after applying
450
- # all modifiers. This method is the only valid source of information for
451
- # anything related to the types of a model's attributes. This method will
452
- # access the database and load the model's schema if it is required.
453
- #
454
- # The return value of this method will implement the interface described
455
- # by ActiveModel::Type::Value (though the object itself may not subclass
456
- # it).
457
- #
458
- # +attr_name+ The name of the attribute to retrieve the type for. Must be
459
- # a string or a symbol.
460
- def type_for_attribute(attr_name, &block)
461
- attr_name = attr_name.to_s
462
- attr_name = attribute_aliases[attr_name] || attr_name
463
-
464
- if block
465
- attribute_types.fetch(attr_name, &block)
466
- else
467
- attribute_types[attr_name]
468
- end
469
- end
470
-
471
452
  # Returns the column object for the named attribute.
472
453
  # Returns an ActiveRecord::ConnectionAdapters::NullColumn if the
473
454
  # named attribute does not exist.
@@ -495,11 +476,6 @@ module ActiveRecord
495
476
  @column_defaults ||= _default_attributes.deep_dup.to_hash.freeze
496
477
  end
497
478
 
498
- def _default_attributes # :nodoc:
499
- load_schema
500
- @default_attributes ||= ActiveModel::AttributeSet.new({})
501
- end
502
-
503
479
  # Returns an array of column names as strings.
504
480
  def column_names
505
481
  @column_names ||= columns.map(&:name).freeze
@@ -527,7 +503,7 @@ module ActiveRecord
527
503
  # when just after creating a table you want to populate it with some default
528
504
  # values, e.g.:
529
505
  #
530
- # class CreateJobLevels < ActiveRecord::Migration[7.1]
506
+ # class CreateJobLevels < ActiveRecord::Migration[7.2]
531
507
  # def up
532
508
  # create_table :job_levels do |t|
533
509
  # t.integer :id
@@ -547,18 +523,20 @@ module ActiveRecord
547
523
  # end
548
524
  # end
549
525
  def reset_column_information
550
- connection.clear_cache!
526
+ connection_pool.active_connection&.clear_cache!
551
527
  ([self] + descendants).each(&:undefine_attribute_methods)
552
- connection.schema_cache.clear_data_source_cache!(table_name)
528
+ schema_cache.clear_data_source_cache!(table_name)
553
529
 
554
530
  reload_schema_from_cache
555
531
  initialize_find_by_cache
556
532
  end
557
533
 
558
- def load_schema # :nodoc:
534
+ # Load the model's schema information either from the schema cache
535
+ # or directly from the database.
536
+ def load_schema
559
537
  return if schema_loaded?
560
538
  @load_schema_monitor.synchronize do
561
- return if @columns_hash
539
+ return if schema_loaded?
562
540
 
563
541
  load_schema!
564
542
 
@@ -579,9 +557,7 @@ module ActiveRecord
579
557
  @arel_table = nil
580
558
  @column_names = nil
581
559
  @symbol_column_to_string_name_hash = nil
582
- @attribute_types = nil
583
560
  @content_columns = nil
584
- @default_attributes = nil
585
561
  @column_defaults = nil
586
562
  @attributes_builder = nil
587
563
  @columns = nil
@@ -607,7 +583,7 @@ module ActiveRecord
607
583
  end
608
584
 
609
585
  def schema_loaded?
610
- defined?(@schema_loaded) && @schema_loaded
586
+ @schema_loaded
611
587
  end
612
588
 
613
589
  def load_schema!
@@ -615,20 +591,11 @@ module ActiveRecord
615
591
  raise ActiveRecord::TableNotSpecified, "#{self} has no table configured. Set one with #{self}.table_name="
616
592
  end
617
593
 
618
- columns_hash = connection.schema_cache.columns_hash(table_name)
594
+ columns_hash = schema_cache.columns_hash(table_name)
619
595
  columns_hash = columns_hash.except(*ignored_columns) unless ignored_columns.empty?
620
596
  @columns_hash = columns_hash.freeze
621
- @columns_hash.each do |name, column|
622
- type = connection.lookup_cast_type_from_column(column)
623
- type = _convert_type_from_options(type)
624
- define_attribute(
625
- name,
626
- type,
627
- default: column.default,
628
- user_provided_default: false
629
- )
630
- alias_attribute :id_value, :id if name == "id"
631
- end
597
+
598
+ super
632
599
  end
633
600
 
634
601
  # Guesses the table name, but does not decorate it with prefix and suffix information.
@@ -654,12 +621,14 @@ module ActiveRecord
654
621
  end
655
622
  end
656
623
 
657
- def _convert_type_from_options(type)
624
+ def type_for_column(connection, column)
625
+ type = connection.lookup_cast_type_from_column(column)
626
+
658
627
  if immutable_strings_by_default && type.respond_to?(:to_immutable_string)
659
- type.to_immutable_string
660
- else
661
- type
628
+ type = type.to_immutable_string
662
629
  end
630
+
631
+ type
663
632
  end
664
633
  end
665
634
  end
@@ -421,10 +421,15 @@ module ActiveRecord
421
421
  # update_only is true, and a <tt>:_destroy</tt> key set to a truthy value,
422
422
  # then the existing record will be marked for destruction.
423
423
  def assign_nested_attributes_for_one_to_one_association(association_name, attributes)
424
- options = nested_attributes_options[association_name]
425
424
  if attributes.respond_to?(:permitted?)
426
425
  attributes = attributes.to_h
427
426
  end
427
+
428
+ unless attributes.is_a?(Hash)
429
+ raise ArgumentError, "Hash expected for `#{association_name}` attributes, got #{attributes.class.name}"
430
+ end
431
+
432
+ options = nested_attributes_options[association_name]
428
433
  attributes = attributes.with_indifferent_access
429
434
  existing_record = send(association_name)
430
435
 
@@ -486,7 +491,7 @@ module ActiveRecord
486
491
  end
487
492
 
488
493
  unless attributes_collection.is_a?(Hash) || attributes_collection.is_a?(Array)
489
- raise ArgumentError, "Hash or Array expected for attribute `#{association_name}`, got #{attributes_collection.class.name} (#{attributes_collection.inspect})"
494
+ raise ArgumentError, "Hash or Array expected for `#{association_name}` attributes, got #{attributes_collection.class.name}"
490
495
  end
491
496
 
492
497
  check_record_limit!(options[:limit], attributes_collection)
@@ -509,7 +514,7 @@ module ActiveRecord
509
514
  attribute_ids.empty? ? [] : association.scope.where(association.klass.primary_key => attribute_ids)
510
515
  end
511
516
 
512
- attributes_collection.each do |attributes|
517
+ records = attributes_collection.map do |attributes|
513
518
  if attributes.respond_to?(:permitted?)
514
519
  attributes = attributes.to_h
515
520
  end
@@ -532,11 +537,14 @@ module ActiveRecord
532
537
  end
533
538
 
534
539
  assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy])
540
+ existing_record
535
541
  end
536
542
  else
537
543
  raise_nested_attributes_record_not_found!(association_name, attributes["id"])
538
544
  end
539
545
  end
546
+
547
+ association.nested_attributes_target = records
540
548
  end
541
549
 
542
550
  # Takes in a limit and checks if the attributes_collection has too many