activerecord 7.1.5.2 → 8.1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +567 -2443
  3. data/README.rdoc +16 -16
  4. data/examples/performance.rb +2 -2
  5. data/lib/active_record/association_relation.rb +3 -2
  6. data/lib/active_record/associations/alias_tracker.rb +31 -23
  7. data/lib/active_record/associations/association.rb +43 -12
  8. data/lib/active_record/associations/belongs_to_association.rb +31 -8
  9. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
  10. data/lib/active_record/associations/builder/association.rb +23 -11
  11. data/lib/active_record/associations/builder/belongs_to.rb +18 -4
  12. data/lib/active_record/associations/builder/collection_association.rb +7 -3
  13. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +2 -2
  14. data/lib/active_record/associations/builder/has_many.rb +3 -4
  15. data/lib/active_record/associations/builder/has_one.rb +3 -4
  16. data/lib/active_record/associations/builder/singular_association.rb +33 -5
  17. data/lib/active_record/associations/collection_association.rb +17 -9
  18. data/lib/active_record/associations/collection_proxy.rb +36 -5
  19. data/lib/active_record/associations/deprecation.rb +88 -0
  20. data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
  21. data/lib/active_record/associations/errors.rb +268 -0
  22. data/lib/active_record/associations/has_many_association.rb +1 -1
  23. data/lib/active_record/associations/has_many_through_association.rb +10 -3
  24. data/lib/active_record/associations/join_dependency/join_association.rb +1 -1
  25. data/lib/active_record/associations/join_dependency.rb +4 -2
  26. data/lib/active_record/associations/nested_error.rb +47 -0
  27. data/lib/active_record/associations/preloader/association.rb +4 -3
  28. data/lib/active_record/associations/preloader/batch.rb +7 -1
  29. data/lib/active_record/associations/preloader/branch.rb +8 -1
  30. data/lib/active_record/associations/preloader/through_association.rb +1 -3
  31. data/lib/active_record/associations/singular_association.rb +14 -3
  32. data/lib/active_record/associations/through_association.rb +1 -1
  33. data/lib/active_record/associations.rb +250 -315
  34. data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
  35. data/lib/active_record/attribute_assignment.rb +0 -2
  36. data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
  37. data/lib/active_record/attribute_methods/primary_key.rb +25 -61
  38. data/lib/active_record/attribute_methods/query.rb +34 -0
  39. data/lib/active_record/attribute_methods/read.rb +1 -13
  40. data/lib/active_record/attribute_methods/serialization.rb +20 -27
  41. data/lib/active_record/attribute_methods/time_zone_conversion.rb +19 -20
  42. data/lib/active_record/attribute_methods.rb +71 -75
  43. data/lib/active_record/attributes.rb +96 -68
  44. data/lib/active_record/autosave_association.rb +93 -58
  45. data/lib/active_record/base.rb +5 -7
  46. data/lib/active_record/callbacks.rb +1 -1
  47. data/lib/active_record/coders/json.rb +14 -5
  48. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +50 -126
  49. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +16 -4
  50. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +52 -13
  51. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +681 -135
  52. data/lib/active_record/connection_adapters/abstract/database_statements.rb +165 -86
  53. data/lib/active_record/connection_adapters/abstract/query_cache.rb +226 -78
  54. data/lib/active_record/connection_adapters/abstract/quoting.rb +79 -114
  55. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +11 -7
  56. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +37 -36
  57. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -1
  58. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +136 -34
  59. data/lib/active_record/connection_adapters/abstract/transaction.rb +163 -68
  60. data/lib/active_record/connection_adapters/abstract_adapter.rb +197 -129
  61. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +112 -63
  62. data/lib/active_record/connection_adapters/column.rb +17 -4
  63. data/lib/active_record/connection_adapters/mysql/database_statements.rb +11 -3
  64. data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -57
  65. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +2 -0
  66. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +41 -10
  67. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +79 -46
  68. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +97 -101
  69. data/lib/active_record/connection_adapters/mysql2_adapter.rb +14 -33
  70. data/lib/active_record/connection_adapters/pool_config.rb +14 -13
  71. data/lib/active_record/connection_adapters/postgresql/column.rb +4 -0
  72. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +98 -44
  73. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +3 -3
  74. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
  75. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
  76. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +1 -1
  77. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
  78. data/lib/active_record/connection_adapters/postgresql/quoting.rb +79 -68
  79. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -4
  80. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +9 -17
  81. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +44 -41
  82. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +69 -32
  83. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +155 -75
  84. data/lib/active_record/connection_adapters/postgresql_adapter.rb +104 -121
  85. data/lib/active_record/connection_adapters/schema_cache.rb +126 -133
  86. data/lib/active_record/connection_adapters/sqlite3/column.rb +14 -1
  87. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +91 -95
  88. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +57 -54
  89. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +16 -0
  90. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +13 -0
  91. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +43 -2
  92. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +38 -15
  93. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +231 -111
  94. data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
  95. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +40 -69
  96. data/lib/active_record/connection_adapters/trilogy_adapter.rb +19 -65
  97. data/lib/active_record/connection_adapters.rb +66 -0
  98. data/lib/active_record/connection_handling.rb +88 -46
  99. data/lib/active_record/core.rb +142 -58
  100. data/lib/active_record/counter_cache.rb +52 -18
  101. data/lib/active_record/database_configurations/connection_url_resolver.rb +9 -2
  102. data/lib/active_record/database_configurations/database_config.rb +28 -5
  103. data/lib/active_record/database_configurations/hash_config.rb +103 -41
  104. data/lib/active_record/database_configurations/url_config.rb +30 -1
  105. data/lib/active_record/database_configurations.rb +8 -4
  106. data/lib/active_record/delegated_type.rb +43 -19
  107. data/lib/active_record/dynamic_matchers.rb +56 -71
  108. data/lib/active_record/encryption/config.rb +3 -1
  109. data/lib/active_record/encryption/encryptable_record.rb +12 -12
  110. data/lib/active_record/encryption/encrypted_attribute_type.rb +35 -6
  111. data/lib/active_record/encryption/encryptor.rb +58 -22
  112. data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
  113. data/lib/active_record/encryption/key_provider.rb +1 -1
  114. data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
  115. data/lib/active_record/encryption/message_serializer.rb +4 -0
  116. data/lib/active_record/encryption/null_encryptor.rb +4 -0
  117. data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
  118. data/lib/active_record/encryption/scheme.rb +9 -2
  119. data/lib/active_record/enum.rb +57 -36
  120. data/lib/active_record/errors.rb +76 -26
  121. data/lib/active_record/explain.rb +14 -25
  122. data/lib/active_record/explain_registry.rb +51 -2
  123. data/lib/active_record/filter_attribute_handler.rb +73 -0
  124. data/lib/active_record/fixture_set/table_row.rb +19 -2
  125. data/lib/active_record/fixtures.rb +39 -35
  126. data/lib/active_record/future_result.rb +21 -13
  127. data/lib/active_record/gem_version.rb +3 -3
  128. data/lib/active_record/inheritance.rb +5 -3
  129. data/lib/active_record/insert_all.rb +28 -20
  130. data/lib/active_record/integration.rb +4 -1
  131. data/lib/active_record/internal_metadata.rb +48 -34
  132. data/lib/active_record/locking/optimistic.rb +15 -7
  133. data/lib/active_record/locking/pessimistic.rb +5 -0
  134. data/lib/active_record/log_subscriber.rb +3 -34
  135. data/lib/active_record/message_pack.rb +1 -1
  136. data/lib/active_record/middleware/shard_selector.rb +34 -17
  137. data/lib/active_record/migration/command_recorder.rb +46 -14
  138. data/lib/active_record/migration/compatibility.rb +40 -25
  139. data/lib/active_record/migration/default_schema_versions_formatter.rb +30 -0
  140. data/lib/active_record/migration/default_strategy.rb +4 -5
  141. data/lib/active_record/migration/pending_migration_connection.rb +2 -2
  142. data/lib/active_record/migration.rb +119 -103
  143. data/lib/active_record/model_schema.rb +66 -78
  144. data/lib/active_record/nested_attributes.rb +17 -9
  145. data/lib/active_record/persistence.rb +161 -454
  146. data/lib/active_record/query_cache.rb +33 -15
  147. data/lib/active_record/query_logs.rb +106 -39
  148. data/lib/active_record/query_logs_formatter.rb +17 -28
  149. data/lib/active_record/querying.rb +28 -16
  150. data/lib/active_record/railtie.rb +61 -74
  151. data/lib/active_record/railties/controller_runtime.rb +19 -5
  152. data/lib/active_record/railties/databases.rake +64 -78
  153. data/lib/active_record/railties/job_checkpoints.rb +15 -0
  154. data/lib/active_record/railties/job_runtime.rb +10 -11
  155. data/lib/active_record/reflection.rb +147 -53
  156. data/lib/active_record/relation/batches/batch_enumerator.rb +19 -5
  157. data/lib/active_record/relation/batches.rb +153 -73
  158. data/lib/active_record/relation/calculations.rb +146 -96
  159. data/lib/active_record/relation/delegation.rb +30 -23
  160. data/lib/active_record/relation/finder_methods.rb +64 -34
  161. data/lib/active_record/relation/merger.rb +12 -14
  162. data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
  163. data/lib/active_record/relation/predicate_builder/association_query_value.rb +19 -11
  164. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +8 -8
  165. data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
  166. data/lib/active_record/relation/predicate_builder.rb +25 -10
  167. data/lib/active_record/relation/query_attribute.rb +4 -2
  168. data/lib/active_record/relation/query_methods.rb +351 -124
  169. data/lib/active_record/relation/spawn_methods.rb +9 -25
  170. data/lib/active_record/relation/where_clause.rb +17 -30
  171. data/lib/active_record/relation.rb +590 -124
  172. data/lib/active_record/result.rb +131 -59
  173. data/lib/active_record/runtime_registry.rb +44 -21
  174. data/lib/active_record/sanitization.rb +33 -25
  175. data/lib/active_record/schema.rb +8 -6
  176. data/lib/active_record/schema_dumper.rb +66 -31
  177. data/lib/active_record/schema_migration.rb +31 -14
  178. data/lib/active_record/scoping/named.rb +6 -2
  179. data/lib/active_record/scoping.rb +0 -1
  180. data/lib/active_record/secure_token.rb +3 -3
  181. data/lib/active_record/signed_id.rb +68 -20
  182. data/lib/active_record/statement_cache.rb +29 -25
  183. data/lib/active_record/store.rb +51 -22
  184. data/lib/active_record/structured_event_subscriber.rb +85 -0
  185. data/lib/active_record/table_metadata.rb +7 -33
  186. data/lib/active_record/tasks/abstract_tasks.rb +76 -0
  187. data/lib/active_record/tasks/database_tasks.rb +118 -90
  188. data/lib/active_record/tasks/mysql_database_tasks.rb +3 -42
  189. data/lib/active_record/tasks/postgresql_database_tasks.rb +14 -40
  190. data/lib/active_record/tasks/sqlite_database_tasks.rb +17 -28
  191. data/lib/active_record/test_databases.rb +14 -4
  192. data/lib/active_record/test_fixtures.rb +123 -89
  193. data/lib/active_record/testing/query_assertions.rb +127 -0
  194. data/lib/active_record/timestamp.rb +6 -4
  195. data/lib/active_record/token_for.rb +22 -12
  196. data/lib/active_record/touch_later.rb +1 -1
  197. data/lib/active_record/transaction.rb +129 -0
  198. data/lib/active_record/transactions.rb +97 -18
  199. data/lib/active_record/translation.rb +0 -2
  200. data/lib/active_record/type/hash_lookup_type_map.rb +2 -1
  201. data/lib/active_record/type/internal/timezone.rb +7 -0
  202. data/lib/active_record/type/json.rb +15 -2
  203. data/lib/active_record/type/serialized.rb +12 -7
  204. data/lib/active_record/type/type_map.rb +1 -1
  205. data/lib/active_record/type_caster/connection.rb +5 -4
  206. data/lib/active_record/validations/associated.rb +10 -4
  207. data/lib/active_record/validations/uniqueness.rb +23 -18
  208. data/lib/active_record/validations.rb +4 -1
  209. data/lib/active_record.rb +203 -59
  210. data/lib/arel/alias_predication.rb +3 -1
  211. data/lib/arel/collectors/bind.rb +4 -2
  212. data/lib/arel/collectors/composite.rb +7 -0
  213. data/lib/arel/collectors/sql_string.rb +2 -2
  214. data/lib/arel/collectors/substitute_binds.rb +3 -3
  215. data/lib/arel/crud.rb +8 -11
  216. data/lib/arel/delete_manager.rb +5 -0
  217. data/lib/arel/nodes/binary.rb +1 -7
  218. data/lib/arel/nodes/bound_sql_literal.rb +9 -5
  219. data/lib/arel/nodes/count.rb +2 -2
  220. data/lib/arel/nodes/delete_statement.rb +4 -2
  221. data/lib/arel/nodes/function.rb +4 -10
  222. data/lib/arel/nodes/named_function.rb +2 -2
  223. data/lib/arel/nodes/{and.rb → nary.rb} +5 -2
  224. data/lib/arel/nodes/node.rb +6 -5
  225. data/lib/arel/nodes/sql_literal.rb +8 -1
  226. data/lib/arel/nodes/update_statement.rb +4 -2
  227. data/lib/arel/nodes.rb +2 -4
  228. data/lib/arel/predications.rb +1 -1
  229. data/lib/arel/select_manager.rb +14 -5
  230. data/lib/arel/table.rb +3 -7
  231. data/lib/arel/tree_manager.rb +3 -2
  232. data/lib/arel/update_manager.rb +7 -1
  233. data/lib/arel/visitors/dot.rb +3 -3
  234. data/lib/arel/visitors/mysql.rb +9 -4
  235. data/lib/arel/visitors/postgresql.rb +56 -12
  236. data/lib/arel/visitors/sqlite.rb +80 -8
  237. data/lib/arel/visitors/to_sql.rb +34 -37
  238. data/lib/arel.rb +10 -4
  239. data/lib/rails/generators/active_record/application_record/USAGE +1 -1
  240. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
  241. metadata +23 -14
  242. data/lib/active_record/explain_subscriber.rb +0 -34
  243. data/lib/active_record/normalization.rb +0 -167
  244. data/lib/active_record/relation/record_fetch_warning.rb +0 -49
@@ -20,6 +20,7 @@ module Arel # :nodoc: all
20
20
 
21
21
  private
22
22
  def visit_Arel_Nodes_DeleteStatement(o, collector)
23
+ collector.retryable = false
23
24
  o = prepare_delete_statement(o)
24
25
 
25
26
  if has_join_sources?(o)
@@ -34,9 +35,11 @@ module Arel # :nodoc: all
34
35
  collect_nodes_for o.wheres, collector, " WHERE ", " AND "
35
36
  collect_nodes_for o.orders, collector, " ORDER BY "
36
37
  maybe_visit o.limit, collector
38
+ maybe_visit o.comment, collector
37
39
  end
38
40
 
39
41
  def visit_Arel_Nodes_UpdateStatement(o, collector)
42
+ collector.retryable = false
40
43
  o = prepare_update_statement(o)
41
44
 
42
45
  collector << "UPDATE "
@@ -46,9 +49,11 @@ module Arel # :nodoc: all
46
49
  collect_nodes_for o.wheres, collector, " WHERE ", " AND "
47
50
  collect_nodes_for o.orders, collector, " ORDER BY "
48
51
  maybe_visit o.limit, collector
52
+ maybe_visit o.comment, collector
49
53
  end
50
54
 
51
55
  def visit_Arel_Nodes_InsertStatement(o, collector)
56
+ collector.retryable = false
52
57
  collector << "INSERT INTO "
53
58
  collector = visit o.relation, collector
54
59
 
@@ -72,13 +77,7 @@ module Arel # :nodoc: all
72
77
 
73
78
  def visit_Arel_Nodes_Exists(o, collector)
74
79
  collector << "EXISTS ("
75
- collector = visit(o.expressions, collector) << ")"
76
- if o.alias
77
- collector << " AS "
78
- visit o.alias, collector
79
- else
80
- collector
81
- end
80
+ visit(o.expressions, collector) << ")"
82
81
  end
83
82
 
84
83
  def visit_Arel_Nodes_Casted(o, collector)
@@ -381,16 +380,11 @@ module Arel # :nodoc: all
381
380
  end
382
381
 
383
382
  def visit_Arel_Nodes_NamedFunction(o, collector)
383
+ collector.retryable = false
384
384
  collector << o.name
385
385
  collector << "("
386
386
  collector << "DISTINCT " if o.distinct
387
- collector = inject_join(o.expressions, collector, ", ") << ")"
388
- if o.alias
389
- collector << " AS "
390
- visit o.alias, collector
391
- else
392
- collector
393
- end
387
+ inject_join(o.expressions, collector, ", ") << ")"
394
388
  end
395
389
 
396
390
  def visit_Arel_Nodes_Extract(o, collector)
@@ -582,10 +576,11 @@ module Arel # :nodoc: all
582
576
  end
583
577
 
584
578
  def visit_Arel_Nodes_In(o, collector)
585
- collector.preparable = false
586
579
  attr, values = o.left, o.right
587
580
 
588
581
  if Array === values
582
+ collector.preparable = false
583
+
589
584
  unless values.empty?
590
585
  values.delete_if { |value| unboundable?(value) }
591
586
  end
@@ -598,10 +593,11 @@ module Arel # :nodoc: all
598
593
  end
599
594
 
600
595
  def visit_Arel_Nodes_NotIn(o, collector)
601
- collector.preparable = false
602
596
  attr, values = o.left, o.right
603
597
 
604
598
  if Array === values
599
+ collector.preparable = false
600
+
605
601
  unless values.empty?
606
602
  values.delete_if { |value| unboundable?(value) }
607
603
  end
@@ -618,18 +614,7 @@ module Arel # :nodoc: all
618
614
  end
619
615
 
620
616
  def visit_Arel_Nodes_Or(o, collector)
621
- stack = [o.right, o.left]
622
-
623
- while o = stack.pop
624
- if o.is_a?(Arel::Nodes::Or)
625
- stack.push o.right, o.left
626
- else
627
- visit o, collector
628
- collector << " OR " unless stack.empty?
629
- end
630
- end
631
-
632
- collector
617
+ inject_join o.children, collector, " OR "
633
618
  end
634
619
 
635
620
  def visit_Arel_Nodes_Assignment(o, collector)
@@ -768,10 +753,12 @@ module Arel # :nodoc: all
768
753
 
769
754
  def visit_Arel_Nodes_SqlLiteral(o, collector)
770
755
  collector.preparable = false
756
+ collector.retryable &&= o.retryable
771
757
  collector << o.to_s
772
758
  end
773
759
 
774
760
  def visit_Arel_Nodes_BoundSqlLiteral(o, collector)
761
+ collector.retryable = false
775
762
  bind_index = 0
776
763
 
777
764
  new_bind = lambda do |value|
@@ -968,30 +955,40 @@ module Arel # :nodoc: all
968
955
  collector = if o.left.class == o.class
969
956
  infix_value_with_paren(o.left, collector, value, true)
970
957
  else
971
- visit o.left, collector
958
+ grouping_parentheses o.left, collector, false
972
959
  end
973
960
  collector << value
974
961
  collector = if o.right.class == o.class
975
962
  infix_value_with_paren(o.right, collector, value, true)
976
963
  else
977
- visit o.right, collector
964
+ grouping_parentheses o.right, collector, false
978
965
  end
979
966
  collector << " )" unless suppress_parens
980
967
  collector
981
968
  end
982
969
 
970
+ # Used by some visitors to enclose select queries in parentheses
971
+ def grouping_parentheses(o, collector, always_wrap_selects = true)
972
+ if o.is_a?(Nodes::SelectStatement) && (always_wrap_selects || require_parentheses?(o))
973
+ collector << "("
974
+ visit o, collector
975
+ collector << ")"
976
+ collector
977
+ else
978
+ visit o, collector
979
+ end
980
+ end
981
+
982
+ def require_parentheses?(o)
983
+ !o.orders.empty? || o.limit || o.offset
984
+ end
985
+
983
986
  def aggregate(name, o, collector)
984
987
  collector << "#{name}("
985
988
  if o.distinct
986
989
  collector << "DISTINCT "
987
990
  end
988
- collector = inject_join(o.expressions, collector, ", ") << ")"
989
- if o.alias
990
- collector << " AS "
991
- visit o.alias, collector
992
- else
993
- collector
994
- end
991
+ inject_join(o.expressions, collector, ", ") << ")"
995
992
  end
996
993
 
997
994
  def is_distinct_from(o, collector)
data/lib/arel.rb CHANGED
@@ -45,16 +45,22 @@ module Arel
45
45
  # that this behavior only applies when bind value parameters are
46
46
  # supplied in the call; without them, the placeholder tokens have no
47
47
  # special meaning, and will be passed through to the query as-is.
48
- def self.sql(sql_string, *positional_binds, **named_binds)
49
- if positional_binds.empty? && named_binds.empty?
50
- Arel::Nodes::SqlLiteral.new sql_string
48
+ #
49
+ # The +:retryable+ option can be used to mark the SQL as safe to retry.
50
+ # Use this option only if the SQL is idempotent, as it could be executed
51
+ # more than once.
52
+ def self.sql(sql_string, *positional_binds, retryable: false, **named_binds)
53
+ if Arel::Nodes::SqlLiteral === sql_string
54
+ sql_string
55
+ elsif positional_binds.empty? && named_binds.empty?
56
+ Arel::Nodes::SqlLiteral.new(sql_string, retryable: retryable)
51
57
  else
52
58
  Arel::Nodes::BoundSqlLiteral.new sql_string, positional_binds, named_binds
53
59
  end
54
60
  end
55
61
 
56
62
  def self.star # :nodoc:
57
- sql "*"
63
+ sql("*", retryable: true)
58
64
  end
59
65
 
60
66
  def self.arel_node?(value) # :nodoc:
@@ -5,4 +5,4 @@ Example:
5
5
  `bin/rails generate application_record`
6
6
 
7
7
  This generates the base class. A test is not generated because no
8
- behaviour is included in `ApplicationRecord` by default.
8
+ behavior is included in `ApplicationRecord` by default.
@@ -12,7 +12,10 @@ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Mi
12
12
  t.<%= attribute.type %> :<%= attribute.name %><%= attribute.inject_options %>
13
13
  <% end -%>
14
14
  <% end -%>
15
- <% if options[:timestamps] %>
15
+ <% unless attributes.empty? -%>
16
+
17
+ <% end -%>
18
+ <% if options[:timestamps] -%>
16
19
  t.timestamps
17
20
  <% end -%>
18
21
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.1.5.2
4
+ version: 8.1.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
@@ -15,28 +15,28 @@ dependencies:
15
15
  requirements:
16
16
  - - '='
17
17
  - !ruby/object:Gem::Version
18
- version: 7.1.5.2
18
+ version: 8.1.2.1
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - '='
24
24
  - !ruby/object:Gem::Version
25
- version: 7.1.5.2
25
+ version: 8.1.2.1
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: activemodel
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - '='
31
31
  - !ruby/object:Gem::Version
32
- version: 7.1.5.2
32
+ version: 8.1.2.1
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - '='
38
38
  - !ruby/object:Gem::Version
39
- version: 7.1.5.2
39
+ version: 8.1.2.1
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: timeout
42
42
  requirement: !ruby/object:Gem::Requirement
@@ -83,7 +83,9 @@ files:
83
83
  - lib/active_record/associations/builder/singular_association.rb
84
84
  - lib/active_record/associations/collection_association.rb
85
85
  - lib/active_record/associations/collection_proxy.rb
86
+ - lib/active_record/associations/deprecation.rb
86
87
  - lib/active_record/associations/disable_joins_association_scope.rb
88
+ - lib/active_record/associations/errors.rb
87
89
  - lib/active_record/associations/foreign_association.rb
88
90
  - lib/active_record/associations/has_many_association.rb
89
91
  - lib/active_record/associations/has_many_through_association.rb
@@ -93,6 +95,7 @@ files:
93
95
  - lib/active_record/associations/join_dependency/join_association.rb
94
96
  - lib/active_record/associations/join_dependency/join_base.rb
95
97
  - lib/active_record/associations/join_dependency/join_part.rb
98
+ - lib/active_record/associations/nested_error.rb
96
99
  - lib/active_record/associations/preloader.rb
97
100
  - lib/active_record/associations/preloader/association.rb
98
101
  - lib/active_record/associations/preloader/batch.rb
@@ -104,6 +107,7 @@ files:
104
107
  - lib/active_record/attribute_assignment.rb
105
108
  - lib/active_record/attribute_methods.rb
106
109
  - lib/active_record/attribute_methods/before_type_cast.rb
110
+ - lib/active_record/attribute_methods/composite_primary_key.rb
107
111
  - lib/active_record/attribute_methods/dirty.rb
108
112
  - lib/active_record/attribute_methods/primary_key.rb
109
113
  - lib/active_record/attribute_methods/query.rb
@@ -239,6 +243,7 @@ files:
239
243
  - lib/active_record/encryption/key_generator.rb
240
244
  - lib/active_record/encryption/key_provider.rb
241
245
  - lib/active_record/encryption/message.rb
246
+ - lib/active_record/encryption/message_pack_message_serializer.rb
242
247
  - lib/active_record/encryption/message_serializer.rb
243
248
  - lib/active_record/encryption/null_encryptor.rb
244
249
  - lib/active_record/encryption/properties.rb
@@ -248,7 +253,7 @@ files:
248
253
  - lib/active_record/errors.rb
249
254
  - lib/active_record/explain.rb
250
255
  - lib/active_record/explain_registry.rb
251
- - lib/active_record/explain_subscriber.rb
256
+ - lib/active_record/filter_attribute_handler.rb
252
257
  - lib/active_record/fixture_set/file.rb
253
258
  - lib/active_record/fixture_set/model_metadata.rb
254
259
  - lib/active_record/fixture_set/render_context.rb
@@ -275,6 +280,7 @@ files:
275
280
  - lib/active_record/migration.rb
276
281
  - lib/active_record/migration/command_recorder.rb
277
282
  - lib/active_record/migration/compatibility.rb
283
+ - lib/active_record/migration/default_schema_versions_formatter.rb
278
284
  - lib/active_record/migration/default_strategy.rb
279
285
  - lib/active_record/migration/execution_strategy.rb
280
286
  - lib/active_record/migration/join_table.rb
@@ -282,7 +288,6 @@ files:
282
288
  - lib/active_record/model_schema.rb
283
289
  - lib/active_record/nested_attributes.rb
284
290
  - lib/active_record/no_touching.rb
285
- - lib/active_record/normalization.rb
286
291
  - lib/active_record/persistence.rb
287
292
  - lib/active_record/promise.rb
288
293
  - lib/active_record/query_cache.rb
@@ -293,6 +298,7 @@ files:
293
298
  - lib/active_record/railties/console_sandbox.rb
294
299
  - lib/active_record/railties/controller_runtime.rb
295
300
  - lib/active_record/railties/databases.rake
301
+ - lib/active_record/railties/job_checkpoints.rb
296
302
  - lib/active_record/railties/job_runtime.rb
297
303
  - lib/active_record/readonly_attributes.rb
298
304
  - lib/active_record/reflection.rb
@@ -313,7 +319,6 @@ files:
313
319
  - lib/active_record/relation/predicate_builder/relation_handler.rb
314
320
  - lib/active_record/relation/query_attribute.rb
315
321
  - lib/active_record/relation/query_methods.rb
316
- - lib/active_record/relation/record_fetch_warning.rb
317
322
  - lib/active_record/relation/spawn_methods.rb
318
323
  - lib/active_record/relation/where_clause.rb
319
324
  - lib/active_record/result.rb
@@ -331,17 +336,21 @@ files:
331
336
  - lib/active_record/signed_id.rb
332
337
  - lib/active_record/statement_cache.rb
333
338
  - lib/active_record/store.rb
339
+ - lib/active_record/structured_event_subscriber.rb
334
340
  - lib/active_record/suppressor.rb
335
341
  - lib/active_record/table_metadata.rb
342
+ - lib/active_record/tasks/abstract_tasks.rb
336
343
  - lib/active_record/tasks/database_tasks.rb
337
344
  - lib/active_record/tasks/mysql_database_tasks.rb
338
345
  - lib/active_record/tasks/postgresql_database_tasks.rb
339
346
  - lib/active_record/tasks/sqlite_database_tasks.rb
340
347
  - lib/active_record/test_databases.rb
341
348
  - lib/active_record/test_fixtures.rb
349
+ - lib/active_record/testing/query_assertions.rb
342
350
  - lib/active_record/timestamp.rb
343
351
  - lib/active_record/token_for.rb
344
352
  - lib/active_record/touch_later.rb
353
+ - lib/active_record/transaction.rb
345
354
  - lib/active_record/transactions.rb
346
355
  - lib/active_record/translation.rb
347
356
  - lib/active_record/type.rb
@@ -385,7 +394,6 @@ files:
385
394
  - lib/arel/insert_manager.rb
386
395
  - lib/arel/math.rb
387
396
  - lib/arel/nodes.rb
388
- - lib/arel/nodes/and.rb
389
397
  - lib/arel/nodes/ascending.rb
390
398
  - lib/arel/nodes/binary.rb
391
399
  - lib/arel/nodes/bind_param.rb
@@ -414,6 +422,7 @@ files:
414
422
  - lib/arel/nodes/leading_join.rb
415
423
  - lib/arel/nodes/matches.rb
416
424
  - lib/arel/nodes/named_function.rb
425
+ - lib/arel/nodes/nary.rb
417
426
  - lib/arel/nodes/node.rb
418
427
  - lib/arel/nodes/node_expression.rb
419
428
  - lib/arel/nodes/ordering.rb
@@ -469,10 +478,10 @@ licenses:
469
478
  - MIT
470
479
  metadata:
471
480
  bug_tracker_uri: https://github.com/rails/rails/issues
472
- changelog_uri: https://github.com/rails/rails/blob/v7.1.5.2/activerecord/CHANGELOG.md
473
- documentation_uri: https://api.rubyonrails.org/v7.1.5.2/
481
+ changelog_uri: https://github.com/rails/rails/blob/v8.1.2.1/activerecord/CHANGELOG.md
482
+ documentation_uri: https://api.rubyonrails.org/v8.1.2.1/
474
483
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
475
- source_code_uri: https://github.com/rails/rails/tree/v7.1.5.2/activerecord
484
+ source_code_uri: https://github.com/rails/rails/tree/v8.1.2.1/activerecord
476
485
  rubygems_mfa_required: 'true'
477
486
  rdoc_options:
478
487
  - "--main"
@@ -483,14 +492,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
483
492
  requirements:
484
493
  - - ">="
485
494
  - !ruby/object:Gem::Version
486
- version: 2.7.0
495
+ version: 3.2.0
487
496
  required_rubygems_version: !ruby/object:Gem::Requirement
488
497
  requirements:
489
498
  - - ">="
490
499
  - !ruby/object:Gem::Version
491
500
  version: '0'
492
501
  requirements: []
493
- rubygems_version: 3.6.9
502
+ rubygems_version: 4.0.6
494
503
  specification_version: 4
495
504
  summary: Object-relational mapper framework (part of Rails).
496
505
  test_files: []
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "active_support/notifications"
4
- require "active_record/explain_registry"
5
-
6
- module ActiveRecord
7
- class ExplainSubscriber # :nodoc:
8
- def start(name, id, payload)
9
- # unused
10
- end
11
-
12
- def finish(name, id, payload)
13
- if ExplainRegistry.collect? && !ignore_payload?(payload)
14
- ExplainRegistry.queries << payload.values_at(:sql, :binds)
15
- end
16
- end
17
-
18
- # SCHEMA queries cannot be EXPLAINed, also we do not want to run EXPLAIN on
19
- # our own EXPLAINs no matter how loopingly beautiful that would be.
20
- #
21
- # On the other hand, we want to monitor the performance of our real database
22
- # queries, not the performance of the access to the query cache.
23
- IGNORED_PAYLOADS = %w(SCHEMA EXPLAIN)
24
- EXPLAINED_SQLS = /\A\s*(\/\*.*\*\/)?\s*(with|select|update|delete|insert)\b/i
25
- def ignore_payload?(payload)
26
- payload[:exception] ||
27
- payload[:cached] ||
28
- IGNORED_PAYLOADS.include?(payload[:name]) ||
29
- !payload[:sql].match?(EXPLAINED_SQLS)
30
- end
31
-
32
- ActiveSupport::Notifications.subscribe("sql.active_record", new)
33
- end
34
- end
@@ -1,167 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveRecord # :nodoc:
4
- module Normalization
5
- extend ActiveSupport::Concern
6
-
7
- included do
8
- class_attribute :normalized_attributes, default: Set.new
9
-
10
- before_validation :normalize_changed_in_place_attributes
11
- end
12
-
13
- # Normalizes a specified attribute using its declared normalizations.
14
- #
15
- # ==== Examples
16
- #
17
- # class User < ActiveRecord::Base
18
- # normalizes :email, with: -> email { email.strip.downcase }
19
- # end
20
- #
21
- # legacy_user = User.find(1)
22
- # legacy_user.email # => " CRUISE-CONTROL@EXAMPLE.COM\n"
23
- # legacy_user.normalize_attribute(:email)
24
- # legacy_user.email # => "cruise-control@example.com"
25
- # legacy_user.save
26
- def normalize_attribute(name)
27
- # Treat the value as a new, unnormalized value.
28
- self[name] = self[name]
29
- end
30
-
31
- module ClassMethods
32
- # Declares a normalization for one or more attributes. The normalization
33
- # is applied when the attribute is assigned or updated, and the normalized
34
- # value will be persisted to the database. The normalization is also
35
- # applied to the corresponding keyword argument of query methods. This
36
- # allows a record to be created and later queried using unnormalized
37
- # values.
38
- #
39
- # However, to prevent confusion, the normalization will not be applied
40
- # when the attribute is fetched from the database. This means that if a
41
- # record was persisted before the normalization was declared, the record's
42
- # attribute will not be normalized until either it is assigned a new
43
- # value, or it is explicitly migrated via Normalization#normalize_attribute.
44
- #
45
- # Because the normalization may be applied multiple times, it should be
46
- # _idempotent_. In other words, applying the normalization more than once
47
- # should have the same result as applying it only once.
48
- #
49
- # By default, the normalization will not be applied to +nil+ values. This
50
- # behavior can be changed with the +:apply_to_nil+ option.
51
- #
52
- # Be aware that if your app was created before Rails 7.1, and your app
53
- # marshals instances of the targeted model (for example, when caching),
54
- # then you should set ActiveRecord.marshalling_format_version to +7.1+ or
55
- # higher via either <tt>config.load_defaults 7.1</tt> or
56
- # <tt>config.active_record.marshalling_format_version = 7.1</tt>.
57
- # Otherwise, +Marshal+ may attempt to serialize the normalization +Proc+
58
- # and raise +TypeError+.
59
- #
60
- # ==== Options
61
- #
62
- # * +:with+ - Any callable object that accepts the attribute's value as
63
- # its sole argument, and returns it normalized.
64
- # * +:apply_to_nil+ - Whether to apply the normalization to +nil+ values.
65
- # Defaults to +false+.
66
- #
67
- # ==== Examples
68
- #
69
- # class User < ActiveRecord::Base
70
- # normalizes :email, with: -> email { email.strip.downcase }
71
- # normalizes :phone, with: -> phone { phone.delete("^0-9").delete_prefix("1") }
72
- # end
73
- #
74
- # user = User.create(email: " CRUISE-CONTROL@EXAMPLE.COM\n")
75
- # user.email # => "cruise-control@example.com"
76
- #
77
- # user = User.find_by(email: "\tCRUISE-CONTROL@EXAMPLE.COM ")
78
- # user.email # => "cruise-control@example.com"
79
- # user.email_before_type_cast # => "cruise-control@example.com"
80
- #
81
- # User.where(email: "\tCRUISE-CONTROL@EXAMPLE.COM ").count # => 1
82
- # User.where(["email = ?", "\tCRUISE-CONTROL@EXAMPLE.COM "]).count # => 0
83
- #
84
- # User.exists?(email: "\tCRUISE-CONTROL@EXAMPLE.COM ") # => true
85
- # User.exists?(["email = ?", "\tCRUISE-CONTROL@EXAMPLE.COM "]) # => false
86
- #
87
- # User.normalize_value_for(:phone, "+1 (555) 867-5309") # => "5558675309"
88
- def normalizes(*names, with:, apply_to_nil: false)
89
- names.each do |name|
90
- attribute(name) do |cast_type|
91
- NormalizedValueType.new(cast_type: cast_type, normalizer: with, normalize_nil: apply_to_nil)
92
- end
93
- end
94
-
95
- self.normalized_attributes += names.map(&:to_sym)
96
- end
97
-
98
- # Normalizes a given +value+ using normalizations declared for +name+.
99
- #
100
- # ==== Examples
101
- #
102
- # class User < ActiveRecord::Base
103
- # normalizes :email, with: -> email { email.strip.downcase }
104
- # end
105
- #
106
- # User.normalize_value_for(:email, " CRUISE-CONTROL@EXAMPLE.COM\n")
107
- # # => "cruise-control@example.com"
108
- def normalize_value_for(name, value)
109
- type_for_attribute(name).cast(value)
110
- end
111
- end
112
-
113
- private
114
- def normalize_changed_in_place_attributes
115
- self.class.normalized_attributes.each do |name|
116
- normalize_attribute(name) if attribute_changed_in_place?(name)
117
- end
118
- end
119
-
120
- class NormalizedValueType < DelegateClass(ActiveModel::Type::Value) # :nodoc:
121
- include ActiveModel::Type::SerializeCastValue
122
-
123
- attr_reader :cast_type, :normalizer, :normalize_nil
124
- alias :normalize_nil? :normalize_nil
125
-
126
- def initialize(cast_type:, normalizer:, normalize_nil:)
127
- @cast_type = cast_type
128
- @normalizer = normalizer
129
- @normalize_nil = normalize_nil
130
- super(cast_type)
131
- end
132
-
133
- def cast(value)
134
- normalize(super(value))
135
- end
136
-
137
- def serialize(value)
138
- serialize_cast_value(cast(value))
139
- end
140
-
141
- def serialize_cast_value(value)
142
- ActiveModel::Type::SerializeCastValue.serialize(cast_type, value)
143
- end
144
-
145
- def ==(other)
146
- self.class == other.class &&
147
- normalize_nil? == other.normalize_nil? &&
148
- normalizer == other.normalizer &&
149
- cast_type == other.cast_type
150
- end
151
- alias eql? ==
152
-
153
- def hash
154
- [self.class, cast_type, normalizer, normalize_nil?].hash
155
- end
156
-
157
- def inspect
158
- Kernel.instance_method(:inspect).bind_call(self)
159
- end
160
-
161
- private
162
- def normalize(value)
163
- normalizer.call(value) unless value.nil? && !normalize_nil?
164
- end
165
- end
166
- end
167
- end
@@ -1,49 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveRecord
4
- class Relation
5
- module RecordFetchWarning
6
- # When this module is prepended to ActiveRecord::Relation and
7
- # +config.active_record.warn_on_records_fetched_greater_than+ is
8
- # set to an integer, if the number of records a query returns is
9
- # greater than the value of +warn_on_records_fetched_greater_than+,
10
- # a warning is logged. This allows for the detection of queries that
11
- # return a large number of records, which could cause memory bloat.
12
- #
13
- # In most cases, fetching large number of records can be performed
14
- # efficiently using the ActiveRecord::Batches methods.
15
- # See ActiveRecord::Batches for more information.
16
- def exec_queries
17
- QueryRegistry.reset
18
-
19
- super.tap do |records|
20
- if logger && ActiveRecord.warn_on_records_fetched_greater_than
21
- if records.length > ActiveRecord.warn_on_records_fetched_greater_than
22
- logger.warn "Query fetched #{records.size} #{@klass} records: #{QueryRegistry.queries.join(";")}"
23
- end
24
- end
25
- end
26
- end
27
-
28
- # :stopdoc:
29
- ActiveSupport::Notifications.subscribe("sql.active_record") do |*, payload|
30
- QueryRegistry.queries << payload[:sql]
31
- end
32
- # :startdoc:
33
-
34
- module QueryRegistry # :nodoc:
35
- extend self
36
-
37
- def queries
38
- ActiveSupport::IsolatedExecutionState[:active_record_query_registry] ||= []
39
- end
40
-
41
- def reset
42
- queries.clear
43
- end
44
- end
45
- end
46
- end
47
- end
48
-
49
- ActiveRecord::Relation.prepend ActiveRecord::Relation::RecordFetchWarning