activerecord 6.0.3.4 → 6.1.2

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 (245) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +891 -695
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +3 -3
  5. data/lib/active_record.rb +7 -14
  6. data/lib/active_record/aggregations.rb +5 -5
  7. data/lib/active_record/association_relation.rb +30 -12
  8. data/lib/active_record/associations.rb +118 -11
  9. data/lib/active_record/associations/alias_tracker.rb +19 -15
  10. data/lib/active_record/associations/association.rb +44 -28
  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 -1
  18. data/lib/active_record/associations/builder/has_many.rb +6 -2
  19. data/lib/active_record/associations/builder/has_one.rb +11 -14
  20. data/lib/active_record/associations/builder/singular_association.rb +1 -1
  21. data/lib/active_record/associations/collection_association.rb +19 -6
  22. data/lib/active_record/associations/collection_proxy.rb +13 -5
  23. data/lib/active_record/associations/foreign_association.rb +13 -0
  24. data/lib/active_record/associations/has_many_association.rb +24 -2
  25. data/lib/active_record/associations/has_many_through_association.rb +10 -4
  26. data/lib/active_record/associations/has_one_association.rb +15 -1
  27. data/lib/active_record/associations/join_dependency.rb +72 -50
  28. data/lib/active_record/associations/join_dependency/join_association.rb +39 -16
  29. data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
  30. data/lib/active_record/associations/preloader.rb +11 -5
  31. data/lib/active_record/associations/preloader/association.rb +51 -25
  32. data/lib/active_record/associations/preloader/through_association.rb +2 -2
  33. data/lib/active_record/associations/singular_association.rb +1 -1
  34. data/lib/active_record/associations/through_association.rb +1 -1
  35. data/lib/active_record/attribute_assignment.rb +10 -8
  36. data/lib/active_record/attribute_methods.rb +64 -54
  37. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -9
  38. data/lib/active_record/attribute_methods/dirty.rb +1 -11
  39. data/lib/active_record/attribute_methods/primary_key.rb +6 -2
  40. data/lib/active_record/attribute_methods/query.rb +3 -6
  41. data/lib/active_record/attribute_methods/read.rb +8 -11
  42. data/lib/active_record/attribute_methods/serialization.rb +11 -5
  43. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -13
  44. data/lib/active_record/attribute_methods/write.rb +12 -20
  45. data/lib/active_record/attributes.rb +33 -8
  46. data/lib/active_record/autosave_association.rb +57 -40
  47. data/lib/active_record/base.rb +2 -14
  48. data/lib/active_record/callbacks.rb +152 -22
  49. data/lib/active_record/coders/yaml_column.rb +1 -1
  50. data/lib/active_record/connection_adapters.rb +50 -0
  51. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +191 -134
  52. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
  53. data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -22
  54. data/lib/active_record/connection_adapters/abstract/query_cache.rb +3 -8
  55. data/lib/active_record/connection_adapters/abstract/quoting.rb +34 -34
  56. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  57. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -116
  58. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +116 -27
  59. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
  60. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +228 -83
  61. data/lib/active_record/connection_adapters/abstract/transaction.rb +80 -32
  62. data/lib/active_record/connection_adapters/abstract_adapter.rb +54 -72
  63. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +133 -96
  64. data/lib/active_record/connection_adapters/column.rb +15 -1
  65. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  66. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
  67. data/lib/active_record/connection_adapters/mysql/database_statements.rb +23 -25
  68. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -1
  69. data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
  70. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +32 -6
  71. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
  72. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +5 -2
  73. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +11 -7
  74. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
  75. data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -12
  76. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  77. data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
  78. data/lib/active_record/connection_adapters/postgresql/column.rb +24 -1
  79. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +13 -54
  80. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  81. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  82. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
  83. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
  84. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -2
  86. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +24 -5
  89. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -1
  90. data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
  91. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
  92. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +5 -1
  93. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +61 -29
  94. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
  95. data/lib/active_record/connection_adapters/postgresql_adapter.rb +73 -58
  96. data/lib/active_record/connection_adapters/schema_cache.rb +98 -15
  97. data/lib/active_record/connection_adapters/sql_type_metadata.rb +10 -0
  98. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +31 -6
  99. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -1
  100. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  101. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +37 -4
  102. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +49 -50
  103. data/lib/active_record/connection_handling.rb +218 -71
  104. data/lib/active_record/core.rb +245 -61
  105. data/lib/active_record/database_configurations.rb +124 -85
  106. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  107. data/lib/active_record/database_configurations/database_config.rb +52 -9
  108. data/lib/active_record/database_configurations/hash_config.rb +54 -8
  109. data/lib/active_record/database_configurations/url_config.rb +15 -40
  110. data/lib/active_record/delegated_type.rb +209 -0
  111. data/lib/active_record/destroy_association_async_job.rb +36 -0
  112. data/lib/active_record/enum.rb +82 -38
  113. data/lib/active_record/errors.rb +47 -12
  114. data/lib/active_record/explain.rb +9 -4
  115. data/lib/active_record/explain_subscriber.rb +1 -1
  116. data/lib/active_record/fixture_set/file.rb +10 -17
  117. data/lib/active_record/fixture_set/model_metadata.rb +1 -2
  118. data/lib/active_record/fixture_set/render_context.rb +1 -1
  119. data/lib/active_record/fixture_set/table_row.rb +2 -2
  120. data/lib/active_record/fixtures.rb +58 -9
  121. data/lib/active_record/gem_version.rb +3 -3
  122. data/lib/active_record/inheritance.rb +40 -18
  123. data/lib/active_record/insert_all.rb +35 -6
  124. data/lib/active_record/integration.rb +3 -5
  125. data/lib/active_record/internal_metadata.rb +16 -7
  126. data/lib/active_record/legacy_yaml_adapter.rb +7 -3
  127. data/lib/active_record/locking/optimistic.rb +33 -17
  128. data/lib/active_record/locking/pessimistic.rb +6 -2
  129. data/lib/active_record/log_subscriber.rb +27 -8
  130. data/lib/active_record/middleware/database_selector.rb +4 -1
  131. data/lib/active_record/middleware/database_selector/resolver.rb +5 -0
  132. data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
  133. data/lib/active_record/migration.rb +113 -83
  134. data/lib/active_record/migration/command_recorder.rb +47 -27
  135. data/lib/active_record/migration/compatibility.rb +68 -17
  136. data/lib/active_record/model_schema.rb +117 -13
  137. data/lib/active_record/nested_attributes.rb +2 -3
  138. data/lib/active_record/no_touching.rb +1 -1
  139. data/lib/active_record/persistence.rb +50 -45
  140. data/lib/active_record/query_cache.rb +15 -5
  141. data/lib/active_record/querying.rb +11 -6
  142. data/lib/active_record/railtie.rb +64 -44
  143. data/lib/active_record/railties/console_sandbox.rb +2 -4
  144. data/lib/active_record/railties/databases.rake +276 -99
  145. data/lib/active_record/readonly_attributes.rb +4 -0
  146. data/lib/active_record/reflection.rb +71 -57
  147. data/lib/active_record/relation.rb +96 -67
  148. data/lib/active_record/relation/batches.rb +38 -31
  149. data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
  150. data/lib/active_record/relation/calculations.rb +101 -44
  151. data/lib/active_record/relation/delegation.rb +2 -1
  152. data/lib/active_record/relation/finder_methods.rb +45 -15
  153. data/lib/active_record/relation/from_clause.rb +1 -1
  154. data/lib/active_record/relation/merger.rb +27 -25
  155. data/lib/active_record/relation/predicate_builder.rb +59 -38
  156. data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
  157. data/lib/active_record/relation/predicate_builder/association_query_value.rb +4 -5
  158. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -6
  159. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  160. data/lib/active_record/relation/query_methods.rb +333 -195
  161. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  162. data/lib/active_record/relation/spawn_methods.rb +8 -7
  163. data/lib/active_record/relation/where_clause.rb +104 -57
  164. data/lib/active_record/result.rb +41 -33
  165. data/lib/active_record/runtime_registry.rb +2 -2
  166. data/lib/active_record/sanitization.rb +6 -17
  167. data/lib/active_record/schema_dumper.rb +34 -4
  168. data/lib/active_record/schema_migration.rb +2 -8
  169. data/lib/active_record/scoping/named.rb +6 -17
  170. data/lib/active_record/secure_token.rb +16 -8
  171. data/lib/active_record/serialization.rb +5 -3
  172. data/lib/active_record/signed_id.rb +116 -0
  173. data/lib/active_record/statement_cache.rb +20 -4
  174. data/lib/active_record/store.rb +2 -2
  175. data/lib/active_record/suppressor.rb +2 -2
  176. data/lib/active_record/table_metadata.rb +42 -51
  177. data/lib/active_record/tasks/database_tasks.rb +140 -113
  178. data/lib/active_record/tasks/mysql_database_tasks.rb +34 -35
  179. data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -26
  180. data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -9
  181. data/lib/active_record/test_databases.rb +5 -4
  182. data/lib/active_record/test_fixtures.rb +37 -16
  183. data/lib/active_record/timestamp.rb +4 -6
  184. data/lib/active_record/touch_later.rb +21 -21
  185. data/lib/active_record/transactions.rb +19 -66
  186. data/lib/active_record/type.rb +8 -1
  187. data/lib/active_record/type/serialized.rb +6 -2
  188. data/lib/active_record/type/time.rb +10 -0
  189. data/lib/active_record/type_caster/connection.rb +0 -1
  190. data/lib/active_record/type_caster/map.rb +8 -5
  191. data/lib/active_record/validations.rb +1 -0
  192. data/lib/active_record/validations/numericality.rb +35 -0
  193. data/lib/active_record/validations/uniqueness.rb +24 -4
  194. data/lib/arel.rb +5 -13
  195. data/lib/arel/attributes/attribute.rb +4 -0
  196. data/lib/arel/collectors/bind.rb +5 -0
  197. data/lib/arel/collectors/composite.rb +8 -0
  198. data/lib/arel/collectors/sql_string.rb +7 -0
  199. data/lib/arel/collectors/substitute_binds.rb +7 -0
  200. data/lib/arel/nodes.rb +3 -1
  201. data/lib/arel/nodes/binary.rb +82 -8
  202. data/lib/arel/nodes/bind_param.rb +8 -0
  203. data/lib/arel/nodes/casted.rb +21 -9
  204. data/lib/arel/nodes/equality.rb +6 -9
  205. data/lib/arel/nodes/grouping.rb +3 -0
  206. data/lib/arel/nodes/homogeneous_in.rb +72 -0
  207. data/lib/arel/nodes/in.rb +8 -1
  208. data/lib/arel/nodes/infix_operation.rb +13 -1
  209. data/lib/arel/nodes/join_source.rb +1 -1
  210. data/lib/arel/nodes/node.rb +7 -6
  211. data/lib/arel/nodes/ordering.rb +27 -0
  212. data/lib/arel/nodes/sql_literal.rb +3 -0
  213. data/lib/arel/nodes/table_alias.rb +7 -3
  214. data/lib/arel/nodes/unary.rb +0 -1
  215. data/lib/arel/predications.rb +12 -18
  216. data/lib/arel/select_manager.rb +1 -2
  217. data/lib/arel/table.rb +13 -5
  218. data/lib/arel/visitors.rb +0 -7
  219. data/lib/arel/visitors/dot.rb +14 -2
  220. data/lib/arel/visitors/mysql.rb +11 -1
  221. data/lib/arel/visitors/postgresql.rb +15 -4
  222. data/lib/arel/visitors/to_sql.rb +89 -78
  223. data/lib/rails/generators/active_record/migration.rb +6 -1
  224. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
  225. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
  226. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +3 -3
  227. data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
  228. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  229. metadata +25 -26
  230. data/lib/active_record/advisory_lock_base.rb +0 -18
  231. data/lib/active_record/attribute_decorators.rb +0 -88
  232. data/lib/active_record/connection_adapters/connection_specification.rb +0 -296
  233. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
  234. data/lib/active_record/define_callbacks.rb +0 -22
  235. data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
  236. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
  237. data/lib/active_record/relation/where_clause_factory.rb +0 -33
  238. data/lib/arel/attributes.rb +0 -22
  239. data/lib/arel/visitors/depth_first.rb +0 -203
  240. data/lib/arel/visitors/ibm_db.rb +0 -34
  241. data/lib/arel/visitors/informix.rb +0 -62
  242. data/lib/arel/visitors/mssql.rb +0 -156
  243. data/lib/arel/visitors/oracle.rb +0 -158
  244. data/lib/arel/visitors/oracle12.rb +0 -65
  245. data/lib/arel/visitors/where_sql.rb +0 -22
@@ -7,6 +7,10 @@ module ActiveRecord
7
7
  class ActiveRecordError < StandardError
8
8
  end
9
9
 
10
+ # Raised when trying to use a feature in Active Record which requires Active Job but the gem is not present.
11
+ class ActiveJobRequiredError < ActiveRecordError
12
+ end
13
+
10
14
  # Raised when the single-table inheritance mechanism fails to locate the subclass
11
15
  # (for example due to improper usage of column that
12
16
  # {ActiveRecord::Base.inheritance_column}[rdoc-ref:ModelSchema::ClassMethods#inheritance_column]
@@ -38,6 +42,10 @@ module ActiveRecord
38
42
  class AdapterNotSpecified < ActiveRecordError
39
43
  end
40
44
 
45
+ # Raised when a model makes a query but it has not specified an associated table.
46
+ class TableNotSpecified < ActiveRecordError
47
+ end
48
+
41
49
  # Raised when Active Record cannot find database adapter specified in
42
50
  # +config/database.yml+ or programmatically.
43
51
  class AdapterNotFound < ActiveRecordError
@@ -49,6 +57,19 @@ module ActiveRecord
49
57
  class ConnectionNotEstablished < ActiveRecordError
50
58
  end
51
59
 
60
+ # Raised when a connection could not be obtained within the connection
61
+ # acquisition timeout period: because max connections in pool
62
+ # are in use.
63
+ class ConnectionTimeoutError < ConnectionNotEstablished
64
+ end
65
+
66
+ # Raised when a pool was unable to get ahold of all its connections
67
+ # to perform a "group" action such as
68
+ # {ActiveRecord::Base.connection_pool.disconnect!}[rdoc-ref:ConnectionAdapters::ConnectionPool#disconnect!]
69
+ # or {ActiveRecord::Base.clear_reloadable_connections!}[rdoc-ref:ConnectionAdapters::ConnectionHandler#clear_reloadable_connections!].
70
+ class ExclusiveConnectionTimeoutError < ConnectionTimeoutError
71
+ end
72
+
52
73
  # Raised when a write to the database is attempted on a read only connection.
53
74
  class ReadOnlyError < ActiveRecordError
54
75
  end
@@ -102,7 +123,7 @@ module ActiveRecord
102
123
  # Wraps the underlying database error as +cause+.
103
124
  class StatementInvalid < ActiveRecordError
104
125
  def initialize(message = nil, sql: nil, binds: nil)
105
- super(message || $!.try(:message))
126
+ super(message || $!&.message)
106
127
  @sql = sql
107
128
  @binds = binds
108
129
  end
@@ -169,9 +190,9 @@ module ActiveRecord
169
190
  class RangeError < StatementInvalid
170
191
  end
171
192
 
172
- # Raised when number of bind variables in statement given to +:condition+ key
173
- # (for example, when using {ActiveRecord::Base.find}[rdoc-ref:FinderMethods#find] method)
174
- # does not match number of expected values supplied.
193
+ # Raised when the number of placeholders in an SQL fragment passed to
194
+ # {ActiveRecord::Base.where}[rdoc-ref:QueryMethods#where]
195
+ # does not match the number of values supplied.
175
196
  #
176
197
  # For example, when there are two placeholders with only one value supplied:
177
198
  #
@@ -183,6 +204,10 @@ module ActiveRecord
183
204
  class NoDatabaseError < StatementInvalid
184
205
  end
185
206
 
207
+ # Raised when creating a database if it exists.
208
+ class DatabaseAlreadyExists < StatementInvalid
209
+ end
210
+
186
211
  # Raised when PostgreSQL returns 'cached plan must not change result type' and
187
212
  # we cannot retry gracefully (e.g. inside a transaction)
188
213
  class PreparedStatementCacheExpired < StatementInvalid
@@ -220,6 +245,10 @@ module ActiveRecord
220
245
  class ReadOnlyRecord < ActiveRecordError
221
246
  end
222
247
 
248
+ # Raised on attempt to lazily load records that are marked as strict loading.
249
+ class StrictLoadingViolationError < ActiveRecordError
250
+ end
251
+
223
252
  # {ActiveRecord::Base.transaction}[rdoc-ref:Transactions::ClassMethods#transaction]
224
253
  # uses this exception to distinguish a deliberate rollback from other exceptional situations.
225
254
  # Normally, raising an exception will cause the
@@ -330,7 +359,7 @@ module ActiveRecord
330
359
  # See the following:
331
360
  #
332
361
  # * https://www.postgresql.org/docs/current/static/transaction-iso.html
333
- # * https://dev.mysql.com/doc/refman/5.7/en/error-messages-server.html#error_er_lock_deadlock
362
+ # * https://dev.mysql.com/doc/mysql-errors/en/server-error-reference.html#error_er_lock_deadlock
334
363
  class TransactionRollbackError < StatementInvalid
335
364
  end
336
365
 
@@ -349,30 +378,36 @@ module ActiveRecord
349
378
  class IrreversibleOrderError < ActiveRecordError
350
379
  end
351
380
 
381
+ # Superclass for errors that have been aborted (either by client or server).
382
+ class QueryAborted < StatementInvalid
383
+ end
384
+
352
385
  # LockWaitTimeout will be raised when lock wait timeout exceeded.
353
386
  class LockWaitTimeout < StatementInvalid
354
387
  end
355
388
 
356
389
  # StatementTimeout will be raised when statement timeout exceeded.
357
- class StatementTimeout < StatementInvalid
390
+ class StatementTimeout < QueryAborted
358
391
  end
359
392
 
360
393
  # QueryCanceled will be raised when canceling statement due to user request.
361
- class QueryCanceled < StatementInvalid
394
+ class QueryCanceled < QueryAborted
395
+ end
396
+
397
+ # AdapterTimeout will be raised when database clients times out while waiting from the server.
398
+ class AdapterTimeout < QueryAborted
362
399
  end
363
400
 
364
401
  # UnknownAttributeReference is raised when an unknown and potentially unsafe
365
- # value is passed to a query method when allow_unsafe_raw_sql is set to
366
- # :disabled. For example, passing a non column name value to a relation's
367
- # #order method might cause this exception.
402
+ # value is passed to a query method. For example, passing a non column name
403
+ # value to a relation's #order method might cause this exception.
368
404
  #
369
405
  # When working around this exception, caution should be taken to avoid SQL
370
406
  # injection vulnerabilities when passing user-provided values to query
371
407
  # methods. Known-safe values can be passed to query methods by wrapping them
372
408
  # in Arel.sql.
373
409
  #
374
- # For example, with allow_unsafe_raw_sql set to :disabled, the following
375
- # code would raise this exception:
410
+ # For example, the following code would raise this exception:
376
411
  #
377
412
  # Post.order("length(title)").first
378
413
  #
@@ -37,13 +37,18 @@ module ActiveRecord
37
37
 
38
38
  private
39
39
  def render_bind(attr)
40
- value = if attr.type.binary? && attr.value
41
- "<#{attr.value_for_database.to_s.bytesize} bytes of binary data>"
40
+ if ActiveModel::Attribute === attr
41
+ value = if attr.type.binary? && attr.value
42
+ "<#{attr.value_for_database.to_s.bytesize} bytes of binary data>"
43
+ else
44
+ connection.type_cast(attr.value_for_database)
45
+ end
42
46
  else
43
- connection.type_cast(attr.value_for_database)
47
+ value = connection.type_cast(attr)
48
+ attr = nil
44
49
  end
45
50
 
46
- [attr.name, value]
51
+ [attr&.name, value]
47
52
  end
48
53
  end
49
54
  end
@@ -26,7 +26,7 @@ module ActiveRecord
26
26
  payload[:exception] ||
27
27
  payload[:cached] ||
28
28
  IGNORED_PAYLOADS.include?(payload[:name]) ||
29
- payload[:sql] !~ EXPLAINED_SQLS
29
+ !payload[:sql].match?(EXPLAINED_SQLS)
30
30
  end
31
31
 
32
32
  ActiveSupport::Notifications.subscribe("sql.active_record", new)
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "erb"
4
- require "yaml"
3
+ require "active_support/configuration_file"
5
4
 
6
5
  module ActiveRecord
7
6
  class FixtureSet
@@ -29,6 +28,10 @@ module ActiveRecord
29
28
  config_row["model_class"]
30
29
  end
31
30
 
31
+ def ignored_fixtures
32
+ config_row["ignore"]
33
+ end
34
+
32
35
  private
33
36
  def rows
34
37
  @rows ||= raw_rows.reject { |fixture_name, _| fixture_name == "_fixture" }
@@ -40,31 +43,21 @@ module ActiveRecord
40
43
  if row
41
44
  row.last
42
45
  else
43
- { 'model_class': nil }
46
+ { 'model_class': nil, 'ignore': nil }
44
47
  end
45
48
  end
46
49
  end
47
50
 
48
51
  def raw_rows
49
52
  @raw_rows ||= begin
50
- data = YAML.load(render(IO.read(@file)))
53
+ data = ActiveSupport::ConfigurationFile.parse(@file, context:
54
+ ActiveRecord::FixtureSet::RenderContext.create_subclass.new.get_binding)
51
55
  data ? validate(data).to_a : []
52
- rescue ArgumentError, Psych::SyntaxError => error
53
- raise Fixture::FormatError, "a YAML error occurred parsing #{@file}. Please note that YAML must be consistently indented using spaces. Tabs are not allowed. Please have a look at http://www.yaml.org/faq.html\nThe exact error was:\n #{error.class}: #{error}", error.backtrace
56
+ rescue RuntimeError => error
57
+ raise Fixture::FormatError, error.message
54
58
  end
55
59
  end
56
60
 
57
- def prepare_erb(content)
58
- erb = ERB.new(content)
59
- erb.filename = @file
60
- erb
61
- end
62
-
63
- def render(content)
64
- context = ActiveRecord::FixtureSet::RenderContext.create_subclass.new
65
- prepare_erb(content).result(context.get_binding)
66
- end
67
-
68
61
  # Validate our unmarshalled data.
69
62
  def validate(data)
70
63
  unless Hash === data || YAML::Omap === data
@@ -21,8 +21,7 @@ module ActiveRecord
21
21
  end
22
22
 
23
23
  def timestamp_column_names
24
- @timestamp_column_names ||=
25
- %w(created_at created_on updated_at updated_on) & @model_class.column_names
24
+ @model_class.all_timestamp_attributes_in_model
26
25
  end
27
26
 
28
27
  def inheritance_column_name
@@ -10,7 +10,7 @@ class ActiveRecord::FixtureSet::RenderContext # :nodoc:
10
10
  end
11
11
 
12
12
  def binary(path)
13
- %(!!binary "#{Base64.strict_encode64(File.read(path))}")
13
+ %(!!binary "#{Base64.strict_encode64(File.binread(path))}")
14
14
  end
15
15
  end
16
16
  end
@@ -112,12 +112,12 @@ module ActiveRecord
112
112
  case association.macro
113
113
  when :belongs_to
114
114
  # Do not replace association name with association foreign key if they are named the same
115
- fk_name = (association.options[:foreign_key] || "#{association.name}_id").to_s
115
+ fk_name = association.join_foreign_key
116
116
 
117
117
  if association.name.to_s != fk_name && value = @row.delete(association.name.to_s)
118
118
  if association.polymorphic? && value.sub!(/\s*\(([^\)]*)\)\s*$/, "")
119
119
  # support polymorphic belongs_to as "label (Type)"
120
- @row[association.foreign_type] = $1
120
+ @row[association.join_foreign_type] = $1
121
121
  end
122
122
 
123
123
  fk_type = reflection_class.type_for_attribute(fk_name).type
@@ -10,7 +10,6 @@ require "active_record/fixture_set/file"
10
10
  require "active_record/fixture_set/render_context"
11
11
  require "active_record/fixture_set/table_rows"
12
12
  require "active_record/test_fixtures"
13
- require "active_record/errors"
14
13
 
15
14
  module ActiveRecord
16
15
  class FixtureClassNotFound < ActiveRecord::ActiveRecordError #:nodoc:
@@ -41,7 +40,7 @@ module ActiveRecord
41
40
  # separated by a blank line for your viewing pleasure.
42
41
  #
43
42
  # Note: Fixtures are unordered. If you want ordered fixtures, use the omap YAML type.
44
- # See http://yaml.org/type/omap.html
43
+ # See https://yaml.org/type/omap.html
45
44
  # for the specification. You will need ordered fixtures when you have foreign key constraints
46
45
  # on keys in the same table. This is commonly needed for tree structures. Example:
47
46
  #
@@ -60,7 +59,7 @@ module ActiveRecord
60
59
  # Since fixtures are a testing construct, we use them in our unit and functional tests. There
61
60
  # are two ways to use the fixtures, but first let's take a look at a sample unit test:
62
61
  #
63
- # require 'test_helper'
62
+ # require "test_helper"
64
63
  #
65
64
  # class WebSiteTest < ActiveSupport::TestCase
66
65
  # test "web_site_count" do
@@ -182,7 +181,7 @@ module ActiveRecord
182
181
  # end
183
182
  # end
184
183
  #
185
- # If you preload your test database with all fixture data (probably by running `rails db:fixtures:load`)
184
+ # If you preload your test database with all fixture data (probably by running `bin/rails db:fixtures:load`)
186
185
  # and use transactional tests, then you may omit all fixtures declarations in your test cases since
187
186
  # all the data's already there and every case rolls back its changes.
188
187
  #
@@ -420,12 +419,35 @@ module ActiveRecord
420
419
  #
421
420
  # Any fixture labeled "DEFAULTS" is safely ignored.
422
421
  #
422
+ # Besides using "DEFAULTS", you can also specify what fixtures will
423
+ # be ignored by setting "ignore" in "_fixture" section.
424
+ #
425
+ # # users.yml
426
+ # _fixture:
427
+ # ignore:
428
+ # - base
429
+ # # or use "ignore: base" when there is only one fixture needs to be ignored.
430
+ #
431
+ # base: &base
432
+ # admin: false
433
+ # introduction: "This is a default description"
434
+ #
435
+ # admin:
436
+ # <<: *base
437
+ # admin: true
438
+ #
439
+ # visitor:
440
+ # <<: *base
441
+ #
442
+ # In the above example, 'base' will be ignored when creating fixtures.
443
+ # This can be used for common attributes inheriting.
444
+ #
423
445
  # == Configure the fixture model class
424
446
  #
425
447
  # It's possible to set the fixture's model class directly in the YAML file.
426
448
  # This is helpful when fixtures are loaded outside tests and
427
449
  # +set_fixture_class+ is not available (e.g.
428
- # when running <tt>rails db:fixtures:load</tt>).
450
+ # when running <tt>bin/rails db:fixtures:load</tt>).
429
451
  #
430
452
  # _fixture:
431
453
  # model_class: User
@@ -563,6 +585,14 @@ module ActiveRecord
563
585
  end
564
586
  end
565
587
 
588
+ def signed_global_id(fixture_set_name, label, column_type: :integer, **options)
589
+ identifier = identify(label, column_type)
590
+ model_name = default_fixture_model_name(fixture_set_name)
591
+ uri = URI::GID.build([GlobalID.app, model_name, identifier, {}])
592
+
593
+ SignedGlobalID.new(uri, **options)
594
+ end
595
+
566
596
  # Superclass for the evaluation contexts used by ERB fixtures.
567
597
  def context_class
568
598
  @context_class ||= Class.new
@@ -619,7 +649,7 @@ module ActiveRecord
619
649
  end
620
650
  end
621
651
 
622
- attr_reader :table_name, :name, :fixtures, :model_class, :config
652
+ attr_reader :table_name, :name, :fixtures, :model_class, :ignored_fixtures, :config
623
653
 
624
654
  def initialize(_, name, class_name, path, config = ActiveRecord::Base)
625
655
  @name = name
@@ -652,8 +682,8 @@ module ActiveRecord
652
682
  # Returns a hash of rows to be inserted. The key is the table, the value is
653
683
  # a list of rows to insert to that table.
654
684
  def table_rows
655
- # allow a standard key to be used for doing defaults in YAML
656
- fixtures.delete("DEFAULTS")
685
+ # allow specifying fixtures to be ignored by setting `ignore` in `_fixture` section
686
+ fixtures.except!(*ignored_fixtures)
657
687
 
658
688
  TableRows.new(
659
689
  table_name,
@@ -672,6 +702,21 @@ module ActiveRecord
672
702
  end
673
703
  end
674
704
 
705
+ def ignored_fixtures=(base)
706
+ @ignored_fixtures =
707
+ case base
708
+ when Array
709
+ base
710
+ when String
711
+ [base]
712
+ else
713
+ []
714
+ end
715
+
716
+ @ignored_fixtures << "DEFAULTS" unless @ignored_fixtures.include?("DEFAULTS")
717
+ @ignored_fixtures.compact
718
+ end
719
+
675
720
  # Loads the fixtures from the YAML file at +path+.
676
721
  # If the file sets the +model_class+ and current instance value is not set,
677
722
  # it uses the file value.
@@ -683,6 +728,7 @@ module ActiveRecord
683
728
  yaml_files.each_with_object({}) do |file, fixtures|
684
729
  FixtureSet::File.open(file) do |fh|
685
730
  self.model_class ||= fh.model_class if fh.model_class
731
+ self.ignored_fixtures ||= fh.ignored_fixtures
686
732
  fh.each do |fixture_name, row|
687
733
  fixtures[fixture_name] = ActiveRecord::Fixture.new(row, model_class)
688
734
  end
@@ -727,9 +773,12 @@ module ActiveRecord
727
773
 
728
774
  def find
729
775
  raise FixtureClassNotFound, "No class attached to find." unless model_class
730
- model_class.unscoped do
776
+ object = model_class.unscoped do
731
777
  model_class.find(fixture[model_class.primary_key])
732
778
  end
779
+ # Fixtures can't be eagerly loaded
780
+ object.instance_variable_set(:@strict_loading, false)
781
+ object
733
782
  end
734
783
  end
735
784
  end
@@ -8,9 +8,9 @@ module ActiveRecord
8
8
 
9
9
  module VERSION
10
10
  MAJOR = 6
11
- MINOR = 0
12
- TINY = 3
13
- PRE = "4"
11
+ MINOR = 1
12
+ TINY = 2
13
+ PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -38,6 +38,8 @@ module ActiveRecord
38
38
  extend ActiveSupport::Concern
39
39
 
40
40
  included do
41
+ class_attribute :store_full_class_name, instance_writer: false, default: true
42
+
41
43
  # Determines whether to store the full constant name including namespace when using STI.
42
44
  # This is true, by default.
43
45
  class_attribute :store_full_sti_class, instance_writer: false, default: true
@@ -52,7 +54,7 @@ module ActiveRecord
52
54
  raise NotImplementedError, "#{self} is an abstract class and cannot be instantiated."
53
55
  end
54
56
 
55
- if has_attribute?(inheritance_column)
57
+ if _has_attribute?(inheritance_column)
56
58
  subclass = subclass_from_attributes(attributes)
57
59
 
58
60
  if subclass.nil? && scope_attributes = current_scope&.scope_for_create
@@ -162,12 +164,42 @@ module ActiveRecord
162
164
  defined?(@abstract_class) && @abstract_class == true
163
165
  end
164
166
 
167
+ # Returns the value to be stored in the inheritance column for STI.
165
168
  def sti_name
166
- store_full_sti_class ? name : name.demodulize
169
+ store_full_sti_class && store_full_class_name ? name : name.demodulize
170
+ end
171
+
172
+ # Returns the class for the provided +type_name+.
173
+ #
174
+ # It is used to find the class correspondent to the value stored in the inheritance column.
175
+ def sti_class_for(type_name)
176
+ if store_full_sti_class && store_full_class_name
177
+ ActiveSupport::Dependencies.constantize(type_name)
178
+ else
179
+ compute_type(type_name)
180
+ end
181
+ rescue NameError
182
+ raise SubclassNotFound,
183
+ "The single-table inheritance mechanism failed to locate the subclass: '#{type_name}'. " \
184
+ "This error is raised because the column '#{inheritance_column}' is reserved for storing the class in case of inheritance. " \
185
+ "Please rename this column if you didn't intend it to be used for storing the inheritance class " \
186
+ "or overwrite #{name}.inheritance_column to use another column for that information."
167
187
  end
168
188
 
189
+ # Returns the value to be stored in the polymorphic type column for Polymorphic Associations.
169
190
  def polymorphic_name
170
- base_class.name
191
+ store_full_class_name ? base_class.name : base_class.name.demodulize
192
+ end
193
+
194
+ # Returns the class for the provided +name+.
195
+ #
196
+ # It is used to find the class correspondent to the value stored in the polymorphic type column.
197
+ def polymorphic_class_for(name)
198
+ if store_full_class_name
199
+ ActiveSupport::Dependencies.constantize(name)
200
+ else
201
+ compute_type(name)
202
+ end
171
203
  end
172
204
 
173
205
  def inherited(subclass)
@@ -219,32 +251,22 @@ module ActiveRecord
219
251
  end
220
252
 
221
253
  def using_single_table_inheritance?(record)
222
- record[inheritance_column].present? && has_attribute?(inheritance_column)
254
+ record[inheritance_column].present? && _has_attribute?(inheritance_column)
223
255
  end
224
256
 
225
257
  def find_sti_class(type_name)
226
258
  type_name = base_class.type_for_attribute(inheritance_column).cast(type_name)
227
- subclass = begin
228
- if store_full_sti_class
229
- ActiveSupport::Dependencies.constantize(type_name)
230
- else
231
- compute_type(type_name)
232
- end
233
- rescue NameError
234
- raise SubclassNotFound,
235
- "The single-table inheritance mechanism failed to locate the subclass: '#{type_name}'. " \
236
- "This error is raised because the column '#{inheritance_column}' is reserved for storing the class in case of inheritance. " \
237
- "Please rename this column if you didn't intend it to be used for storing the inheritance class " \
238
- "or overwrite #{name}.inheritance_column to use another column for that information."
239
- end
259
+ subclass = sti_class_for(type_name)
260
+
240
261
  unless subclass == self || descendants.include?(subclass)
241
262
  raise SubclassNotFound, "Invalid single-table inheritance type: #{subclass.name} is not a subclass of #{name}"
242
263
  end
264
+
243
265
  subclass
244
266
  end
245
267
 
246
268
  def type_condition(table = arel_table)
247
- sti_column = arel_attribute(inheritance_column, table)
269
+ sti_column = table[inheritance_column]
248
270
  sti_names = ([self] + descendants).map(&:sti_name)
249
271
 
250
272
  predicate_builder.build(sti_column, sti_names)