activerecord 6.0.3 → 6.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (244) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +779 -705
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +2 -2
  5. data/lib/active_record.rb +7 -14
  6. data/lib/active_record/aggregations.rb +1 -1
  7. data/lib/active_record/association_relation.rb +22 -14
  8. data/lib/active_record/associations.rb +114 -11
  9. data/lib/active_record/associations/alias_tracker.rb +19 -15
  10. data/lib/active_record/associations/association.rb +40 -29
  11. data/lib/active_record/associations/association_scope.rb +17 -15
  12. data/lib/active_record/associations/belongs_to_association.rb +15 -5
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -1
  14. data/lib/active_record/associations/builder/association.rb +9 -3
  15. data/lib/active_record/associations/builder/belongs_to.rb +10 -7
  16. data/lib/active_record/associations/builder/collection_association.rb +5 -4
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +0 -1
  18. data/lib/active_record/associations/builder/has_many.rb +6 -2
  19. data/lib/active_record/associations/builder/has_one.rb +11 -14
  20. data/lib/active_record/associations/builder/singular_association.rb +1 -1
  21. data/lib/active_record/associations/collection_association.rb +19 -6
  22. data/lib/active_record/associations/collection_proxy.rb +13 -5
  23. data/lib/active_record/associations/foreign_association.rb +13 -0
  24. data/lib/active_record/associations/has_many_association.rb +24 -2
  25. data/lib/active_record/associations/has_many_through_association.rb +10 -4
  26. data/lib/active_record/associations/has_one_association.rb +15 -1
  27. data/lib/active_record/associations/join_dependency.rb +72 -50
  28. data/lib/active_record/associations/join_dependency/join_association.rb +36 -14
  29. data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
  30. data/lib/active_record/associations/preloader.rb +11 -5
  31. data/lib/active_record/associations/preloader/association.rb +51 -25
  32. data/lib/active_record/associations/preloader/through_association.rb +2 -2
  33. data/lib/active_record/associations/singular_association.rb +1 -1
  34. data/lib/active_record/associations/through_association.rb +1 -1
  35. data/lib/active_record/attribute_assignment.rb +10 -8
  36. data/lib/active_record/attribute_methods.rb +52 -48
  37. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -9
  38. data/lib/active_record/attribute_methods/dirty.rb +1 -11
  39. data/lib/active_record/attribute_methods/primary_key.rb +6 -2
  40. data/lib/active_record/attribute_methods/query.rb +3 -6
  41. data/lib/active_record/attribute_methods/read.rb +8 -11
  42. data/lib/active_record/attribute_methods/serialization.rb +4 -4
  43. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -13
  44. data/lib/active_record/attribute_methods/write.rb +12 -20
  45. data/lib/active_record/attributes.rb +27 -7
  46. data/lib/active_record/autosave_association.rb +57 -40
  47. data/lib/active_record/base.rb +2 -14
  48. data/lib/active_record/callbacks.rb +32 -22
  49. data/lib/active_record/coders/yaml_column.rb +1 -1
  50. data/lib/active_record/connection_adapters.rb +50 -0
  51. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +186 -134
  52. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
  53. data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -22
  54. data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -7
  55. data/lib/active_record/connection_adapters/abstract/quoting.rb +34 -34
  56. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  57. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -116
  58. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +112 -27
  59. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
  60. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +224 -85
  61. data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -24
  62. data/lib/active_record/connection_adapters/abstract_adapter.rb +36 -69
  63. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +129 -88
  64. data/lib/active_record/connection_adapters/column.rb +15 -1
  65. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  66. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
  67. data/lib/active_record/connection_adapters/mysql/database_statements.rb +23 -25
  68. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -1
  69. data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
  70. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +33 -6
  71. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
  72. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
  73. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +11 -7
  74. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
  75. data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -12
  76. data/lib/active_record/connection_adapters/pool_config.rb +63 -0
  77. data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
  78. data/lib/active_record/connection_adapters/postgresql/column.rb +24 -1
  79. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +13 -54
  80. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  81. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  82. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
  83. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -2
  84. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -2
  86. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +24 -5
  89. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -1
  90. data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
  91. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
  92. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +5 -1
  93. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +61 -29
  94. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
  95. data/lib/active_record/connection_adapters/postgresql_adapter.rb +72 -55
  96. data/lib/active_record/connection_adapters/schema_cache.rb +98 -15
  97. data/lib/active_record/connection_adapters/sql_type_metadata.rb +10 -0
  98. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +31 -6
  99. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -1
  100. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  101. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +37 -4
  102. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +49 -50
  103. data/lib/active_record/connection_handling.rb +210 -71
  104. data/lib/active_record/core.rb +220 -55
  105. data/lib/active_record/database_configurations.rb +124 -85
  106. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  107. data/lib/active_record/database_configurations/database_config.rb +52 -9
  108. data/lib/active_record/database_configurations/hash_config.rb +54 -8
  109. data/lib/active_record/database_configurations/url_config.rb +15 -40
  110. data/lib/active_record/delegated_type.rb +209 -0
  111. data/lib/active_record/destroy_association_async_job.rb +36 -0
  112. data/lib/active_record/enum.rb +27 -10
  113. data/lib/active_record/errors.rb +47 -12
  114. data/lib/active_record/explain.rb +9 -4
  115. data/lib/active_record/explain_subscriber.rb +1 -1
  116. data/lib/active_record/fixture_set/file.rb +10 -17
  117. data/lib/active_record/fixture_set/model_metadata.rb +1 -2
  118. data/lib/active_record/fixture_set/render_context.rb +1 -1
  119. data/lib/active_record/fixture_set/table_row.rb +2 -2
  120. data/lib/active_record/fixtures.rb +54 -8
  121. data/lib/active_record/gem_version.rb +3 -3
  122. data/lib/active_record/inheritance.rb +40 -18
  123. data/lib/active_record/insert_all.rb +33 -6
  124. data/lib/active_record/integration.rb +3 -5
  125. data/lib/active_record/internal_metadata.rb +15 -4
  126. data/lib/active_record/legacy_yaml_adapter.rb +7 -3
  127. data/lib/active_record/locking/optimistic.rb +22 -16
  128. data/lib/active_record/locking/pessimistic.rb +6 -2
  129. data/lib/active_record/log_subscriber.rb +26 -8
  130. data/lib/active_record/middleware/database_selector.rb +4 -1
  131. data/lib/active_record/middleware/database_selector/resolver.rb +5 -0
  132. data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
  133. data/lib/active_record/migration.rb +113 -83
  134. data/lib/active_record/migration/command_recorder.rb +47 -27
  135. data/lib/active_record/migration/compatibility.rb +67 -17
  136. data/lib/active_record/model_schema.rb +88 -13
  137. data/lib/active_record/nested_attributes.rb +2 -3
  138. data/lib/active_record/no_touching.rb +1 -1
  139. data/lib/active_record/persistence.rb +50 -45
  140. data/lib/active_record/query_cache.rb +15 -5
  141. data/lib/active_record/querying.rb +11 -6
  142. data/lib/active_record/railtie.rb +64 -44
  143. data/lib/active_record/railties/databases.rake +253 -98
  144. data/lib/active_record/readonly_attributes.rb +4 -0
  145. data/lib/active_record/reflection.rb +70 -57
  146. data/lib/active_record/relation.rb +96 -67
  147. data/lib/active_record/relation/batches.rb +38 -31
  148. data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
  149. data/lib/active_record/relation/calculations.rb +101 -44
  150. data/lib/active_record/relation/delegation.rb +2 -1
  151. data/lib/active_record/relation/finder_methods.rb +45 -15
  152. data/lib/active_record/relation/from_clause.rb +1 -1
  153. data/lib/active_record/relation/merger.rb +27 -25
  154. data/lib/active_record/relation/predicate_builder.rb +57 -33
  155. data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
  156. data/lib/active_record/relation/predicate_builder/association_query_value.rb +2 -2
  157. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +3 -3
  158. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  159. data/lib/active_record/relation/query_methods.rb +330 -195
  160. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  161. data/lib/active_record/relation/spawn_methods.rb +6 -5
  162. data/lib/active_record/relation/where_clause.rb +104 -57
  163. data/lib/active_record/result.rb +41 -33
  164. data/lib/active_record/runtime_registry.rb +2 -2
  165. data/lib/active_record/sanitization.rb +6 -17
  166. data/lib/active_record/schema_dumper.rb +34 -4
  167. data/lib/active_record/schema_migration.rb +0 -4
  168. data/lib/active_record/scoping/named.rb +6 -17
  169. data/lib/active_record/secure_token.rb +16 -8
  170. data/lib/active_record/serialization.rb +5 -3
  171. data/lib/active_record/signed_id.rb +116 -0
  172. data/lib/active_record/statement_cache.rb +20 -4
  173. data/lib/active_record/store.rb +2 -2
  174. data/lib/active_record/suppressor.rb +2 -2
  175. data/lib/active_record/table_metadata.rb +36 -52
  176. data/lib/active_record/tasks/database_tasks.rb +139 -113
  177. data/lib/active_record/tasks/mysql_database_tasks.rb +34 -35
  178. data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -26
  179. data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -9
  180. data/lib/active_record/test_databases.rb +5 -4
  181. data/lib/active_record/test_fixtures.rb +37 -16
  182. data/lib/active_record/timestamp.rb +4 -6
  183. data/lib/active_record/touch_later.rb +21 -21
  184. data/lib/active_record/transactions.rb +15 -64
  185. data/lib/active_record/type.rb +8 -1
  186. data/lib/active_record/type/serialized.rb +6 -2
  187. data/lib/active_record/type/time.rb +10 -0
  188. data/lib/active_record/type_caster/connection.rb +0 -1
  189. data/lib/active_record/type_caster/map.rb +8 -5
  190. data/lib/active_record/validations.rb +1 -0
  191. data/lib/active_record/validations/numericality.rb +35 -0
  192. data/lib/active_record/validations/uniqueness.rb +24 -4
  193. data/lib/arel.rb +5 -13
  194. data/lib/arel/attributes/attribute.rb +4 -0
  195. data/lib/arel/collectors/bind.rb +5 -0
  196. data/lib/arel/collectors/composite.rb +8 -0
  197. data/lib/arel/collectors/sql_string.rb +7 -0
  198. data/lib/arel/collectors/substitute_binds.rb +7 -0
  199. data/lib/arel/nodes.rb +3 -1
  200. data/lib/arel/nodes/binary.rb +82 -8
  201. data/lib/arel/nodes/bind_param.rb +8 -0
  202. data/lib/arel/nodes/casted.rb +21 -9
  203. data/lib/arel/nodes/equality.rb +6 -9
  204. data/lib/arel/nodes/grouping.rb +3 -0
  205. data/lib/arel/nodes/homogeneous_in.rb +72 -0
  206. data/lib/arel/nodes/in.rb +8 -1
  207. data/lib/arel/nodes/infix_operation.rb +13 -1
  208. data/lib/arel/nodes/join_source.rb +1 -1
  209. data/lib/arel/nodes/node.rb +7 -6
  210. data/lib/arel/nodes/ordering.rb +27 -0
  211. data/lib/arel/nodes/sql_literal.rb +3 -0
  212. data/lib/arel/nodes/table_alias.rb +7 -3
  213. data/lib/arel/nodes/unary.rb +0 -1
  214. data/lib/arel/predications.rb +12 -18
  215. data/lib/arel/select_manager.rb +1 -2
  216. data/lib/arel/table.rb +13 -5
  217. data/lib/arel/visitors.rb +0 -7
  218. data/lib/arel/visitors/dot.rb +14 -2
  219. data/lib/arel/visitors/mysql.rb +11 -1
  220. data/lib/arel/visitors/postgresql.rb +15 -4
  221. data/lib/arel/visitors/to_sql.rb +89 -78
  222. data/lib/rails/generators/active_record/migration.rb +6 -1
  223. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
  224. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
  225. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +3 -3
  226. data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
  227. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  228. metadata +27 -28
  229. data/lib/active_record/advisory_lock_base.rb +0 -18
  230. data/lib/active_record/attribute_decorators.rb +0 -88
  231. data/lib/active_record/connection_adapters/connection_specification.rb +0 -296
  232. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
  233. data/lib/active_record/define_callbacks.rb +0 -22
  234. data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
  235. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
  236. data/lib/active_record/relation/where_clause_factory.rb +0 -33
  237. data/lib/arel/attributes.rb +0 -22
  238. data/lib/arel/visitors/depth_first.rb +0 -203
  239. data/lib/arel/visitors/ibm_db.rb +0 -34
  240. data/lib/arel/visitors/informix.rb +0 -62
  241. data/lib/arel/visitors/mssql.rb +0 -156
  242. data/lib/arel/visitors/oracle.rb +0 -158
  243. data/lib/arel/visitors/oracle12.rb +0 -65
  244. 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(destroy: :active_record_destroy)
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 wether 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
@@ -259,5 +273,11 @@ To keep using the current cache store, you can turn off cache versioning entirel
259
273
  self.filter_attributes += Rails.application.config.filter_parameters
260
274
  end
261
275
  end
276
+
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") }
280
+ end
281
+ end
262
282
  end
263
283
  end