activerecord 6.0.1 → 6.1.0

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 (268) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +843 -626
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +3 -3
  5. data/lib/active_record/aggregations.rb +1 -2
  6. data/lib/active_record/association_relation.rb +18 -17
  7. data/lib/active_record/associations/alias_tracker.rb +19 -16
  8. data/lib/active_record/associations/association.rb +49 -37
  9. data/lib/active_record/associations/association_scope.rb +17 -15
  10. data/lib/active_record/associations/belongs_to_association.rb +15 -5
  11. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -1
  12. data/lib/active_record/associations/builder/association.rb +9 -3
  13. data/lib/active_record/associations/builder/belongs_to.rb +10 -7
  14. data/lib/active_record/associations/builder/collection_association.rb +5 -4
  15. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +0 -3
  16. data/lib/active_record/associations/builder/has_many.rb +6 -2
  17. data/lib/active_record/associations/builder/has_one.rb +11 -14
  18. data/lib/active_record/associations/builder/singular_association.rb +1 -1
  19. data/lib/active_record/associations/collection_association.rb +25 -8
  20. data/lib/active_record/associations/collection_proxy.rb +14 -7
  21. data/lib/active_record/associations/foreign_association.rb +13 -0
  22. data/lib/active_record/associations/has_many_association.rb +24 -3
  23. data/lib/active_record/associations/has_many_through_association.rb +10 -4
  24. data/lib/active_record/associations/has_one_association.rb +15 -1
  25. data/lib/active_record/associations/join_dependency/join_association.rb +36 -14
  26. data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
  27. data/lib/active_record/associations/join_dependency.rb +73 -42
  28. data/lib/active_record/associations/preloader/association.rb +51 -25
  29. data/lib/active_record/associations/preloader/through_association.rb +2 -2
  30. data/lib/active_record/associations/preloader.rb +12 -7
  31. data/lib/active_record/associations/singular_association.rb +1 -1
  32. data/lib/active_record/associations/through_association.rb +1 -1
  33. data/lib/active_record/associations.rb +115 -12
  34. data/lib/active_record/attribute_assignment.rb +10 -9
  35. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -10
  36. data/lib/active_record/attribute_methods/dirty.rb +3 -13
  37. data/lib/active_record/attribute_methods/primary_key.rb +6 -4
  38. data/lib/active_record/attribute_methods/query.rb +3 -6
  39. data/lib/active_record/attribute_methods/read.rb +8 -12
  40. data/lib/active_record/attribute_methods/serialization.rb +11 -6
  41. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
  42. data/lib/active_record/attribute_methods/write.rb +12 -21
  43. data/lib/active_record/attribute_methods.rb +64 -54
  44. data/lib/active_record/attributes.rb +32 -8
  45. data/lib/active_record/autosave_association.rb +56 -41
  46. data/lib/active_record/base.rb +2 -14
  47. data/lib/active_record/callbacks.rb +153 -24
  48. data/lib/active_record/coders/yaml_column.rb +1 -2
  49. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +190 -136
  50. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
  51. data/lib/active_record/connection_adapters/abstract/database_statements.rb +82 -37
  52. data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -8
  53. data/lib/active_record/connection_adapters/abstract/quoting.rb +34 -34
  54. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  55. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +152 -116
  56. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +137 -52
  57. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
  58. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +263 -107
  59. data/lib/active_record/connection_adapters/abstract/transaction.rb +82 -35
  60. data/lib/active_record/connection_adapters/abstract_adapter.rb +60 -73
  61. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +136 -111
  62. data/lib/active_record/connection_adapters/column.rb +15 -1
  63. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  64. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
  65. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  66. data/lib/active_record/connection_adapters/mysql/database_statements.rb +28 -36
  67. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
  68. data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
  69. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +32 -7
  70. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
  71. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
  72. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +17 -13
  73. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
  74. data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -13
  75. data/lib/active_record/connection_adapters/pool_config.rb +63 -0
  76. data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
  77. data/lib/active_record/connection_adapters/postgresql/column.rb +24 -1
  78. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +19 -56
  79. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +0 -1
  80. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  81. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
  82. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
  83. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  84. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +0 -1
  85. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
  87. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  89. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
  90. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +24 -6
  91. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -2
  93. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  94. data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
  95. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
  96. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +7 -3
  97. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +1 -1
  98. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
  99. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +72 -54
  100. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
  101. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  102. data/lib/active_record/connection_adapters/postgresql_adapter.rb +77 -57
  103. data/lib/active_record/connection_adapters/schema_cache.rb +98 -15
  104. data/lib/active_record/connection_adapters/sql_type_metadata.rb +10 -0
  105. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +36 -12
  106. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -2
  107. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  108. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +38 -5
  109. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +57 -57
  110. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  111. data/lib/active_record/connection_adapters.rb +50 -0
  112. data/lib/active_record/connection_handling.rb +210 -87
  113. data/lib/active_record/core.rb +229 -65
  114. data/lib/active_record/counter_cache.rb +4 -1
  115. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  116. data/lib/active_record/database_configurations/database_config.rb +52 -9
  117. data/lib/active_record/database_configurations/hash_config.rb +54 -8
  118. data/lib/active_record/database_configurations/url_config.rb +15 -41
  119. data/lib/active_record/database_configurations.rb +124 -85
  120. data/lib/active_record/delegated_type.rb +209 -0
  121. data/lib/active_record/destroy_association_async_job.rb +36 -0
  122. data/lib/active_record/dynamic_matchers.rb +2 -3
  123. data/lib/active_record/enum.rb +40 -16
  124. data/lib/active_record/errors.rb +47 -12
  125. data/lib/active_record/explain.rb +9 -5
  126. data/lib/active_record/explain_subscriber.rb +1 -1
  127. data/lib/active_record/fixture_set/file.rb +10 -17
  128. data/lib/active_record/fixture_set/model_metadata.rb +1 -2
  129. data/lib/active_record/fixture_set/render_context.rb +1 -1
  130. data/lib/active_record/fixture_set/table_row.rb +2 -3
  131. data/lib/active_record/fixture_set/table_rows.rb +0 -1
  132. data/lib/active_record/fixtures.rb +54 -11
  133. data/lib/active_record/gem_version.rb +2 -2
  134. data/lib/active_record/inheritance.rb +40 -21
  135. data/lib/active_record/insert_all.rb +38 -9
  136. data/lib/active_record/integration.rb +3 -5
  137. data/lib/active_record/internal_metadata.rb +16 -7
  138. data/lib/active_record/legacy_yaml_adapter.rb +7 -3
  139. data/lib/active_record/locking/optimistic.rb +22 -17
  140. data/lib/active_record/locking/pessimistic.rb +6 -2
  141. data/lib/active_record/log_subscriber.rb +27 -9
  142. data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
  143. data/lib/active_record/middleware/database_selector/resolver.rb +6 -2
  144. data/lib/active_record/middleware/database_selector.rb +4 -2
  145. data/lib/active_record/migration/command_recorder.rb +53 -45
  146. data/lib/active_record/migration/compatibility.rb +70 -20
  147. data/lib/active_record/migration/join_table.rb +0 -1
  148. data/lib/active_record/migration.rb +114 -84
  149. data/lib/active_record/model_schema.rb +117 -15
  150. data/lib/active_record/nested_attributes.rb +2 -5
  151. data/lib/active_record/no_touching.rb +1 -1
  152. data/lib/active_record/null_relation.rb +0 -1
  153. data/lib/active_record/persistence.rb +50 -46
  154. data/lib/active_record/query_cache.rb +15 -5
  155. data/lib/active_record/querying.rb +12 -7
  156. data/lib/active_record/railtie.rb +65 -45
  157. data/lib/active_record/railties/databases.rake +267 -93
  158. data/lib/active_record/readonly_attributes.rb +4 -0
  159. data/lib/active_record/reflection.rb +77 -63
  160. data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
  161. data/lib/active_record/relation/batches.rb +38 -32
  162. data/lib/active_record/relation/calculations.rb +102 -45
  163. data/lib/active_record/relation/delegation.rb +9 -7
  164. data/lib/active_record/relation/finder_methods.rb +45 -16
  165. data/lib/active_record/relation/from_clause.rb +5 -1
  166. data/lib/active_record/relation/merger.rb +27 -26
  167. data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
  168. data/lib/active_record/relation/predicate_builder/association_query_value.rb +4 -5
  169. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +3 -3
  170. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  171. data/lib/active_record/relation/predicate_builder.rb +55 -35
  172. data/lib/active_record/relation/query_methods.rb +335 -187
  173. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  174. data/lib/active_record/relation/spawn_methods.rb +8 -8
  175. data/lib/active_record/relation/where_clause.rb +104 -58
  176. data/lib/active_record/relation.rb +108 -68
  177. data/lib/active_record/result.rb +41 -34
  178. data/lib/active_record/runtime_registry.rb +2 -2
  179. data/lib/active_record/sanitization.rb +6 -17
  180. data/lib/active_record/schema_dumper.rb +34 -4
  181. data/lib/active_record/schema_migration.rb +2 -8
  182. data/lib/active_record/scoping/default.rb +0 -1
  183. data/lib/active_record/scoping/named.rb +7 -18
  184. data/lib/active_record/scoping.rb +0 -1
  185. data/lib/active_record/secure_token.rb +16 -8
  186. data/lib/active_record/serialization.rb +5 -3
  187. data/lib/active_record/signed_id.rb +116 -0
  188. data/lib/active_record/statement_cache.rb +20 -4
  189. data/lib/active_record/store.rb +3 -3
  190. data/lib/active_record/suppressor.rb +2 -2
  191. data/lib/active_record/table_metadata.rb +39 -36
  192. data/lib/active_record/tasks/database_tasks.rb +139 -113
  193. data/lib/active_record/tasks/mysql_database_tasks.rb +34 -36
  194. data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -27
  195. data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -10
  196. data/lib/active_record/test_databases.rb +5 -4
  197. data/lib/active_record/test_fixtures.rb +38 -16
  198. data/lib/active_record/timestamp.rb +4 -7
  199. data/lib/active_record/touch_later.rb +20 -21
  200. data/lib/active_record/transactions.rb +21 -70
  201. data/lib/active_record/type/adapter_specific_registry.rb +2 -5
  202. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  203. data/lib/active_record/type/serialized.rb +6 -3
  204. data/lib/active_record/type/time.rb +10 -0
  205. data/lib/active_record/type/type_map.rb +0 -1
  206. data/lib/active_record/type/unsigned_integer.rb +0 -1
  207. data/lib/active_record/type.rb +8 -2
  208. data/lib/active_record/type_caster/connection.rb +0 -1
  209. data/lib/active_record/type_caster/map.rb +8 -5
  210. data/lib/active_record/validations/associated.rb +1 -2
  211. data/lib/active_record/validations/numericality.rb +35 -0
  212. data/lib/active_record/validations/uniqueness.rb +24 -4
  213. data/lib/active_record/validations.rb +3 -3
  214. data/lib/active_record.rb +7 -13
  215. data/lib/arel/attributes/attribute.rb +4 -0
  216. data/lib/arel/collectors/bind.rb +5 -0
  217. data/lib/arel/collectors/composite.rb +8 -0
  218. data/lib/arel/collectors/sql_string.rb +7 -0
  219. data/lib/arel/collectors/substitute_binds.rb +7 -0
  220. data/lib/arel/nodes/binary.rb +82 -8
  221. data/lib/arel/nodes/bind_param.rb +8 -0
  222. data/lib/arel/nodes/casted.rb +21 -9
  223. data/lib/arel/nodes/equality.rb +6 -9
  224. data/lib/arel/nodes/grouping.rb +3 -0
  225. data/lib/arel/nodes/homogeneous_in.rb +72 -0
  226. data/lib/arel/nodes/in.rb +8 -1
  227. data/lib/arel/nodes/infix_operation.rb +13 -1
  228. data/lib/arel/nodes/join_source.rb +1 -1
  229. data/lib/arel/nodes/node.rb +7 -6
  230. data/lib/arel/nodes/ordering.rb +27 -0
  231. data/lib/arel/nodes/sql_literal.rb +3 -0
  232. data/lib/arel/nodes/table_alias.rb +7 -3
  233. data/lib/arel/nodes/unary.rb +0 -1
  234. data/lib/arel/nodes.rb +3 -1
  235. data/lib/arel/predications.rb +17 -24
  236. data/lib/arel/select_manager.rb +1 -2
  237. data/lib/arel/table.rb +13 -5
  238. data/lib/arel/visitors/dot.rb +14 -3
  239. data/lib/arel/visitors/mysql.rb +11 -1
  240. data/lib/arel/visitors/postgresql.rb +15 -5
  241. data/lib/arel/visitors/sqlite.rb +0 -1
  242. data/lib/arel/visitors/to_sql.rb +89 -79
  243. data/lib/arel/visitors/visitor.rb +0 -1
  244. data/lib/arel/visitors.rb +0 -7
  245. data/lib/arel.rb +5 -9
  246. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  247. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
  248. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
  249. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
  250. data/lib/rails/generators/active_record/migration.rb +6 -2
  251. data/lib/rails/generators/active_record/model/model_generator.rb +38 -2
  252. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  253. metadata +26 -26
  254. data/lib/active_record/attribute_decorators.rb +0 -90
  255. data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
  256. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
  257. data/lib/active_record/define_callbacks.rb +0 -22
  258. data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
  259. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
  260. data/lib/active_record/relation/where_clause_factory.rb +0 -33
  261. data/lib/arel/attributes.rb +0 -22
  262. data/lib/arel/visitors/depth_first.rb +0 -204
  263. data/lib/arel/visitors/ibm_db.rb +0 -34
  264. data/lib/arel/visitors/informix.rb +0 -62
  265. data/lib/arel/visitors/mssql.rb +0 -157
  266. data/lib/arel/visitors/oracle.rb +0 -159
  267. data/lib/arel/visitors/oracle12.rb +0 -66
  268. data/lib/arel/visitors/where_sql.rb +0 -23
@@ -29,7 +29,6 @@ module ActiveRecord
29
29
  end
30
30
 
31
31
  private
32
-
33
32
  def build_table_rows_from(table_name, fixtures, config)
34
33
  now = config.default_timezone == :utc ? Time.now.utc : Time.now
35
34
 
@@ -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
@@ -464,7 +486,6 @@ module ActiveRecord
464
486
  end
465
487
 
466
488
  private
467
-
468
489
  def insert_class(class_names, name, klass)
469
490
  # We only want to deal with AR objects.
470
491
  if klass && klass < ActiveRecord::Base
@@ -564,13 +585,20 @@ module ActiveRecord
564
585
  end
565
586
  end
566
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
+
567
596
  # Superclass for the evaluation contexts used by ERB fixtures.
568
597
  def context_class
569
598
  @context_class ||= Class.new
570
599
  end
571
600
 
572
601
  private
573
-
574
602
  def read_and_insert(fixtures_directory, fixture_files, class_names, connection) # :nodoc:
575
603
  fixtures_map = {}
576
604
  fixture_sets = fixture_files.map do |fixture_set_name|
@@ -621,7 +649,7 @@ module ActiveRecord
621
649
  end
622
650
  end
623
651
 
624
- attr_reader :table_name, :name, :fixtures, :model_class, :config
652
+ attr_reader :table_name, :name, :fixtures, :model_class, :ignored_fixtures, :config
625
653
 
626
654
  def initialize(_, name, class_name, path, config = ActiveRecord::Base)
627
655
  @name = name
@@ -654,8 +682,8 @@ module ActiveRecord
654
682
  # Returns a hash of rows to be inserted. The key is the table, the value is
655
683
  # a list of rows to insert to that table.
656
684
  def table_rows
657
- # allow a standard key to be used for doing defaults in YAML
658
- fixtures.delete("DEFAULTS")
685
+ # allow specifying fixtures to be ignored by setting `ignore` in `_fixture` section
686
+ fixtures.except!(*ignored_fixtures)
659
687
 
660
688
  TableRows.new(
661
689
  table_name,
@@ -666,7 +694,6 @@ module ActiveRecord
666
694
  end
667
695
 
668
696
  private
669
-
670
697
  def model_class=(class_name)
671
698
  if class_name.is_a?(Class) # TODO: Should be an AR::Base type class, or any?
672
699
  @model_class = class_name
@@ -675,6 +702,21 @@ module ActiveRecord
675
702
  end
676
703
  end
677
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
+
678
720
  # Loads the fixtures from the YAML file at +path+.
679
721
  # If the file sets the +model_class+ and current instance value is not set,
680
722
  # it uses the file value.
@@ -686,6 +728,7 @@ module ActiveRecord
686
728
  yaml_files.each_with_object({}) do |file, fixtures|
687
729
  FixtureSet::File.open(file) do |fh|
688
730
  self.model_class ||= fh.model_class if fh.model_class
731
+ self.ignored_fixtures ||= fh.ignored_fixtures
689
732
  fh.each do |fixture_name, row|
690
733
  fixtures[fixture_name] = ActiveRecord::Fixture.new(row, model_class)
691
734
  end
@@ -8,8 +8,8 @@ module ActiveRecord
8
8
 
9
9
  module VERSION
10
10
  MAJOR = 6
11
- MINOR = 0
12
- TINY = 1
11
+ MINOR = 1
12
+ TINY = 0
13
13
  PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
@@ -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
167
170
  end
168
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."
187
+ end
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)
@@ -176,7 +208,6 @@ module ActiveRecord
176
208
  end
177
209
 
178
210
  protected
179
-
180
211
  # Returns the class type of the record using the current module as a prefix. So descendants of
181
212
  # MyApp::Business::Account would appear as MyApp::Business::AccountSubclass.
182
213
  def compute_type(type_name)
@@ -208,7 +239,6 @@ module ActiveRecord
208
239
  end
209
240
 
210
241
  private
211
-
212
242
  # Called by +instantiate+ to decide which class to use for a new
213
243
  # record instance. For single-table inheritance, we check the record
214
244
  # for a +type+ column and return the corresponding class.
@@ -221,32 +251,22 @@ module ActiveRecord
221
251
  end
222
252
 
223
253
  def using_single_table_inheritance?(record)
224
- record[inheritance_column].present? && has_attribute?(inheritance_column)
254
+ record[inheritance_column].present? && _has_attribute?(inheritance_column)
225
255
  end
226
256
 
227
257
  def find_sti_class(type_name)
228
258
  type_name = base_class.type_for_attribute(inheritance_column).cast(type_name)
229
- subclass = begin
230
- if store_full_sti_class
231
- ActiveSupport::Dependencies.constantize(type_name)
232
- else
233
- compute_type(type_name)
234
- end
235
- rescue NameError
236
- raise SubclassNotFound,
237
- "The single-table inheritance mechanism failed to locate the subclass: '#{type_name}'. " \
238
- "This error is raised because the column '#{inheritance_column}' is reserved for storing the class in case of inheritance. " \
239
- "Please rename this column if you didn't intend it to be used for storing the inheritance class " \
240
- "or overwrite #{name}.inheritance_column to use another column for that information."
241
- end
259
+ subclass = sti_class_for(type_name)
260
+
242
261
  unless subclass == self || descendants.include?(subclass)
243
262
  raise SubclassNotFound, "Invalid single-table inheritance type: #{subclass.name} is not a subclass of #{name}"
244
263
  end
264
+
245
265
  subclass
246
266
  end
247
267
 
248
268
  def type_condition(table = arel_table)
249
- sti_column = arel_attribute(inheritance_column, table)
269
+ sti_column = table[inheritance_column]
250
270
  sti_names = ([self] + descendants).map(&:sti_name)
251
271
 
252
272
  predicate_builder.build(sti_column, sti_names)
@@ -272,7 +292,6 @@ module ActiveRecord
272
292
  end
273
293
 
274
294
  private
275
-
276
295
  def initialize_internals_callback
277
296
  super
278
297
  ensure_proper_type
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/core_ext/enumerable"
4
+
3
5
  module ActiveRecord
4
6
  class InsertAll # :nodoc:
5
7
  attr_reader :model, :connection, :inserts, :keys
@@ -8,13 +10,19 @@ module ActiveRecord
8
10
  def initialize(model, inserts, on_duplicate:, returning: nil, unique_by: nil)
9
11
  raise ArgumentError, "Empty list of attributes passed" if inserts.blank?
10
12
 
11
- @model, @connection, @inserts, @keys = model, model.connection, inserts, inserts.first.keys.map(&:to_s).to_set
13
+ @model, @connection, @inserts, @keys = model, model.connection, inserts, inserts.first.keys.map(&:to_s)
12
14
  @on_duplicate, @returning, @unique_by = on_duplicate, returning, unique_by
13
15
 
16
+ if model.scope_attributes?
17
+ @scope_attributes = model.scope_attributes
18
+ @keys |= @scope_attributes.keys
19
+ end
20
+ @keys = @keys.to_set
21
+
14
22
  @returning = (connection.supports_insert_returning? ? primary_keys : false) if @returning.nil?
15
23
  @returning = false if @returning == []
16
24
 
17
- @unique_by = find_unique_index_for(unique_by) if unique_by
25
+ @unique_by = find_unique_index_for(unique_by)
18
26
  @on_duplicate = :skip if @on_duplicate == :update && updatable_columns.empty?
19
27
 
20
28
  ensure_valid_options_for_connection!
@@ -32,7 +40,7 @@ module ActiveRecord
32
40
  end
33
41
 
34
42
  def primary_keys
35
- Array(model.primary_key)
43
+ Array(connection.schema_cache.primary_keys(model.table_name))
36
44
  end
37
45
 
38
46
 
@@ -47,6 +55,8 @@ module ActiveRecord
47
55
  def map_key_with_value
48
56
  inserts.map do |attributes|
49
57
  attributes = attributes.stringify_keys
58
+ attributes.merge!(scope_attributes) if scope_attributes
59
+
50
60
  verify_attributes(attributes)
51
61
 
52
62
  keys.map do |key|
@@ -56,13 +66,20 @@ module ActiveRecord
56
66
  end
57
67
 
58
68
  private
69
+ attr_reader :scope_attributes
70
+
59
71
  def find_unique_index_for(unique_by)
60
- match = Array(unique_by).map(&:to_s)
72
+ return unique_by if !connection.supports_insert_conflict_target?
73
+
74
+ name_or_columns = unique_by || model.primary_key
75
+ match = Array(name_or_columns).map(&:to_s)
61
76
 
62
77
  if index = unique_indexes.find { |i| match.include?(i.name) || i.columns == match }
63
78
  index
79
+ elsif match == primary_keys
80
+ unique_by.nil? ? nil : ActiveRecord::ConnectionAdapters::IndexDefinition.new(model.table_name, "#{model.table_name}_primary_key", true, match)
64
81
  else
65
- raise ArgumentError, "No unique index found for #{unique_by}"
82
+ raise ArgumentError, "No unique index found for #{name_or_columns}"
66
83
  end
67
84
  end
68
85
 
@@ -120,7 +137,7 @@ module ActiveRecord
120
137
  end
121
138
 
122
139
  def into
123
- "INTO #{model.quoted_table_name}(#{columns_list})"
140
+ "INTO #{model.quoted_table_name} (#{columns_list})"
124
141
  end
125
142
 
126
143
  def values_list
@@ -130,7 +147,7 @@ module ActiveRecord
130
147
  connection.with_yaml_fallback(types[key].serialize(value))
131
148
  end
132
149
 
133
- Arel::InsertManager.new.create_values_list(values_list).to_sql
150
+ connection.visitor.compile(Arel::Nodes::ValuesList.new(values_list))
134
151
  end
135
152
 
136
153
  def returning
@@ -151,9 +168,21 @@ module ActiveRecord
151
168
  quote_columns(insert_all.updatable_columns)
152
169
  end
153
170
 
171
+ def touch_model_timestamps_unless(&block)
172
+ model.send(:timestamp_attributes_for_update_in_model).map do |column_name|
173
+ if touch_timestamp_attribute?(column_name)
174
+ "#{column_name}=(CASE WHEN (#{updatable_columns.map(&block).join(" AND ")}) THEN #{model.quoted_table_name}.#{column_name} ELSE CURRENT_TIMESTAMP END),"
175
+ end
176
+ end.compact.join
177
+ end
178
+
154
179
  private
155
180
  attr_reader :connection, :insert_all
156
181
 
182
+ def touch_timestamp_attribute?(column_name)
183
+ update_duplicates? && !insert_all.updatable_columns.include?(column_name)
184
+ end
185
+
157
186
  def columns_list
158
187
  format_columns(insert_all.keys)
159
188
  end
@@ -164,11 +193,11 @@ module ActiveRecord
164
193
  unknown_column = (keys - columns.keys).first
165
194
  raise UnknownAttributeError.new(model.new, unknown_column) if unknown_column
166
195
 
167
- keys.map { |key| [ key, connection.lookup_cast_type_from_column(columns[key]) ] }.to_h
196
+ keys.index_with { |key| model.type_for_attribute(key) }
168
197
  end
169
198
 
170
199
  def format_columns(columns)
171
- quote_columns(columns).join(",")
200
+ columns.respond_to?(:map) ? quote_columns(columns).join(",") : columns
172
201
  end
173
202
 
174
203
  def quote_columns(columns)
@@ -93,7 +93,7 @@ module ActiveRecord
93
93
  # cache_version, but this method can be overwritten to return something else.
94
94
  #
95
95
  # Note, this method will return nil if ActiveRecord::Base.cache_versioning is set to
96
- # +false+ (which it is by default until Rails 6.0).
96
+ # +false+.
97
97
  def cache_version
98
98
  return unless cache_versioning
99
99
 
@@ -104,10 +104,8 @@ module ActiveRecord
104
104
  elsif timestamp = updated_at
105
105
  timestamp.utc.to_s(cache_timestamp_format)
106
106
  end
107
- else
108
- if self.class.has_attribute?("updated_at")
109
- raise ActiveModel::MissingAttributeError, "missing attribute: updated_at"
110
- end
107
+ elsif self.class.has_attribute?("updated_at")
108
+ raise ActiveModel::MissingAttributeError, "missing attribute: updated_at"
111
109
  end
112
110
  end
113
111
 
@@ -6,8 +6,15 @@ require "active_record/scoping/named"
6
6
  module ActiveRecord
7
7
  # This class is used to create a table that keeps track of values and keys such
8
8
  # as which environment migrations were run in.
9
+ #
10
+ # This is enabled by default. To disable this functionality set
11
+ # `use_metadata_table` to false in your database configuration.
9
12
  class InternalMetadata < ActiveRecord::Base # :nodoc:
10
13
  class << self
14
+ def enabled?
15
+ ActiveRecord::Base.connection.use_metadata_table?
16
+ end
17
+
11
18
  def _internal?
12
19
  true
13
20
  end
@@ -21,24 +28,24 @@ module ActiveRecord
21
28
  end
22
29
 
23
30
  def []=(key, value)
31
+ return unless enabled?
32
+
24
33
  find_or_initialize_by(key: key).update!(value: value)
25
34
  end
26
35
 
27
36
  def [](key)
28
- where(key: key).pluck(:value).first
29
- end
37
+ return unless enabled?
30
38
 
31
- def table_exists?
32
- connection.table_exists?(table_name)
39
+ where(key: key).pluck(:value).first
33
40
  end
34
41
 
35
42
  # Creates an internal metadata table with columns +key+ and +value+
36
43
  def create_table
37
- unless table_exists?
38
- key_options = connection.internal_string_options_for_primary_key
44
+ return unless enabled?
39
45
 
46
+ unless connection.table_exists?(table_name)
40
47
  connection.create_table(table_name, id: false) do |t|
41
- t.string :key, key_options
48
+ t.string :key, **connection.internal_string_options_for_primary_key
42
49
  t.string :value
43
50
  t.timestamps
44
51
  end
@@ -46,6 +53,8 @@ module ActiveRecord
46
53
  end
47
54
 
48
55
  def drop_table
56
+ return unless enabled?
57
+
49
58
  connection.drop_table table_name, if_exists: true
50
59
  end
51
60
  end
@@ -1,13 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecord
4
- module LegacyYamlAdapter
4
+ module LegacyYamlAdapter # :nodoc:
5
5
  def self.convert(klass, coder)
6
6
  return coder unless coder.is_a?(Psych::Coder)
7
7
 
8
8
  case coder["active_record_yaml_version"]
9
9
  when 1, 2 then coder
10
10
  else
11
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
12
+ YAML loading from legacy format older than Rails 5.0 is deprecated
13
+ and will be removed in Rails 6.2.
14
+ MSG
11
15
  if coder["attributes"].is_a?(ActiveModel::AttributeSet)
12
16
  Rails420.convert(klass, coder)
13
17
  else
@@ -16,7 +20,7 @@ module ActiveRecord
16
20
  end
17
21
  end
18
22
 
19
- module Rails420
23
+ module Rails420 # :nodoc:
20
24
  def self.convert(klass, coder)
21
25
  attribute_set = coder["attributes"]
22
26
 
@@ -32,7 +36,7 @@ module ActiveRecord
32
36
  end
33
37
  end
34
38
 
35
- module Rails41
39
+ module Rails41 # :nodoc:
36
40
  def self.convert(klass, coder)
37
41
  attributes = klass.attributes_builder
38
42
  .build_from_database(coder["attributes"])
@@ -60,6 +60,15 @@ module ActiveRecord
60
60
  self.class.locking_enabled?
61
61
  end
62
62
 
63
+ def increment!(*, **) #:nodoc:
64
+ super.tap do
65
+ if locking_enabled?
66
+ self[self.class.locking_column] += 1
67
+ clear_attribute_change(self.class.locking_column)
68
+ end
69
+ end
70
+ end
71
+
63
72
  private
64
73
  def _create_record(attribute_names = self.attribute_names)
65
74
  if locking_enabled?
@@ -80,7 +89,8 @@ module ActiveRecord
80
89
 
81
90
  begin
82
91
  locking_column = self.class.locking_column
83
- previous_lock_value = read_attribute_before_type_cast(locking_column)
92
+ previous_lock_value = attribute_before_type_cast(locking_column)
93
+ attribute_names = attribute_names.dup if attribute_names.frozen?
84
94
  attribute_names << locking_column
85
95
 
86
96
  self[locking_column] += 1
@@ -88,7 +98,7 @@ module ActiveRecord
88
98
  affected_rows = self.class._update_record(
89
99
  attributes_with_values(attribute_names),
90
100
  @primary_key => id_in_database,
91
- locking_column => previous_lock_value
101
+ locking_column => @attributes[locking_column].original_value_for_database
92
102
  )
93
103
 
94
104
  if affected_rows != 1
@@ -111,7 +121,7 @@ module ActiveRecord
111
121
 
112
122
  affected_rows = self.class._delete_record(
113
123
  @primary_key => id_in_database,
114
- locking_column => read_attribute_before_type_cast(locking_column)
124
+ locking_column => attribute_before_type_cast(locking_column)
115
125
  )
116
126
 
117
127
  if affected_rows != 1
@@ -155,21 +165,12 @@ module ActiveRecord
155
165
  super
156
166
  end
157
167
 
158
- private
159
-
160
- # We need to apply this decorator here, rather than on module inclusion. The closure
161
- # created by the matcher would otherwise evaluate for `ActiveRecord::Base`, not the
162
- # sub class being decorated. As such, changes to `lock_optimistically`, or
163
- # `locking_column` would not be picked up.
164
- def inherited(subclass)
165
- subclass.class_eval do
166
- is_lock_column = ->(name, _) { lock_optimistically && name == locking_column }
167
- decorate_matching_attribute_types(is_lock_column, "_optimistic_locking") do |type|
168
- LockingType.new(type)
169
- end
170
- end
171
- super
168
+ def define_attribute(name, cast_type, **) # :nodoc:
169
+ if lock_optimistically && name == locking_column
170
+ cast_type = LockingType.new(cast_type)
172
171
  end
172
+ super
173
+ end
173
174
  end
174
175
  end
175
176
 
@@ -177,6 +178,10 @@ module ActiveRecord
177
178
  # `nil` values to `lock_version`, and not result in `ActiveRecord::StaleObjectError`
178
179
  # during update record.
179
180
  class LockingType < DelegateClass(Type::Value) # :nodoc:
181
+ def self.new(subtype)
182
+ self === subtype ? subtype : super
183
+ end
184
+
180
185
  def deserialize(value)
181
186
  super.to_i
182
187
  end
@@ -53,8 +53,12 @@ module ActiveRecord
53
53
  # end
54
54
  #
55
55
  # Database-specific information on row locking:
56
- # MySQL: https://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html
57
- # PostgreSQL: https://www.postgresql.org/docs/current/interactive/sql-select.html#SQL-FOR-UPDATE-SHARE
56
+ #
57
+ # [MySQL]
58
+ # https://dev.mysql.com/doc/refman/en/innodb-locking-reads.html
59
+ #
60
+ # [PostgreSQL]
61
+ # https://www.postgresql.org/docs/current/interactive/sql-select.html#SQL-FOR-UPDATE-SHARE
58
62
  module Pessimistic
59
63
  # Obtain a row lock on this record. Reloads the record to obtain the requested
60
64
  # lock. Pass an SQL locking clause to append the end of the SELECT statement