activerecord 6.0.0 → 6.1.3

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 (270) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1045 -575
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -4
  5. data/lib/active_record.rb +7 -13
  6. data/lib/active_record/aggregations.rb +5 -6
  7. data/lib/active_record/association_relation.rb +30 -10
  8. data/lib/active_record/associations.rb +120 -13
  9. data/lib/active_record/associations/alias_tracker.rb +19 -16
  10. data/lib/active_record/associations/association.rb +49 -29
  11. data/lib/active_record/associations/association_scope.rb +19 -15
  12. data/lib/active_record/associations/belongs_to_association.rb +22 -8
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -3
  14. data/lib/active_record/associations/builder/association.rb +32 -5
  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 -3
  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 +25 -8
  22. data/lib/active_record/associations/collection_proxy.rb +14 -7
  23. data/lib/active_record/associations/foreign_association.rb +13 -0
  24. data/lib/active_record/associations/has_many_association.rb +24 -3
  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 +77 -42
  28. data/lib/active_record/associations/join_dependency/join_association.rb +39 -16
  29. data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
  30. data/lib/active_record/associations/preloader.rb +13 -8
  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 -9
  36. data/lib/active_record/attribute_methods.rb +64 -54
  37. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -10
  38. data/lib/active_record/attribute_methods/dirty.rb +3 -13
  39. data/lib/active_record/attribute_methods/primary_key.rb +6 -4
  40. data/lib/active_record/attribute_methods/query.rb +3 -6
  41. data/lib/active_record/attribute_methods/read.rb +8 -12
  42. data/lib/active_record/attribute_methods/serialization.rb +11 -6
  43. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
  44. data/lib/active_record/attribute_methods/write.rb +12 -21
  45. data/lib/active_record/attributes.rb +33 -9
  46. data/lib/active_record/autosave_association.rb +63 -44
  47. data/lib/active_record/base.rb +2 -14
  48. data/lib/active_record/callbacks.rb +153 -24
  49. data/lib/active_record/coders/yaml_column.rb +1 -2
  50. data/lib/active_record/connection_adapters.rb +50 -0
  51. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +202 -138
  52. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
  53. data/lib/active_record/connection_adapters/abstract/database_statements.rb +87 -38
  54. data/lib/active_record/connection_adapters/abstract/query_cache.rb +5 -10
  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 +152 -116
  58. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +141 -52
  59. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
  60. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +267 -105
  61. data/lib/active_record/connection_adapters/abstract/transaction.rb +82 -35
  62. data/lib/active_record/connection_adapters/abstract_adapter.rb +74 -77
  63. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +149 -115
  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/column.rb +1 -1
  68. data/lib/active_record/connection_adapters/mysql/database_statements.rb +30 -36
  69. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
  70. data/lib/active_record/connection_adapters/mysql/quoting.rb +18 -3
  71. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +32 -7
  72. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
  73. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +5 -2
  74. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +17 -13
  75. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
  76. data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -13
  77. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  78. data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
  79. data/lib/active_record/connection_adapters/postgresql/column.rb +24 -1
  80. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +21 -56
  81. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  82. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +0 -1
  83. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  84. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
  85. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
  86. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  87. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +0 -1
  88. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
  90. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  92. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +24 -6
  95. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  96. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -2
  97. data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
  98. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
  99. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +7 -3
  100. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +1 -1
  101. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
  102. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +72 -54
  103. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
  104. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  105. data/lib/active_record/connection_adapters/postgresql_adapter.rb +83 -65
  106. data/lib/active_record/connection_adapters/schema_cache.rb +98 -15
  107. data/lib/active_record/connection_adapters/sql_type_metadata.rb +10 -0
  108. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +38 -12
  109. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -2
  110. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  111. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +38 -5
  112. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -57
  113. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  114. data/lib/active_record/connection_handling.rb +219 -81
  115. data/lib/active_record/core.rb +253 -67
  116. data/lib/active_record/counter_cache.rb +4 -1
  117. data/lib/active_record/database_configurations.rb +124 -85
  118. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  119. data/lib/active_record/database_configurations/database_config.rb +52 -9
  120. data/lib/active_record/database_configurations/hash_config.rb +54 -8
  121. data/lib/active_record/database_configurations/url_config.rb +15 -41
  122. data/lib/active_record/delegated_type.rb +209 -0
  123. data/lib/active_record/destroy_association_async_job.rb +36 -0
  124. data/lib/active_record/dynamic_matchers.rb +2 -3
  125. data/lib/active_record/enum.rb +82 -38
  126. data/lib/active_record/errors.rb +47 -12
  127. data/lib/active_record/explain.rb +9 -5
  128. data/lib/active_record/explain_subscriber.rb +1 -1
  129. data/lib/active_record/fixture_set/file.rb +10 -17
  130. data/lib/active_record/fixture_set/model_metadata.rb +1 -2
  131. data/lib/active_record/fixture_set/render_context.rb +1 -1
  132. data/lib/active_record/fixture_set/table_row.rb +2 -3
  133. data/lib/active_record/fixture_set/table_rows.rb +0 -1
  134. data/lib/active_record/fixtures.rb +58 -12
  135. data/lib/active_record/gem_version.rb +2 -2
  136. data/lib/active_record/inheritance.rb +40 -21
  137. data/lib/active_record/insert_all.rb +39 -10
  138. data/lib/active_record/integration.rb +3 -5
  139. data/lib/active_record/internal_metadata.rb +16 -7
  140. data/lib/active_record/legacy_yaml_adapter.rb +7 -3
  141. data/lib/active_record/locking/optimistic.rb +33 -18
  142. data/lib/active_record/locking/pessimistic.rb +6 -2
  143. data/lib/active_record/log_subscriber.rb +28 -9
  144. data/lib/active_record/middleware/database_selector.rb +4 -2
  145. data/lib/active_record/middleware/database_selector/resolver.rb +14 -14
  146. data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
  147. data/lib/active_record/migration.rb +115 -85
  148. data/lib/active_record/migration/command_recorder.rb +53 -45
  149. data/lib/active_record/migration/compatibility.rb +71 -20
  150. data/lib/active_record/migration/join_table.rb +0 -1
  151. data/lib/active_record/model_schema.rb +120 -15
  152. data/lib/active_record/nested_attributes.rb +2 -5
  153. data/lib/active_record/no_touching.rb +1 -1
  154. data/lib/active_record/null_relation.rb +0 -1
  155. data/lib/active_record/persistence.rb +50 -46
  156. data/lib/active_record/query_cache.rb +15 -5
  157. data/lib/active_record/querying.rb +12 -7
  158. data/lib/active_record/railtie.rb +65 -45
  159. data/lib/active_record/railties/console_sandbox.rb +2 -4
  160. data/lib/active_record/railties/databases.rake +277 -97
  161. data/lib/active_record/readonly_attributes.rb +4 -0
  162. data/lib/active_record/reflection.rb +77 -63
  163. data/lib/active_record/relation.rb +107 -67
  164. data/lib/active_record/relation/batches.rb +38 -32
  165. data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
  166. data/lib/active_record/relation/calculations.rb +102 -45
  167. data/lib/active_record/relation/delegation.rb +9 -7
  168. data/lib/active_record/relation/finder_methods.rb +55 -17
  169. data/lib/active_record/relation/from_clause.rb +5 -1
  170. data/lib/active_record/relation/merger.rb +27 -26
  171. data/lib/active_record/relation/predicate_builder.rb +59 -40
  172. data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
  173. data/lib/active_record/relation/predicate_builder/association_query_value.rb +4 -5
  174. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -6
  175. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  176. data/lib/active_record/relation/query_methods.rb +343 -180
  177. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  178. data/lib/active_record/relation/spawn_methods.rb +8 -8
  179. data/lib/active_record/relation/where_clause.rb +107 -61
  180. data/lib/active_record/result.rb +41 -34
  181. data/lib/active_record/runtime_registry.rb +2 -2
  182. data/lib/active_record/sanitization.rb +6 -17
  183. data/lib/active_record/schema_dumper.rb +34 -4
  184. data/lib/active_record/schema_migration.rb +2 -8
  185. data/lib/active_record/scoping.rb +0 -1
  186. data/lib/active_record/scoping/default.rb +0 -1
  187. data/lib/active_record/scoping/named.rb +7 -18
  188. data/lib/active_record/secure_token.rb +16 -8
  189. data/lib/active_record/serialization.rb +5 -3
  190. data/lib/active_record/signed_id.rb +116 -0
  191. data/lib/active_record/statement_cache.rb +20 -4
  192. data/lib/active_record/store.rb +3 -3
  193. data/lib/active_record/suppressor.rb +2 -2
  194. data/lib/active_record/table_metadata.rb +42 -36
  195. data/lib/active_record/tasks/database_tasks.rb +140 -113
  196. data/lib/active_record/tasks/mysql_database_tasks.rb +34 -36
  197. data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -27
  198. data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -10
  199. data/lib/active_record/test_databases.rb +5 -4
  200. data/lib/active_record/test_fixtures.rb +38 -16
  201. data/lib/active_record/timestamp.rb +4 -7
  202. data/lib/active_record/touch_later.rb +20 -21
  203. data/lib/active_record/transactions.rb +26 -73
  204. data/lib/active_record/type.rb +8 -2
  205. data/lib/active_record/type/adapter_specific_registry.rb +2 -5
  206. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  207. data/lib/active_record/type/serialized.rb +6 -3
  208. data/lib/active_record/type/time.rb +10 -0
  209. data/lib/active_record/type/type_map.rb +0 -1
  210. data/lib/active_record/type/unsigned_integer.rb +0 -1
  211. data/lib/active_record/type_caster/connection.rb +0 -1
  212. data/lib/active_record/type_caster/map.rb +8 -5
  213. data/lib/active_record/validations.rb +3 -3
  214. data/lib/active_record/validations/associated.rb +1 -2
  215. data/lib/active_record/validations/numericality.rb +35 -0
  216. data/lib/active_record/validations/uniqueness.rb +24 -4
  217. data/lib/arel.rb +15 -12
  218. data/lib/arel/attributes/attribute.rb +4 -0
  219. data/lib/arel/collectors/bind.rb +5 -0
  220. data/lib/arel/collectors/composite.rb +8 -0
  221. data/lib/arel/collectors/sql_string.rb +7 -0
  222. data/lib/arel/collectors/substitute_binds.rb +7 -0
  223. data/lib/arel/nodes.rb +3 -1
  224. data/lib/arel/nodes/binary.rb +82 -8
  225. data/lib/arel/nodes/bind_param.rb +8 -0
  226. data/lib/arel/nodes/casted.rb +21 -9
  227. data/lib/arel/nodes/equality.rb +6 -9
  228. data/lib/arel/nodes/grouping.rb +3 -0
  229. data/lib/arel/nodes/homogeneous_in.rb +72 -0
  230. data/lib/arel/nodes/in.rb +8 -1
  231. data/lib/arel/nodes/infix_operation.rb +13 -1
  232. data/lib/arel/nodes/join_source.rb +1 -1
  233. data/lib/arel/nodes/node.rb +7 -6
  234. data/lib/arel/nodes/ordering.rb +27 -0
  235. data/lib/arel/nodes/sql_literal.rb +3 -0
  236. data/lib/arel/nodes/table_alias.rb +7 -3
  237. data/lib/arel/nodes/unary.rb +0 -1
  238. data/lib/arel/predications.rb +17 -24
  239. data/lib/arel/select_manager.rb +1 -2
  240. data/lib/arel/table.rb +13 -5
  241. data/lib/arel/visitors.rb +0 -7
  242. data/lib/arel/visitors/dot.rb +14 -3
  243. data/lib/arel/visitors/mysql.rb +11 -1
  244. data/lib/arel/visitors/postgresql.rb +15 -5
  245. data/lib/arel/visitors/sqlite.rb +0 -1
  246. data/lib/arel/visitors/to_sql.rb +89 -79
  247. data/lib/arel/visitors/visitor.rb +0 -1
  248. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  249. data/lib/rails/generators/active_record/migration.rb +6 -2
  250. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
  251. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
  252. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
  253. data/lib/rails/generators/active_record/model/model_generator.rb +38 -2
  254. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  255. metadata +30 -27
  256. data/lib/active_record/attribute_decorators.rb +0 -90
  257. data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
  258. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
  259. data/lib/active_record/define_callbacks.rb +0 -22
  260. data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
  261. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
  262. data/lib/active_record/relation/where_clause_factory.rb +0 -33
  263. data/lib/arel/attributes.rb +0 -22
  264. data/lib/arel/visitors/depth_first.rb +0 -204
  265. data/lib/arel/visitors/ibm_db.rb +0 -34
  266. data/lib/arel/visitors/informix.rb +0 -62
  267. data/lib/arel/visitors/mssql.rb +0 -157
  268. data/lib/arel/visitors/oracle.rb +0 -159
  269. data/lib/arel/visitors/oracle12.rb +0 -66
  270. data/lib/arel/visitors/where_sql.rb +0 -23
@@ -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
@@ -354,7 +353,6 @@ module ActiveRecord
354
353
  end
355
354
 
356
355
  private
357
-
358
356
  # Generates a writer method for this association. Serves as a point for
359
357
  # accessing the objects in the association. For example, this method
360
358
  # could generate the following:
@@ -386,7 +384,6 @@ module ActiveRecord
386
384
  end
387
385
 
388
386
  private
389
-
390
387
  # Attribute hash keys that should not be assigned as normal attributes.
391
388
  # These hash keys are nested attributes implementation details.
392
389
  UNASSIGNABLE_KEYS = %w( id _destroy )
@@ -512,7 +509,7 @@ module ActiveRecord
512
509
  if target_record
513
510
  existing_record = target_record
514
511
  else
515
- association.add_to_target(existing_record, :skip_callbacks)
512
+ association.add_to_target(existing_record, skip_callbacks: true)
516
513
  end
517
514
 
518
515
  assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy])
@@ -58,7 +58,7 @@ module ActiveRecord
58
58
  super unless no_touching?
59
59
  end
60
60
 
61
- def touch(*) # :nodoc:
61
+ def touch(*, **) # :nodoc:
62
62
  super unless no_touching?
63
63
  end
64
64
  end
@@ -60,7 +60,6 @@ module ActiveRecord
60
60
  end
61
61
 
62
62
  private
63
-
64
63
  def exec_queries
65
64
  @records = [].freeze
66
65
  end
@@ -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, &block)
470
- create_or_update(*args, &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, &block)
503
- create_or_update(*args, &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)
@@ -870,7 +865,6 @@ module ActiveRecord
870
865
  end
871
866
 
872
867
  private
873
-
874
868
  # A hook to be overridden by association modules.
875
869
  def destroy_associations
876
870
  end
@@ -920,6 +914,8 @@ module ActiveRecord
920
914
  @_trigger_update_callback = affected_rows == 1
921
915
  end
922
916
 
917
+ @previously_new_record = false
918
+
923
919
  yield(self) if block_given?
924
920
 
925
921
  affected_rows
@@ -937,6 +933,7 @@ module ActiveRecord
937
933
  self.id ||= new_id if @primary_key
938
934
 
939
935
  @new_record = false
936
+ @previously_new_record = true
940
937
 
941
938
  yield(self) if block_given?
942
939
 
@@ -944,7 +941,7 @@ module ActiveRecord
944
941
  end
945
942
 
946
943
  def verify_readonly_attribute(name)
947
- 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)
948
945
  end
949
946
 
950
947
  def _raise_record_not_destroyed
@@ -954,14 +951,21 @@ module ActiveRecord
954
951
  @_association_destroy_exception = nil
955
952
  end
956
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
+
957
965
  # The name of the method used to touch a +belongs_to+ association when the
958
966
  # +:touch+ option is used.
959
967
  def belongs_to_touch_method
960
968
  :touch
961
969
  end
962
-
963
- def _raise_readonly_record_error
964
- raise ReadOnlyRecord, "#{self.class} is marked as readonly"
965
- end
966
970
  end
967
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
 
@@ -36,7 +37,7 @@ module ActiveRecord
36
37
  #
37
38
  # # A simple SQL query spanning multiple tables
38
39
  # Post.find_by_sql "SELECT p.title, c.author FROM posts p, comments c WHERE p.id = c.post_id"
39
- # # => [#<Post:0x36bff9c @attributes={"title"=>"Ruby Meetup", "first_name"=>"Quentin"}>, ...]
40
+ # # => [#<Post:0x36bff9c @attributes={"title"=>"Ruby Meetup", "author"=>"Quentin"}>, ...]
40
41
  #
41
42
  # You can use the same string replacement techniques as you can with <tt>ActiveRecord::QueryMethods#where</tt>:
42
43
  #
@@ -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
 
@@ -114,7 +116,7 @@ To keep using the current cache store, you can turn off cache versioning entirel
114
116
 
115
117
  config.active_record.cache_versioning = false
116
118
 
117
- end_error
119
+ end_error
118
120
  end
119
121
  end
120
122
  end
@@ -122,23 +124,37 @@ end_error
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 @@ end_error
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 @@ end_error
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 @@ end_error
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 @@ end_error
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 @@ end_error
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