activerecord 6.0.5.1 → 6.1.7.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (243) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1163 -774
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +2 -2
  5. data/lib/active_record/aggregations.rb +5 -5
  6. data/lib/active_record/association_relation.rb +30 -12
  7. data/lib/active_record/associations/alias_tracker.rb +19 -15
  8. data/lib/active_record/associations/association.rb +49 -26
  9. data/lib/active_record/associations/association_scope.rb +18 -20
  10. data/lib/active_record/associations/belongs_to_association.rb +23 -10
  11. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -3
  12. data/lib/active_record/associations/builder/association.rb +32 -5
  13. data/lib/active_record/associations/builder/belongs_to.rb +10 -7
  14. data/lib/active_record/associations/builder/collection_association.rb +5 -4
  15. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +0 -1
  16. data/lib/active_record/associations/builder/has_many.rb +6 -2
  17. data/lib/active_record/associations/builder/has_one.rb +11 -14
  18. data/lib/active_record/associations/builder/singular_association.rb +1 -1
  19. data/lib/active_record/associations/collection_association.rb +32 -18
  20. data/lib/active_record/associations/collection_proxy.rb +12 -5
  21. data/lib/active_record/associations/foreign_association.rb +13 -0
  22. data/lib/active_record/associations/has_many_association.rb +24 -2
  23. data/lib/active_record/associations/has_many_through_association.rb +10 -4
  24. data/lib/active_record/associations/has_one_association.rb +15 -1
  25. data/lib/active_record/associations/join_dependency/join_association.rb +37 -21
  26. data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
  27. data/lib/active_record/associations/join_dependency.rb +63 -49
  28. data/lib/active_record/associations/preloader/association.rb +14 -8
  29. data/lib/active_record/associations/preloader/through_association.rb +1 -1
  30. data/lib/active_record/associations/preloader.rb +5 -3
  31. data/lib/active_record/associations/singular_association.rb +1 -1
  32. data/lib/active_record/associations.rb +118 -11
  33. data/lib/active_record/attribute_assignment.rb +10 -8
  34. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -9
  35. data/lib/active_record/attribute_methods/dirty.rb +1 -11
  36. data/lib/active_record/attribute_methods/primary_key.rb +6 -2
  37. data/lib/active_record/attribute_methods/query.rb +3 -6
  38. data/lib/active_record/attribute_methods/read.rb +8 -11
  39. data/lib/active_record/attribute_methods/serialization.rb +11 -5
  40. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -13
  41. data/lib/active_record/attribute_methods/write.rb +12 -20
  42. data/lib/active_record/attribute_methods.rb +64 -54
  43. data/lib/active_record/attributes.rb +33 -8
  44. data/lib/active_record/autosave_association.rb +47 -30
  45. data/lib/active_record/base.rb +2 -14
  46. data/lib/active_record/callbacks.rb +152 -22
  47. data/lib/active_record/coders/yaml_column.rb +16 -6
  48. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +185 -134
  49. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
  50. data/lib/active_record/connection_adapters/abstract/database_statements.rb +66 -23
  51. data/lib/active_record/connection_adapters/abstract/query_cache.rb +3 -8
  52. data/lib/active_record/connection_adapters/abstract/quoting.rb +44 -35
  53. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  54. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -116
  55. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +114 -26
  56. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
  57. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +228 -83
  58. data/lib/active_record/connection_adapters/abstract/transaction.rb +92 -33
  59. data/lib/active_record/connection_adapters/abstract_adapter.rb +52 -76
  60. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +123 -87
  61. data/lib/active_record/connection_adapters/column.rb +15 -1
  62. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  63. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
  64. data/lib/active_record/connection_adapters/mysql/database_statements.rb +24 -24
  65. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -1
  66. data/lib/active_record/connection_adapters/mysql/quoting.rb +18 -3
  67. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +32 -6
  68. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
  69. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +5 -2
  70. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +7 -4
  71. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
  72. data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -12
  73. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  74. data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
  75. data/lib/active_record/connection_adapters/postgresql/column.rb +24 -1
  76. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +14 -53
  77. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  78. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
  79. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -2
  80. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  81. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -2
  82. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  83. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -2
  84. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -1
  85. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  86. data/lib/active_record/connection_adapters/postgresql/quoting.rb +30 -4
  87. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
  88. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +5 -1
  89. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +61 -29
  90. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
  91. data/lib/active_record/connection_adapters/postgresql_adapter.rb +75 -64
  92. data/lib/active_record/connection_adapters/schema_cache.rb +130 -15
  93. data/lib/active_record/connection_adapters/sql_type_metadata.rb +8 -0
  94. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +32 -5
  95. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -1
  96. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  97. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +36 -3
  98. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +48 -50
  99. data/lib/active_record/connection_adapters.rb +52 -0
  100. data/lib/active_record/connection_handling.rb +218 -71
  101. data/lib/active_record/core.rb +265 -64
  102. data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -0
  103. data/lib/active_record/database_configurations/database_config.rb +52 -9
  104. data/lib/active_record/database_configurations/hash_config.rb +54 -8
  105. data/lib/active_record/database_configurations/url_config.rb +15 -40
  106. data/lib/active_record/database_configurations.rb +125 -85
  107. data/lib/active_record/delegated_type.rb +209 -0
  108. data/lib/active_record/destroy_association_async_job.rb +36 -0
  109. data/lib/active_record/enum.rb +69 -34
  110. data/lib/active_record/errors.rb +47 -12
  111. data/lib/active_record/explain.rb +9 -4
  112. data/lib/active_record/explain_subscriber.rb +1 -1
  113. data/lib/active_record/fixture_set/file.rb +10 -17
  114. data/lib/active_record/fixture_set/model_metadata.rb +1 -2
  115. data/lib/active_record/fixture_set/render_context.rb +1 -1
  116. data/lib/active_record/fixture_set/table_row.rb +2 -2
  117. data/lib/active_record/fixtures.rb +58 -9
  118. data/lib/active_record/gem_version.rb +3 -3
  119. data/lib/active_record/inheritance.rb +40 -18
  120. data/lib/active_record/insert_all.rb +38 -5
  121. data/lib/active_record/integration.rb +3 -5
  122. data/lib/active_record/internal_metadata.rb +18 -7
  123. data/lib/active_record/legacy_yaml_adapter.rb +7 -3
  124. data/lib/active_record/locking/optimistic.rb +24 -17
  125. data/lib/active_record/locking/pessimistic.rb +6 -2
  126. data/lib/active_record/log_subscriber.rb +27 -8
  127. data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
  128. data/lib/active_record/middleware/database_selector/resolver.rb +5 -0
  129. data/lib/active_record/middleware/database_selector.rb +4 -1
  130. data/lib/active_record/migration/command_recorder.rb +47 -27
  131. data/lib/active_record/migration/compatibility.rb +72 -18
  132. data/lib/active_record/migration.rb +114 -84
  133. data/lib/active_record/model_schema.rb +89 -14
  134. data/lib/active_record/nested_attributes.rb +2 -3
  135. data/lib/active_record/no_touching.rb +1 -1
  136. data/lib/active_record/persistence.rb +50 -45
  137. data/lib/active_record/query_cache.rb +15 -5
  138. data/lib/active_record/querying.rb +11 -6
  139. data/lib/active_record/railtie.rb +61 -59
  140. data/lib/active_record/railties/console_sandbox.rb +2 -4
  141. data/lib/active_record/railties/databases.rake +279 -101
  142. data/lib/active_record/readonly_attributes.rb +4 -0
  143. data/lib/active_record/reflection.rb +60 -44
  144. data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
  145. data/lib/active_record/relation/batches.rb +38 -31
  146. data/lib/active_record/relation/calculations.rb +104 -43
  147. data/lib/active_record/relation/finder_methods.rb +44 -14
  148. data/lib/active_record/relation/from_clause.rb +1 -1
  149. data/lib/active_record/relation/merger.rb +20 -23
  150. data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
  151. data/lib/active_record/relation/predicate_builder/association_query_value.rb +4 -5
  152. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -6
  153. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  154. data/lib/active_record/relation/predicate_builder.rb +61 -38
  155. data/lib/active_record/relation/query_methods.rb +324 -196
  156. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  157. data/lib/active_record/relation/spawn_methods.rb +8 -7
  158. data/lib/active_record/relation/where_clause.rb +111 -61
  159. data/lib/active_record/relation.rb +100 -81
  160. data/lib/active_record/result.rb +41 -33
  161. data/lib/active_record/runtime_registry.rb +2 -2
  162. data/lib/active_record/sanitization.rb +6 -17
  163. data/lib/active_record/schema_dumper.rb +34 -4
  164. data/lib/active_record/schema_migration.rb +2 -8
  165. data/lib/active_record/scoping/default.rb +1 -3
  166. data/lib/active_record/scoping/named.rb +1 -17
  167. data/lib/active_record/secure_token.rb +16 -8
  168. data/lib/active_record/serialization.rb +5 -3
  169. data/lib/active_record/signed_id.rb +116 -0
  170. data/lib/active_record/statement_cache.rb +20 -4
  171. data/lib/active_record/store.rb +8 -3
  172. data/lib/active_record/suppressor.rb +2 -2
  173. data/lib/active_record/table_metadata.rb +42 -51
  174. data/lib/active_record/tasks/database_tasks.rb +140 -113
  175. data/lib/active_record/tasks/mysql_database_tasks.rb +34 -35
  176. data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -26
  177. data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -9
  178. data/lib/active_record/test_databases.rb +5 -4
  179. data/lib/active_record/test_fixtures.rb +79 -31
  180. data/lib/active_record/timestamp.rb +4 -6
  181. data/lib/active_record/touch_later.rb +21 -21
  182. data/lib/active_record/transactions.rb +19 -66
  183. data/lib/active_record/type/serialized.rb +6 -2
  184. data/lib/active_record/type.rb +8 -1
  185. data/lib/active_record/type_caster/connection.rb +0 -1
  186. data/lib/active_record/type_caster/map.rb +8 -5
  187. data/lib/active_record/validations/associated.rb +1 -1
  188. data/lib/active_record/validations/numericality.rb +35 -0
  189. data/lib/active_record/validations/uniqueness.rb +24 -4
  190. data/lib/active_record/validations.rb +1 -0
  191. data/lib/active_record.rb +7 -14
  192. data/lib/arel/attributes/attribute.rb +4 -0
  193. data/lib/arel/collectors/bind.rb +5 -0
  194. data/lib/arel/collectors/composite.rb +8 -0
  195. data/lib/arel/collectors/sql_string.rb +7 -0
  196. data/lib/arel/collectors/substitute_binds.rb +7 -0
  197. data/lib/arel/nodes/binary.rb +82 -8
  198. data/lib/arel/nodes/bind_param.rb +8 -0
  199. data/lib/arel/nodes/casted.rb +21 -9
  200. data/lib/arel/nodes/equality.rb +6 -9
  201. data/lib/arel/nodes/grouping.rb +3 -0
  202. data/lib/arel/nodes/homogeneous_in.rb +76 -0
  203. data/lib/arel/nodes/in.rb +8 -1
  204. data/lib/arel/nodes/infix_operation.rb +13 -1
  205. data/lib/arel/nodes/join_source.rb +1 -1
  206. data/lib/arel/nodes/node.rb +7 -6
  207. data/lib/arel/nodes/ordering.rb +27 -0
  208. data/lib/arel/nodes/sql_literal.rb +3 -0
  209. data/lib/arel/nodes/table_alias.rb +7 -3
  210. data/lib/arel/nodes/unary.rb +0 -1
  211. data/lib/arel/nodes.rb +3 -1
  212. data/lib/arel/predications.rb +12 -18
  213. data/lib/arel/select_manager.rb +1 -2
  214. data/lib/arel/table.rb +13 -5
  215. data/lib/arel/visitors/dot.rb +14 -2
  216. data/lib/arel/visitors/mysql.rb +11 -1
  217. data/lib/arel/visitors/postgresql.rb +15 -4
  218. data/lib/arel/visitors/to_sql.rb +89 -78
  219. data/lib/arel/visitors.rb +0 -7
  220. data/lib/arel.rb +5 -13
  221. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
  222. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
  223. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +3 -3
  224. data/lib/rails/generators/active_record/migration.rb +6 -1
  225. data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
  226. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  227. metadata +24 -25
  228. data/lib/active_record/advisory_lock_base.rb +0 -18
  229. data/lib/active_record/attribute_decorators.rb +0 -88
  230. data/lib/active_record/connection_adapters/connection_specification.rb +0 -296
  231. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
  232. data/lib/active_record/define_callbacks.rb +0 -22
  233. data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
  234. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
  235. data/lib/active_record/relation/where_clause_factory.rb +0 -33
  236. data/lib/arel/attributes.rb +0 -22
  237. data/lib/arel/visitors/depth_first.rb +0 -203
  238. data/lib/arel/visitors/ibm_db.rb +0 -34
  239. data/lib/arel/visitors/informix.rb +0 -62
  240. data/lib/arel/visitors/mssql.rb +0 -156
  241. data/lib/arel/visitors/oracle.rb +0 -158
  242. data/lib/arel/visitors/oracle12.rb +0 -65
  243. data/lib/arel/visitors/where_sql.rb +0 -22
@@ -2,7 +2,6 @@
2
2
 
3
3
  require "active_support/core_ext/hash/except"
4
4
  require "active_support/core_ext/module/redefine_method"
5
- require "active_support/core_ext/object/try"
6
5
  require "active_support/core_ext/hash/indifferent_access"
7
6
 
8
7
  module ActiveRecord
@@ -289,7 +288,7 @@ module ActiveRecord
289
288
  # [:allow_destroy]
290
289
  # If true, destroys any members from the attributes hash with a
291
290
  # <tt>_destroy</tt> key and a value that evaluates to +true+
292
- # (eg. 1, '1', true, or 'true'). This option is off by default.
291
+ # (e.g. 1, '1', true, or 'true'). This option is off by default.
293
292
  # [:reject_if]
294
293
  # Allows you to specify a Proc or a Symbol pointing to a method
295
294
  # that checks whether a record should be built for a certain attribute
@@ -510,7 +509,7 @@ module ActiveRecord
510
509
  if target_record
511
510
  existing_record = target_record
512
511
  else
513
- association.add_to_target(existing_record, :skip_callbacks)
512
+ association.add_to_target(existing_record, skip_callbacks: true)
514
513
  end
515
514
 
516
515
  assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy])
@@ -54,7 +54,7 @@ module ActiveRecord
54
54
  NoTouching.applied_to?(self.class)
55
55
  end
56
56
 
57
- def touch_later(*, **) # :nodoc:
57
+ def touch_later(*) # :nodoc:
58
58
  super unless no_touching?
59
59
  end
60
60
 
@@ -414,8 +414,8 @@ module ActiveRecord
414
414
 
415
415
  def _substitute_values(values)
416
416
  values.map do |name, value|
417
- attr = arel_attribute(name)
418
- bind = predicate_builder.build_bind_attribute(name, value)
417
+ attr = arel_table[name]
418
+ bind = predicate_builder.build_bind_attribute(attr.name, value)
419
419
  [attr, bind]
420
420
  end
421
421
  end
@@ -424,26 +424,30 @@ module ActiveRecord
424
424
  # Returns true if this object hasn't been saved yet -- that is, a record
425
425
  # for the object doesn't exist in the database yet; otherwise, returns false.
426
426
  def new_record?
427
- sync_with_transaction_state if @transaction_state&.finalized?
428
427
  @new_record
429
428
  end
430
429
 
430
+ # Returns true if this object was just created -- that is, prior to the last
431
+ # save, the object didn't exist in the database and new_record? would have
432
+ # returned true.
433
+ def previously_new_record?
434
+ @previously_new_record
435
+ end
436
+
431
437
  # Returns true if this object has been destroyed, otherwise returns false.
432
438
  def destroyed?
433
- sync_with_transaction_state if @transaction_state&.finalized?
434
439
  @destroyed
435
440
  end
436
441
 
437
442
  # Returns true if the record is persisted, i.e. it's not a new record and it was
438
443
  # not destroyed, otherwise returns false.
439
444
  def persisted?
440
- sync_with_transaction_state if @transaction_state&.finalized?
441
445
  !(@new_record || @destroyed)
442
446
  end
443
447
 
444
448
  ##
445
449
  # :call-seq:
446
- # save(*args)
450
+ # save(**options)
447
451
  #
448
452
  # Saves the model.
449
453
  #
@@ -466,15 +470,15 @@ module ActiveRecord
466
470
  #
467
471
  # Attributes marked as readonly are silently ignored if the record is
468
472
  # being updated.
469
- def save(*args, **options, &block)
470
- create_or_update(*args, **options, &block)
473
+ def save(**options, &block)
474
+ create_or_update(**options, &block)
471
475
  rescue ActiveRecord::RecordInvalid
472
476
  false
473
477
  end
474
478
 
475
479
  ##
476
480
  # :call-seq:
477
- # save!(*args)
481
+ # save!(**options)
478
482
  #
479
483
  # Saves the model.
480
484
  #
@@ -499,8 +503,8 @@ module ActiveRecord
499
503
  # being updated.
500
504
  #
501
505
  # Unless an error is raised, returns true.
502
- def save!(*args, **options, &block)
503
- create_or_update(*args, **options, &block) || raise(RecordNotSaved.new("Failed to save the record", self))
506
+ def save!(**options, &block)
507
+ create_or_update(**options, &block) || raise(RecordNotSaved.new("Failed to save the record", self))
504
508
  end
505
509
 
506
510
  # Deletes the record in the database and freezes this instance to
@@ -514,7 +518,7 @@ module ActiveRecord
514
518
  #
515
519
  # To enforce the object's +before_destroy+ and +after_destroy+
516
520
  # callbacks or any <tt>:dependent</tt> association
517
- # options, use <tt>#destroy</tt>.
521
+ # options, use #destroy.
518
522
  def delete
519
523
  _delete_row if persisted?
520
524
  @destroyed = true
@@ -565,12 +569,15 @@ module ActiveRecord
565
569
  # If you want to change the sti column as well, use #becomes! instead.
566
570
  def becomes(klass)
567
571
  became = klass.allocate
568
- became.send(:initialize)
569
- became.instance_variable_set("@attributes", @attributes)
570
- became.instance_variable_set("@mutations_from_database", @mutations_from_database ||= nil)
571
- became.instance_variable_set("@new_record", new_record?)
572
- became.instance_variable_set("@destroyed", destroyed?)
573
- became.errors.copy!(errors)
572
+
573
+ became.send(:initialize) do |becoming|
574
+ becoming.instance_variable_set(:@attributes, @attributes)
575
+ becoming.instance_variable_set(:@mutations_from_database, @mutations_from_database ||= nil)
576
+ becoming.instance_variable_set(:@new_record, new_record?)
577
+ becoming.instance_variable_set(:@destroyed, destroyed?)
578
+ becoming.errors.copy!(errors)
579
+ end
580
+
574
581
  became
575
582
  end
576
583
 
@@ -622,9 +629,6 @@ module ActiveRecord
622
629
  end
623
630
  end
624
631
 
625
- alias update_attributes update
626
- deprecate update_attributes: "please, use update instead"
627
-
628
632
  # Updates its receiver just like #update but calls #save! instead
629
633
  # of +save+, so an exception is raised if the record is invalid and saving will fail.
630
634
  def update!(attributes)
@@ -636,9 +640,6 @@ module ActiveRecord
636
640
  end
637
641
  end
638
642
 
639
- alias update_attributes! update!
640
- deprecate update_attributes!: "please, use update! instead"
641
-
642
643
  # Equivalent to <code>update_columns(name => value)</code>.
643
644
  def update_column(name, value)
644
645
  update_columns(name => value)
@@ -666,11 +667,8 @@ module ActiveRecord
666
667
 
667
668
  attributes = attributes.transform_keys do |key|
668
669
  name = key.to_s
669
- self.class.attribute_aliases[name] || name
670
- end
671
-
672
- attributes.each_key do |key|
673
- verify_readonly_attribute(key)
670
+ name = self.class.attribute_aliases[name] || name
671
+ verify_readonly_attribute(name) || name
674
672
  end
675
673
 
676
674
  id_in_database = self.id_in_database
@@ -703,9 +701,9 @@ module ActiveRecord
703
701
  # Returns +self+.
704
702
  def increment!(attribute, by = 1, touch: nil)
705
703
  increment(attribute, by)
706
- change = public_send(attribute) - (attribute_in_database(attribute.to_s) || 0)
704
+ change = public_send(attribute) - (public_send(:"#{attribute}_in_database") || 0)
707
705
  self.class.update_counters(id, attribute => change, touch: touch)
708
- clear_attribute_change(attribute) # eww
706
+ public_send(:"clear_#{attribute}_change")
709
707
  self
710
708
  end
711
709
 
@@ -809,8 +807,9 @@ module ActiveRecord
809
807
  self.class.unscoped { self.class.find(id) }
810
808
  end
811
809
 
812
- @attributes = fresh_object.instance_variable_get("@attributes")
810
+ @attributes = fresh_object.instance_variable_get(:@attributes)
813
811
  @new_record = false
812
+ @previously_new_record = false
814
813
  self
815
814
  end
816
815
 
@@ -849,17 +848,13 @@ module ActiveRecord
849
848
  # ball.touch(:updated_at) # => raises ActiveRecordError
850
849
  #
851
850
  def touch(*names, time: nil)
852
- unless persisted?
853
- raise ActiveRecordError, <<-MSG.squish
854
- cannot touch on a new or destroyed record object. Consider using
855
- persisted?, new_record?, or destroyed? before touching
856
- MSG
857
- end
851
+ _raise_record_not_touched_error unless persisted?
858
852
 
859
853
  attribute_names = timestamp_attributes_for_update_in_model
860
- attribute_names |= names.map!(&:to_s).map! { |name|
854
+ attribute_names |= names.map! do |name|
855
+ name = name.to_s
861
856
  self.class.attribute_aliases[name] || name
862
- }
857
+ end unless names.empty?
863
858
 
864
859
  unless attribute_names.empty?
865
860
  affected_rows = _touch_row(attribute_names, time)
@@ -919,6 +914,8 @@ module ActiveRecord
919
914
  @_trigger_update_callback = affected_rows == 1
920
915
  end
921
916
 
917
+ @previously_new_record = false
918
+
922
919
  yield(self) if block_given?
923
920
 
924
921
  affected_rows
@@ -936,6 +933,7 @@ module ActiveRecord
936
933
  self.id ||= new_id if @primary_key
937
934
 
938
935
  @new_record = false
936
+ @previously_new_record = true
939
937
 
940
938
  yield(self) if block_given?
941
939
 
@@ -943,7 +941,7 @@ module ActiveRecord
943
941
  end
944
942
 
945
943
  def verify_readonly_attribute(name)
946
- raise ActiveRecordError, "#{name} is marked as readonly" if self.class.readonly_attributes.include?(name)
944
+ raise ActiveRecordError, "#{name} is marked as readonly" if self.class.readonly_attribute?(name)
947
945
  end
948
946
 
949
947
  def _raise_record_not_destroyed
@@ -953,14 +951,21 @@ module ActiveRecord
953
951
  @_association_destroy_exception = nil
954
952
  end
955
953
 
954
+ def _raise_readonly_record_error
955
+ raise ReadOnlyRecord, "#{self.class} is marked as readonly"
956
+ end
957
+
958
+ def _raise_record_not_touched_error
959
+ raise ActiveRecordError, <<~MSG.squish
960
+ Cannot touch on a new or destroyed record object. Consider using
961
+ persisted?, new_record?, or destroyed? before touching.
962
+ MSG
963
+ end
964
+
956
965
  # The name of the method used to touch a +belongs_to+ association when the
957
966
  # +:touch+ option is used.
958
967
  def belongs_to_touch_method
959
968
  :touch
960
969
  end
961
-
962
- def _raise_readonly_record_error
963
- raise ReadOnlyRecord, "#{self.class} is marked as readonly"
964
- end
965
970
  end
966
971
  end
@@ -28,18 +28,28 @@ module ActiveRecord
28
28
  def self.run
29
29
  pools = []
30
30
 
31
- ActiveRecord::Base.connection_handlers.each do |key, handler|
32
- pools << handler.connection_pool_list.reject { |p| p.query_cache_enabled }.each { |p| p.enable_query_cache! }
31
+ if ActiveRecord::Base.legacy_connection_handling
32
+ ActiveRecord::Base.connection_handlers.each do |key, handler|
33
+ pools.concat(handler.connection_pool_list.reject { |p| p.query_cache_enabled }.each { |p| p.enable_query_cache! })
34
+ end
35
+ else
36
+ pools.concat(ActiveRecord::Base.connection_handler.all_connection_pools.reject { |p| p.query_cache_enabled }.each { |p| p.enable_query_cache! })
33
37
  end
34
38
 
35
- pools.flatten
39
+ pools
36
40
  end
37
41
 
38
42
  def self.complete(pools)
39
43
  pools.each { |pool| pool.disable_query_cache! }
40
44
 
41
- ActiveRecord::Base.connection_handlers.each do |_, handler|
42
- handler.connection_pool_list.each do |pool|
45
+ if ActiveRecord::Base.legacy_connection_handling
46
+ ActiveRecord::Base.connection_handlers.each do |_, handler|
47
+ handler.connection_pool_list.each do |pool|
48
+ pool.release_connection if pool.active_connection? && !pool.connection.transaction_open?
49
+ end
50
+ end
51
+ else
52
+ ActiveRecord::Base.connection_handler.all_connection_pools.each do |pool|
43
53
  pool.release_connection if pool.active_connection? && !pool.connection.transaction_open?
44
54
  end
45
55
  end
@@ -13,10 +13,11 @@ module ActiveRecord
13
13
  :destroy_all, :delete_all, :update_all, :touch_all, :destroy_by, :delete_by,
14
14
  :find_each, :find_in_batches, :in_batches,
15
15
  :select, :reselect, :order, :reorder, :group, :limit, :offset, :joins, :left_joins, :left_outer_joins,
16
- :where, :rewhere, :preload, :extract_associated, :eager_load, :includes, :from, :lock, :readonly, :extending, :or,
17
- :having, :create_with, :distinct, :references, :none, :unscope, :optimizer_hints, :merge, :except, :only,
18
- :count, :average, :minimum, :maximum, :sum, :calculate, :annotate,
19
- :pluck, :pick, :ids
16
+ :where, :rewhere, :preload, :extract_associated, :eager_load, :includes, :from, :lock, :readonly,
17
+ :and, :or, :annotate, :optimizer_hints, :extending,
18
+ :having, :create_with, :distinct, :references, :none, :unscope, :merge, :except, :only,
19
+ :count, :average, :minimum, :maximum, :sum, :calculate,
20
+ :pluck, :pick, :ids, :strict_loading
20
21
  ].freeze # :nodoc:
21
22
  delegate(*QUERYING_METHODS, to: :all)
22
23
 
@@ -44,8 +45,12 @@ module ActiveRecord
44
45
  # Post.find_by_sql ["SELECT body FROM comments WHERE author = :user_id OR approved_by = :user_id", { :user_id => user_id }]
45
46
  def find_by_sql(sql, binds = [], preparable: nil, &block)
46
47
  result_set = connection.select_all(sanitize_sql(sql), "#{name} Load", binds, preparable: preparable)
47
- column_types = result_set.column_types.dup
48
- attribute_types.each_key { |k| column_types.delete k }
48
+ column_types = result_set.column_types
49
+
50
+ unless column_types.empty?
51
+ column_types = column_types.reject { |k, _| attribute_types.key?(k) }
52
+ end
53
+
49
54
  message_bus = ActiveSupport::Notifications.instrumenter
50
55
 
51
56
  payload = {
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "active_record"
4
4
  require "rails"
5
+ require "active_support/core_ext/object/try"
5
6
  require "active_model/railtie"
6
7
 
7
8
  # For now, action_controller must always be present with
@@ -26,18 +27,17 @@ module ActiveRecord
26
27
  )
27
28
 
28
29
  config.active_record.use_schema_cache_dump = true
30
+ config.active_record.check_schema_cache_dump_version = true
29
31
  config.active_record.maintain_test_schema = true
32
+ config.active_record.has_many_inversing = false
30
33
 
31
- config.active_record.sqlite3 = ActiveSupport::OrderedOptions.new
32
- config.active_record.sqlite3.represent_boolean_as_integer = nil
34
+ config.active_record.queues = ActiveSupport::InheritableOptions.new
33
35
 
34
36
  config.eager_load_namespaces << ActiveRecord
35
37
 
36
38
  rake_tasks do
37
39
  namespace :db do
38
40
  task :load_config do
39
- ActiveRecord::Tasks::DatabaseTasks.database_configuration = Rails.application.config.database_configuration
40
-
41
41
  if defined?(ENGINE_ROOT) && engine = Rails::Engine.find(ENGINE_ROOT)
42
42
  if engine.paths["db/migrate"].existent
43
43
  ActiveRecord::Tasks::DatabaseTasks.migrations_paths += engine.paths["db/migrate"].to_a
@@ -57,6 +57,7 @@ module ActiveRecord
57
57
  require "active_record/base"
58
58
  unless ActiveSupport::Logger.logger_outputs_to?(Rails.logger, STDERR, STDOUT)
59
59
  console = ActiveSupport::Logger.new(STDERR)
60
+ console.level = Rails.logger.level
60
61
  Rails.logger.extend ActiveSupport::Logger.broadcast console
61
62
  end
62
63
  ActiveRecord::Base.verbose_query_logs = false
@@ -81,10 +82,11 @@ module ActiveRecord
81
82
  ActiveSupport.on_load(:active_record) { LogSubscriber.backtrace_cleaner = ::Rails.backtrace_cleaner }
82
83
  end
83
84
 
84
- initializer "active_record.migration_error" do
85
+ initializer "active_record.migration_error" do |app|
85
86
  if config.active_record.delete(:migration_error) == :page_load
86
87
  config.app_middleware.insert_after ::ActionDispatch::Callbacks,
87
- ActiveRecord::Migration::CheckPending
88
+ ActiveRecord::Migration::CheckPending,
89
+ file_watcher: app.config.file_watcher
88
90
  end
89
91
  end
90
92
 
@@ -122,23 +124,37 @@ To keep using the current cache store, you can turn off cache versioning entirel
122
124
  end
123
125
 
124
126
  initializer "active_record.check_schema_cache_dump" do
127
+ check_schema_cache_dump_version = config.active_record.delete(:check_schema_cache_dump_version)
128
+
125
129
  if config.active_record.delete(:use_schema_cache_dump)
126
130
  config.after_initialize do |app|
127
131
  ActiveSupport.on_load(:active_record) do
128
- filename = File.join(app.config.paths["db"].first, "schema_cache.yml")
129
-
130
- if File.file?(filename)
131
- current_version = ActiveRecord::Migrator.current_version
132
-
132
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env).first
133
+
134
+ filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(
135
+ db_config.name,
136
+ schema_cache_path: db_config&.schema_cache_path
137
+ )
138
+
139
+ cache = ActiveRecord::ConnectionAdapters::SchemaCache.load_from(filename)
140
+ next if cache.nil?
141
+
142
+ if check_schema_cache_dump_version
143
+ current_version = begin
144
+ ActiveRecord::Migrator.current_version
145
+ rescue ActiveRecordError => error
146
+ warn "Failed to validate the schema cache because of #{error.class}: #{error.message}"
147
+ nil
148
+ end
133
149
  next if current_version.nil?
134
150
 
135
- cache = YAML.load(File.read(filename))
136
- if cache.version == current_version
137
- connection_pool.schema_cache = cache.dup
138
- else
139
- warn "Ignoring db/schema_cache.yml because it has expired. The current schema version is #{current_version}, but the one in the cache is #{cache.version}."
151
+ if cache.version != current_version
152
+ warn "Ignoring #{filename} because it has expired. The current schema version is #{current_version}, but the one in the cache is #{cache.version}."
153
+ next
140
154
  end
141
155
  end
156
+
157
+ connection_pool.set_schema_cache(cache)
142
158
  end
143
159
  end
144
160
  end
@@ -148,16 +164,29 @@ To keep using the current cache store, you can turn off cache versioning entirel
148
164
  config.after_initialize do
149
165
  ActiveSupport.on_load(:active_record) do
150
166
  if app.config.eager_load
151
- descendants.each do |model|
152
- # SchemaMigration and InternalMetadata both override `table_exists?`
153
- # to bypass the schema cache, so skip them to avoid the extra queries.
154
- next if model._internal?
155
-
156
- # If there's no connection yet, or the schema cache doesn't have the columns
157
- # hash for the model cached, `define_attribute_methods` would trigger a query.
158
- next unless model.connected? && model.connection.schema_cache.columns_hash?(model.table_name)
159
-
160
- model.define_attribute_methods
167
+ begin
168
+ descendants.each do |model|
169
+ # SchemaMigration and InternalMetadata both override `table_exists?`
170
+ # to bypass the schema cache, so skip them to avoid the extra queries.
171
+ next if model._internal?
172
+
173
+ # If the schema cache was loaded from a dump, we can use it without connecting
174
+ schema_cache = model.connection_pool.schema_cache
175
+
176
+ # If there's no connection yet, we avoid connecting.
177
+ schema_cache ||= model.connected? && model.connection.schema_cache
178
+
179
+ # If the schema cache doesn't have the columns
180
+ # hash for the model cached, `define_attribute_methods` would trigger a query.
181
+ if schema_cache && schema_cache.columns_hash?(model.table_name)
182
+ model.define_attribute_methods
183
+ end
184
+ end
185
+ rescue ActiveRecordError => error
186
+ # Regardless of whether there was already a connection or not, we rescue any database
187
+ # error because it is critical that the application can boot even if the database
188
+ # is unhealthy.
189
+ warn "Failed to define attribute methods because of #{error.class}: #{error.message}"
161
190
  end
162
191
  end
163
192
  end
@@ -176,16 +205,6 @@ To keep using the current cache store, you can turn off cache versioning entirel
176
205
  ActiveSupport.on_load(:active_record) do
177
206
  configs = app.config.active_record
178
207
 
179
- represent_boolean_as_integer = configs.sqlite3.delete(:represent_boolean_as_integer)
180
-
181
- unless represent_boolean_as_integer.nil?
182
- ActiveSupport.on_load(:active_record_sqlite3adapter) do
183
- ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = represent_boolean_as_integer
184
- end
185
- end
186
-
187
- configs.delete(:sqlite3)
188
-
189
208
  configs.each do |k, v|
190
209
  send "#{k}=", v
191
210
  end
@@ -196,7 +215,9 @@ To keep using the current cache store, you can turn off cache versioning entirel
196
215
  # and then establishes the connection.
197
216
  initializer "active_record.initialize_database" do
198
217
  ActiveSupport.on_load(:active_record) do
199
- self.connection_handlers = { writing_role => ActiveRecord::Base.default_connection_handler }
218
+ if ActiveRecord::Base.legacy_connection_handling
219
+ self.connection_handlers = { writing_role => ActiveRecord::Base.default_connection_handler }
220
+ end
200
221
  self.configurations = Rails.application.config.database_configuration
201
222
  establish_connection
202
223
  end
@@ -210,13 +231,6 @@ To keep using the current cache store, you can turn off cache versioning entirel
210
231
  end
211
232
  end
212
233
 
213
- initializer "active_record.collection_cache_association_loading" do
214
- require "active_record/railties/collection_cache_association_loading"
215
- ActiveSupport.on_load(:action_view) do
216
- ActionView::PartialRenderer.prepend(ActiveRecord::Railties::CollectionCacheAssociationLoading)
217
- end
218
- end
219
-
220
234
  initializer "active_record.set_reloader_hooks" do
221
235
  ActiveSupport.on_load(:active_record) do
222
236
  ActiveSupport::Reloader.before_class_unload do
@@ -260,21 +274,9 @@ To keep using the current cache store, you can turn off cache versioning entirel
260
274
  end
261
275
  end
262
276
 
263
- initializer "active_record.use_yaml_unsafe_load" do |app|
264
- config.after_initialize do
265
- unless app.config.active_record.use_yaml_unsafe_load.nil?
266
- ActiveRecord::Base.use_yaml_unsafe_load =
267
- app.config.active_record.use_yaml_unsafe_load
268
- end
269
- end
270
- end
271
-
272
- initializer "active_record.yaml_column_permitted_classes" do |app|
273
- config.after_initialize do
274
- unless app.config.active_record.yaml_column_permitted_classes.nil?
275
- ActiveRecord::Base.yaml_column_permitted_classes =
276
- app.config.active_record.yaml_column_permitted_classes
277
- end
277
+ initializer "active_record.set_signed_id_verifier_secret" do
278
+ ActiveSupport.on_load(:active_record) do
279
+ self.signed_id_verifier_secret ||= -> { Rails.application.key_generator.generate_key("active_record/signed_id") }
278
280
  end
279
281
  end
280
282
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- ActiveRecord::Base.connection.begin_transaction(joinable: false)
4
-
5
- at_exit do
6
- ActiveRecord::Base.connection.rollback_transaction
3
+ ActiveRecord::ConnectionAdapters::AbstractAdapter.set_callback(:checkout, :after) do
4
+ begin_transaction(joinable: false)
7
5
  end