activerecord 7.0.0 → 7.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 (289) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +515 -1268
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +31 -31
  5. data/examples/performance.rb +2 -2
  6. data/lib/active_record/aggregations.rb +16 -13
  7. data/lib/active_record/association_relation.rb +2 -2
  8. data/lib/active_record/associations/alias_tracker.rb +25 -19
  9. data/lib/active_record/associations/association.rb +35 -12
  10. data/lib/active_record/associations/association_scope.rb +16 -9
  11. data/lib/active_record/associations/belongs_to_association.rb +23 -8
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
  13. data/lib/active_record/associations/builder/association.rb +3 -3
  14. data/lib/active_record/associations/builder/belongs_to.rb +22 -8
  15. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -7
  16. data/lib/active_record/associations/builder/has_many.rb +3 -4
  17. data/lib/active_record/associations/builder/has_one.rb +3 -4
  18. data/lib/active_record/associations/builder/singular_association.rb +4 -0
  19. data/lib/active_record/associations/collection_association.rb +28 -17
  20. data/lib/active_record/associations/collection_proxy.rb +36 -13
  21. data/lib/active_record/associations/errors.rb +265 -0
  22. data/lib/active_record/associations/foreign_association.rb +10 -3
  23. data/lib/active_record/associations/has_many_association.rb +28 -18
  24. data/lib/active_record/associations/has_many_through_association.rb +10 -6
  25. data/lib/active_record/associations/has_one_association.rb +10 -3
  26. data/lib/active_record/associations/join_dependency/join_association.rb +27 -25
  27. data/lib/active_record/associations/join_dependency.rb +18 -14
  28. data/lib/active_record/associations/nested_error.rb +47 -0
  29. data/lib/active_record/associations/preloader/association.rb +33 -8
  30. data/lib/active_record/associations/preloader/branch.rb +7 -1
  31. data/lib/active_record/associations/preloader/through_association.rb +2 -4
  32. data/lib/active_record/associations/preloader.rb +13 -10
  33. data/lib/active_record/associations/singular_association.rb +7 -1
  34. data/lib/active_record/associations/through_association.rb +22 -11
  35. data/lib/active_record/associations.rb +378 -491
  36. data/lib/active_record/attribute_assignment.rb +1 -13
  37. data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
  38. data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
  39. data/lib/active_record/attribute_methods/dirty.rb +53 -35
  40. data/lib/active_record/attribute_methods/primary_key.rb +45 -25
  41. data/lib/active_record/attribute_methods/query.rb +28 -16
  42. data/lib/active_record/attribute_methods/read.rb +8 -7
  43. data/lib/active_record/attribute_methods/serialization.rb +153 -70
  44. data/lib/active_record/attribute_methods/time_zone_conversion.rb +7 -6
  45. data/lib/active_record/attribute_methods/write.rb +6 -6
  46. data/lib/active_record/attribute_methods.rb +153 -40
  47. data/lib/active_record/attributes.rb +63 -48
  48. data/lib/active_record/autosave_association.rb +70 -38
  49. data/lib/active_record/base.rb +12 -8
  50. data/lib/active_record/callbacks.rb +16 -32
  51. data/lib/active_record/coders/column_serializer.rb +61 -0
  52. data/lib/active_record/coders/json.rb +1 -1
  53. data/lib/active_record/coders/yaml_column.rb +70 -34
  54. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +124 -132
  55. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +4 -1
  57. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +297 -88
  58. data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
  59. data/lib/active_record/connection_adapters/abstract/database_statements.rb +160 -45
  60. data/lib/active_record/connection_adapters/abstract/query_cache.rb +215 -63
  61. data/lib/active_record/connection_adapters/abstract/quoting.rb +83 -65
  62. data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
  63. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +18 -4
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +163 -29
  65. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
  66. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +319 -135
  67. data/lib/active_record/connection_adapters/abstract/transaction.rb +367 -75
  68. data/lib/active_record/connection_adapters/abstract_adapter.rb +512 -126
  69. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +282 -119
  70. data/lib/active_record/connection_adapters/column.rb +9 -0
  71. data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
  72. data/lib/active_record/connection_adapters/mysql/database_statements.rb +27 -140
  73. data/lib/active_record/connection_adapters/mysql/quoting.rb +64 -52
  74. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
  75. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
  76. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
  77. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +45 -14
  78. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
  79. data/lib/active_record/connection_adapters/mysql2_adapter.rb +101 -68
  80. data/lib/active_record/connection_adapters/pool_config.rb +20 -10
  81. data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +16 -3
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +101 -48
  84. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
  85. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -2
  87. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
  88. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +11 -2
  90. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +4 -2
  91. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
  92. data/lib/active_record/connection_adapters/postgresql/quoting.rb +94 -61
  93. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +6 -10
  94. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
  95. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +151 -2
  96. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +53 -0
  97. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +379 -66
  98. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
  99. data/lib/active_record/connection_adapters/postgresql_adapter.rb +370 -203
  100. data/lib/active_record/connection_adapters/schema_cache.rb +302 -79
  101. data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
  102. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +60 -43
  103. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +61 -46
  104. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  105. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +20 -0
  106. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
  107. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +64 -22
  108. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +321 -110
  109. data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
  110. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
  111. data/lib/active_record/connection_adapters/trilogy_adapter.rb +229 -0
  112. data/lib/active_record/connection_adapters.rb +124 -1
  113. data/lib/active_record/connection_handling.rb +98 -106
  114. data/lib/active_record/core.rb +220 -177
  115. data/lib/active_record/counter_cache.rb +68 -34
  116. data/lib/active_record/database_configurations/connection_url_resolver.rb +8 -2
  117. data/lib/active_record/database_configurations/database_config.rb +26 -5
  118. data/lib/active_record/database_configurations/hash_config.rb +52 -34
  119. data/lib/active_record/database_configurations/url_config.rb +37 -12
  120. data/lib/active_record/database_configurations.rb +88 -35
  121. data/lib/active_record/delegated_type.rb +40 -11
  122. data/lib/active_record/deprecator.rb +7 -0
  123. data/lib/active_record/destroy_association_async_job.rb +3 -1
  124. data/lib/active_record/disable_joins_association_relation.rb +1 -1
  125. data/lib/active_record/dynamic_matchers.rb +2 -2
  126. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  127. data/lib/active_record/encryption/cipher/aes256_gcm.rb +4 -1
  128. data/lib/active_record/encryption/config.rb +25 -1
  129. data/lib/active_record/encryption/configurable.rb +13 -14
  130. data/lib/active_record/encryption/context.rb +10 -3
  131. data/lib/active_record/encryption/contexts.rb +8 -4
  132. data/lib/active_record/encryption/derived_secret_key_provider.rb +9 -3
  133. data/lib/active_record/encryption/deterministic_key_provider.rb +1 -1
  134. data/lib/active_record/encryption/encryptable_record.rb +47 -25
  135. data/lib/active_record/encryption/encrypted_attribute_type.rb +49 -14
  136. data/lib/active_record/encryption/encryptor.rb +25 -10
  137. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +3 -3
  138. data/lib/active_record/encryption/extended_deterministic_queries.rb +83 -86
  139. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +3 -3
  140. data/lib/active_record/encryption/key_generator.rb +12 -1
  141. data/lib/active_record/encryption/message.rb +1 -1
  142. data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
  143. data/lib/active_record/encryption/message_serializer.rb +6 -0
  144. data/lib/active_record/encryption/null_encryptor.rb +4 -0
  145. data/lib/active_record/encryption/properties.rb +4 -4
  146. data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
  147. data/lib/active_record/encryption/scheme.rb +23 -22
  148. data/lib/active_record/encryption.rb +1 -0
  149. data/lib/active_record/enum.rb +131 -27
  150. data/lib/active_record/errors.rb +151 -31
  151. data/lib/active_record/explain.rb +21 -12
  152. data/lib/active_record/explain_subscriber.rb +1 -1
  153. data/lib/active_record/fixture_set/model_metadata.rb +14 -4
  154. data/lib/active_record/fixture_set/render_context.rb +2 -0
  155. data/lib/active_record/fixture_set/table_row.rb +29 -8
  156. data/lib/active_record/fixtures.rb +169 -99
  157. data/lib/active_record/future_result.rb +47 -8
  158. data/lib/active_record/gem_version.rb +3 -3
  159. data/lib/active_record/inheritance.rb +34 -18
  160. data/lib/active_record/insert_all.rb +72 -22
  161. data/lib/active_record/integration.rb +13 -10
  162. data/lib/active_record/internal_metadata.rb +124 -20
  163. data/lib/active_record/locking/optimistic.rb +39 -24
  164. data/lib/active_record/locking/pessimistic.rb +8 -5
  165. data/lib/active_record/log_subscriber.rb +28 -27
  166. data/lib/active_record/marshalling.rb +56 -0
  167. data/lib/active_record/message_pack.rb +124 -0
  168. data/lib/active_record/middleware/database_selector/resolver.rb +4 -0
  169. data/lib/active_record/middleware/database_selector.rb +18 -13
  170. data/lib/active_record/middleware/shard_selector.rb +7 -5
  171. data/lib/active_record/migration/command_recorder.rb +110 -13
  172. data/lib/active_record/migration/compatibility.rb +174 -64
  173. data/lib/active_record/migration/default_strategy.rb +22 -0
  174. data/lib/active_record/migration/execution_strategy.rb +19 -0
  175. data/lib/active_record/migration/pending_migration_connection.rb +21 -0
  176. data/lib/active_record/migration.rb +292 -125
  177. data/lib/active_record/model_schema.rb +113 -112
  178. data/lib/active_record/nested_attributes.rb +35 -9
  179. data/lib/active_record/normalization.rb +163 -0
  180. data/lib/active_record/persistence.rb +177 -345
  181. data/lib/active_record/promise.rb +84 -0
  182. data/lib/active_record/query_cache.rb +19 -25
  183. data/lib/active_record/query_logs.rb +102 -51
  184. data/lib/active_record/query_logs_formatter.rb +41 -0
  185. data/lib/active_record/querying.rb +34 -9
  186. data/lib/active_record/railtie.rb +153 -100
  187. data/lib/active_record/railties/controller_runtime.rb +24 -10
  188. data/lib/active_record/railties/databases.rake +148 -152
  189. data/lib/active_record/railties/job_runtime.rb +23 -0
  190. data/lib/active_record/readonly_attributes.rb +32 -5
  191. data/lib/active_record/reflection.rb +278 -69
  192. data/lib/active_record/relation/batches/batch_enumerator.rb +20 -5
  193. data/lib/active_record/relation/batches.rb +198 -63
  194. data/lib/active_record/relation/calculations.rb +293 -108
  195. data/lib/active_record/relation/delegation.rb +31 -20
  196. data/lib/active_record/relation/finder_methods.rb +93 -18
  197. data/lib/active_record/relation/merger.rb +6 -6
  198. data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
  199. data/lib/active_record/relation/predicate_builder/association_query_value.rb +38 -4
  200. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -7
  201. data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
  202. data/lib/active_record/relation/predicate_builder.rb +28 -16
  203. data/lib/active_record/relation/query_attribute.rb +25 -1
  204. data/lib/active_record/relation/query_methods.rb +625 -107
  205. data/lib/active_record/relation/record_fetch_warning.rb +3 -0
  206. data/lib/active_record/relation/spawn_methods.rb +5 -4
  207. data/lib/active_record/relation/where_clause.rb +7 -19
  208. data/lib/active_record/relation.rb +602 -96
  209. data/lib/active_record/result.rb +55 -52
  210. data/lib/active_record/runtime_registry.rb +63 -1
  211. data/lib/active_record/sanitization.rb +76 -30
  212. data/lib/active_record/schema.rb +39 -23
  213. data/lib/active_record/schema_dumper.rb +82 -30
  214. data/lib/active_record/schema_migration.rb +75 -24
  215. data/lib/active_record/scoping/default.rb +20 -12
  216. data/lib/active_record/scoping/named.rb +3 -2
  217. data/lib/active_record/scoping.rb +2 -1
  218. data/lib/active_record/secure_password.rb +60 -0
  219. data/lib/active_record/secure_token.rb +21 -3
  220. data/lib/active_record/serialization.rb +5 -0
  221. data/lib/active_record/signed_id.rb +29 -8
  222. data/lib/active_record/statement_cache.rb +7 -7
  223. data/lib/active_record/store.rb +16 -11
  224. data/lib/active_record/suppressor.rb +3 -1
  225. data/lib/active_record/table_metadata.rb +7 -3
  226. data/lib/active_record/tasks/database_tasks.rb +191 -121
  227. data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
  228. data/lib/active_record/tasks/postgresql_database_tasks.rb +17 -15
  229. data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -7
  230. data/lib/active_record/test_fixtures.rb +174 -152
  231. data/lib/active_record/testing/query_assertions.rb +121 -0
  232. data/lib/active_record/timestamp.rb +31 -17
  233. data/lib/active_record/token_for.rb +123 -0
  234. data/lib/active_record/touch_later.rb +12 -7
  235. data/lib/active_record/transaction.rb +132 -0
  236. data/lib/active_record/transactions.rb +109 -27
  237. data/lib/active_record/translation.rb +1 -3
  238. data/lib/active_record/type/adapter_specific_registry.rb +1 -8
  239. data/lib/active_record/type/internal/timezone.rb +7 -2
  240. data/lib/active_record/type/serialized.rb +9 -7
  241. data/lib/active_record/type/time.rb +4 -0
  242. data/lib/active_record/type_caster/connection.rb +4 -4
  243. data/lib/active_record/validations/absence.rb +1 -1
  244. data/lib/active_record/validations/associated.rb +12 -6
  245. data/lib/active_record/validations/numericality.rb +5 -4
  246. data/lib/active_record/validations/presence.rb +5 -28
  247. data/lib/active_record/validations/uniqueness.rb +63 -14
  248. data/lib/active_record/validations.rb +12 -5
  249. data/lib/active_record/version.rb +1 -1
  250. data/lib/active_record.rb +266 -30
  251. data/lib/arel/alias_predication.rb +1 -1
  252. data/lib/arel/collectors/bind.rb +2 -0
  253. data/lib/arel/collectors/composite.rb +7 -0
  254. data/lib/arel/collectors/sql_string.rb +1 -1
  255. data/lib/arel/collectors/substitute_binds.rb +1 -1
  256. data/lib/arel/errors.rb +10 -0
  257. data/lib/arel/factory_methods.rb +4 -0
  258. data/lib/arel/filter_predications.rb +1 -1
  259. data/lib/arel/nodes/binary.rb +6 -7
  260. data/lib/arel/nodes/bound_sql_literal.rb +65 -0
  261. data/lib/arel/nodes/cte.rb +36 -0
  262. data/lib/arel/nodes/filter.rb +1 -1
  263. data/lib/arel/nodes/fragments.rb +35 -0
  264. data/lib/arel/nodes/homogeneous_in.rb +1 -9
  265. data/lib/arel/nodes/leading_join.rb +8 -0
  266. data/lib/arel/nodes/{and.rb → nary.rb} +9 -2
  267. data/lib/arel/nodes/node.rb +115 -5
  268. data/lib/arel/nodes/sql_literal.rb +13 -0
  269. data/lib/arel/nodes/table_alias.rb +4 -0
  270. data/lib/arel/nodes.rb +6 -2
  271. data/lib/arel/predications.rb +3 -1
  272. data/lib/arel/select_manager.rb +1 -1
  273. data/lib/arel/table.rb +9 -5
  274. data/lib/arel/tree_manager.rb +8 -3
  275. data/lib/arel/update_manager.rb +2 -1
  276. data/lib/arel/visitors/dot.rb +1 -0
  277. data/lib/arel/visitors/mysql.rb +17 -5
  278. data/lib/arel/visitors/postgresql.rb +1 -12
  279. data/lib/arel/visitors/to_sql.rb +112 -34
  280. data/lib/arel/visitors/visitor.rb +2 -2
  281. data/lib/arel.rb +21 -3
  282. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  283. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
  284. data/lib/rails/generators/active_record/migration.rb +3 -1
  285. data/lib/rails/generators/active_record/model/USAGE +113 -0
  286. data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
  287. metadata +59 -17
  288. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
  289. data/lib/active_record/null_relation.rb +0 -63
@@ -8,11 +8,21 @@ module ActiveRecord
8
8
  included do
9
9
  ##
10
10
  # :singleton-method:
11
- # Set the secret used for the signed id verifier instance when using Active Record outside of Rails.
12
- # Within Rails, this is automatically set using the Rails application key generator.
11
+ # Set the secret used for the signed id verifier instance when using Active Record outside of \Rails.
12
+ # Within \Rails, this is automatically set using the \Rails application key generator.
13
13
  class_attribute :signed_id_verifier_secret, instance_writer: false
14
14
  end
15
15
 
16
+ module RelationMethods # :nodoc:
17
+ def find_signed(...)
18
+ scoping { model.find_signed(...) }
19
+ end
20
+
21
+ def find_signed!(...)
22
+ scoping { model.find_signed!(...) }
23
+ end
24
+ end
25
+
16
26
  module ClassMethods
17
27
  # Lets you find a record based on a signed id that's safe to put into the world without risk of tampering.
18
28
  # This is particularly useful for things like password reset or email verification, where you want
@@ -47,7 +57,7 @@ module ActiveRecord
47
57
  end
48
58
  end
49
59
 
50
- # Works like +find_signed+, but will raise an +ActiveSupport::MessageVerifier::InvalidSignature+
60
+ # Works like find_signed, but will raise an +ActiveSupport::MessageVerifier::InvalidSignature+
51
61
  # exception if the +signed_id+ has either expired, has a purpose mismatch, is for another record,
52
62
  # or has been tampered with. It will also raise an +ActiveRecord::RecordNotFound+ exception if
53
63
  # the valid signed id can't find a record.
@@ -66,7 +76,7 @@ module ActiveRecord
66
76
  end
67
77
 
68
78
  # The verifier instance that all signed ids are generated and verified from. By default, it'll be initialized
69
- # with the class-level +signed_id_verifier_secret+, which within Rails comes from the
79
+ # with the class-level +signed_id_verifier_secret+, which within \Rails comes from the
70
80
  # Rails.application.key_generator. By default, it's SHA256 for the digest and JSON for the serialization.
71
81
  def signed_id_verifier
72
82
  @signed_id_verifier ||= begin
@@ -76,7 +86,7 @@ module ActiveRecord
76
86
  if secret.nil?
77
87
  raise ArgumentError, "You must set ActiveRecord::Base.signed_id_verifier_secret to use signed ids"
78
88
  else
79
- ActiveSupport::MessageVerifier.new secret, digest: "SHA256", serializer: JSON
89
+ ActiveSupport::MessageVerifier.new secret, digest: "SHA256", serializer: JSON, url_safe: true
80
90
  end
81
91
  end
82
92
  end
@@ -96,8 +106,17 @@ module ActiveRecord
96
106
 
97
107
 
98
108
  # Returns a signed id that's generated using a preconfigured +ActiveSupport::MessageVerifier+ instance.
109
+ #
99
110
  # This signed id is tamper proof, so it's safe to send in an email or otherwise share with the outside world.
100
- # It can further more be set to expire (the default is not to expire), and scoped down with a specific purpose.
111
+ # However, as with any message signed with a +ActiveSupport::MessageVerifier+,
112
+ # {the signed id is not encrypted}[link:classes/ActiveSupport/MessageVerifier.html#class-ActiveSupport::MessageVerifier-label-Signing+is+not+encryption].
113
+ # It's just encoded and protected against tampering.
114
+ #
115
+ # This means that the ID can be decoded by anyone; however, if tampered with (so to point to a different ID),
116
+ # the cryptographic signature will no longer match, and the signed id will be considered invalid and return nil
117
+ # when passed to +find_signed+ (or raise with +find_signed!+).
118
+ #
119
+ # It can furthermore be set to expire (the default is not to expire), and scoped down with a specific purpose.
101
120
  # If the expiration date has been exceeded before +find_signed+ is called, the id won't find the designated
102
121
  # record. If a purpose is set, this too must match.
103
122
  #
@@ -109,8 +128,10 @@ module ActiveRecord
109
128
  #
110
129
  # And you then change your +find_signed+ calls to require this new purpose. Any old signed ids that were not
111
130
  # created with the purpose will no longer find the record.
112
- def signed_id(expires_in: nil, purpose: nil)
113
- self.class.signed_id_verifier.generate id, expires_in: expires_in, purpose: self.class.combine_signed_id_purposes(purpose)
131
+ def signed_id(expires_in: nil, expires_at: nil, purpose: nil)
132
+ raise ArgumentError, "Cannot get a signed_id for a new record" if new_record?
133
+
134
+ self.class.signed_id_verifier.generate id, expires_in: expires_in, expires_at: expires_at, purpose: self.class.combine_signed_id_purposes(purpose)
114
135
  end
115
136
  end
116
137
  end
@@ -4,14 +4,14 @@ module ActiveRecord
4
4
  # Statement cache is used to cache a single statement in order to avoid creating the AST again.
5
5
  # Initializing the cache is done by passing the statement in the create block:
6
6
  #
7
- # cache = StatementCache.create(Book.connection) do |params|
7
+ # cache = StatementCache.create(ClothingItem.lease_connection) do |params|
8
8
  # Book.where(name: "my book").where("author_id > 3")
9
9
  # end
10
10
  #
11
11
  # The cached statement is executed by using the
12
12
  # {connection.execute}[rdoc-ref:ConnectionAdapters::DatabaseStatements#execute] method:
13
13
  #
14
- # cache.execute([], Book.connection)
14
+ # cache.execute([], ClothingItem.lease_connection)
15
15
  #
16
16
  # The relation returned by the block is cached, and for each
17
17
  # {execute}[rdoc-ref:ConnectionAdapters::DatabaseStatements#execute]
@@ -20,13 +20,13 @@ module ActiveRecord
20
20
  # If you want to cache the statement without the values you can use the +bind+ method of the
21
21
  # block parameter.
22
22
  #
23
- # cache = StatementCache.create(Book.connection) do |params|
23
+ # cache = StatementCache.create(ClothingItem.lease_connection) do |params|
24
24
  # Book.where(name: params.bind)
25
25
  # end
26
26
  #
27
27
  # And pass the bind values as the first argument of +execute+ call.
28
28
  #
29
- # cache.execute(["my book"], Book.connection)
29
+ # cache.execute(["my book"], ClothingItem.lease_connection)
30
30
  class StatementCache # :nodoc:
31
31
  class Substitute; end # :nodoc:
32
32
 
@@ -62,7 +62,7 @@ module ActiveRecord
62
62
  end
63
63
 
64
64
  class PartialQueryCollector
65
- attr_accessor :preparable
65
+ attr_accessor :preparable, :retryable
66
66
 
67
67
  def initialize
68
68
  @parts = []
@@ -142,12 +142,12 @@ module ActiveRecord
142
142
  @klass = klass
143
143
  end
144
144
 
145
- def execute(params, connection, &block)
145
+ def execute(params, connection, allow_retry: false, &block)
146
146
  bind_values = bind_map.bind params
147
147
 
148
148
  sql = query_builder.sql_for bind_values, connection
149
149
 
150
- klass.find_by_sql(sql, bind_values, preparable: true, &block)
150
+ klass.find_by_sql(sql, bind_values, preparable: true, allow_retry: allow_retry, &block)
151
151
  rescue ::RangeError
152
152
  []
153
153
  end
@@ -3,6 +3,8 @@
3
3
  require "active_support/core_ext/hash/indifferent_access"
4
4
 
5
5
  module ActiveRecord
6
+ # = Active Record \Store
7
+ #
6
8
  # Store gives you a thin wrapper around serialize for the purpose of storing hashes in a single column.
7
9
  # It's like a simple key/value store baked into your record when you don't care about being able to
8
10
  # query that store outside the context of a single record.
@@ -59,7 +61,7 @@ module ActiveRecord
59
61
  # u.color = 'green'
60
62
  # u.color_changed? # => true
61
63
  # u.color_was # => 'black'
62
- # u.color_change # => ['black', 'red']
64
+ # u.color_change # => ['black', 'green']
63
65
  #
64
66
  # # Add additional accessors to an existing store through store_accessor
65
67
  # class SuperUser < User
@@ -70,7 +72,7 @@ module ActiveRecord
70
72
  #
71
73
  # The stored attribute names can be retrieved using {.stored_attributes}[rdoc-ref:rdoc-ref:ClassMethods#stored_attributes].
72
74
  #
73
- # User.stored_attributes[:settings] # [:color, :homepage, :two_factor_auth, :login_retry]
75
+ # User.stored_attributes[:settings] # => [:color, :homepage, :two_factor_auth, :login_retry]
74
76
  #
75
77
  # == Overwriting default accessors
76
78
  #
@@ -102,7 +104,8 @@ module ActiveRecord
102
104
 
103
105
  module ClassMethods
104
106
  def store(store_attribute, options = {})
105
- serialize store_attribute, IndifferentCoder.new(store_attribute, options[:coder])
107
+ coder = build_column_serializer(store_attribute, options[:coder], Object, options[:yaml])
108
+ serialize store_attribute, coder: IndifferentCoder.new(store_attribute, coder)
106
109
  store_accessor(store_attribute, options[:accessors], **options.slice(:prefix, :suffix)) if options.has_key? :accessors
107
110
  end
108
111
 
@@ -160,19 +163,19 @@ module ActiveRecord
160
163
 
161
164
  define_method("saved_change_to_#{accessor_key}?") do
162
165
  return false unless saved_change_to_attribute?(store_attribute)
163
- prev_store, new_store = saved_change_to_attribute(store_attribute)
166
+ prev_store, new_store = saved_changes[store_attribute]
164
167
  prev_store&.dig(key) != new_store&.dig(key)
165
168
  end
166
169
 
167
170
  define_method("saved_change_to_#{accessor_key}") do
168
171
  return unless saved_change_to_attribute?(store_attribute)
169
- prev_store, new_store = saved_change_to_attribute(store_attribute)
172
+ prev_store, new_store = saved_changes[store_attribute]
170
173
  [prev_store&.dig(key), new_store&.dig(key)]
171
174
  end
172
175
 
173
176
  define_method("#{accessor_key}_before_last_save") do
174
177
  return unless saved_change_to_attribute?(store_attribute)
175
- prev_store, _new_store = saved_change_to_attribute(store_attribute)
178
+ prev_store, _new_store = saved_changes[store_attribute]
176
179
  prev_store&.dig(key)
177
180
  end
178
181
  end
@@ -225,10 +228,7 @@ module ActiveRecord
225
228
 
226
229
  def self.write(object, attribute, key, value)
227
230
  prepare(object, attribute)
228
- if value != read(object, attribute, key)
229
- object.public_send :"#{attribute}_will_change!"
230
- object.public_send(attribute)[key] = value
231
- end
231
+ object.public_send(attribute)[key] = value if value != read(object, attribute, key)
232
232
  end
233
233
 
234
234
  def self.prepare(object, attribute)
@@ -268,7 +268,7 @@ module ActiveRecord
268
268
  end
269
269
 
270
270
  def dump(obj)
271
- @coder.dump self.class.as_indifferent_hash(obj)
271
+ @coder.dump as_regular_hash(obj)
272
272
  end
273
273
 
274
274
  def load(yaml)
@@ -285,6 +285,11 @@ module ActiveRecord
285
285
  ActiveSupport::HashWithIndifferentAccess.new
286
286
  end
287
287
  end
288
+
289
+ private
290
+ def as_regular_hash(obj)
291
+ obj.respond_to?(:to_hash) ? obj.to_hash : {}
292
+ end
288
293
  end
289
294
  end
290
295
  end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecord
4
+ # = Active Record \Suppressor
5
+ #
4
6
  # ActiveRecord::Suppressor prevents the receiver from being saved during
5
7
  # a given block.
6
8
  #
@@ -32,7 +34,7 @@ module ActiveRecord
32
34
 
33
35
  class << self
34
36
  def registry # :nodoc:
35
- ActiveSupport::IsolatedExecutionState[:active_record_suppresor_registry] ||= {}
37
+ ActiveSupport::IsolatedExecutionState[:active_record_suppressor_registry] ||= {}
36
38
  end
37
39
  end
38
40
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  module ActiveRecord
4
4
  class TableMetadata # :nodoc:
5
- delegate :join_primary_key, :join_foreign_key, :join_foreign_type, to: :reflection
5
+ delegate :join_primary_key, :join_primary_type, :join_foreign_key, :join_foreign_type, to: :reflection
6
6
 
7
7
  def initialize(klass, arel_table, reflection = nil)
8
8
  @klass = klass
@@ -19,11 +19,11 @@ module ActiveRecord
19
19
  end
20
20
 
21
21
  def has_column?(column_name)
22
- klass&.columns_hash.key?(column_name)
22
+ klass&.columns_hash&.key?(column_name)
23
23
  end
24
24
 
25
25
  def associated_with?(table_name)
26
- klass&._reflect_on_association(table_name) || klass&._reflect_on_association(table_name.singularize)
26
+ klass&._reflect_on_association(table_name)
27
27
  end
28
28
 
29
29
  def associated_table(table_name)
@@ -54,6 +54,10 @@ module ActiveRecord
54
54
  reflection&.polymorphic?
55
55
  end
56
56
 
57
+ def polymorphic_name_association
58
+ reflection&.polymorphic_name
59
+ end
60
+
57
61
  def through_association?
58
62
  reflection&.through_reflection?
59
63
  end