activerecord 7.0.0.alpha2 → 7.0.0.rc1

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 (102) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +504 -10
  3. data/lib/active_record/associations/association.rb +2 -8
  4. data/lib/active_record/associations/builder/collection_association.rb +9 -2
  5. data/lib/active_record/associations/collection_association.rb +10 -2
  6. data/lib/active_record/associations/preloader/association.rb +68 -48
  7. data/lib/active_record/associations/preloader/batch.rb +3 -6
  8. data/lib/active_record/associations/preloader/through_association.rb +19 -9
  9. data/lib/active_record/associations/preloader.rb +14 -24
  10. data/lib/active_record/associations/through_association.rb +2 -2
  11. data/lib/active_record/associations.rb +16 -3
  12. data/lib/active_record/asynchronous_queries_tracker.rb +3 -0
  13. data/lib/active_record/attribute_methods/dirty.rb +9 -1
  14. data/lib/active_record/attribute_methods.rb +7 -5
  15. data/lib/active_record/autosave_association.rb +3 -3
  16. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +6 -26
  17. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -2
  18. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +18 -5
  19. data/lib/active_record/connection_adapters/abstract/database_limits.rb +0 -17
  20. data/lib/active_record/connection_adapters/abstract/database_statements.rb +1 -1
  21. data/lib/active_record/connection_adapters/abstract/quoting.rb +33 -70
  22. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +4 -0
  23. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +9 -2
  24. data/lib/active_record/connection_adapters/abstract/transaction.rb +12 -19
  25. data/lib/active_record/connection_adapters/abstract_adapter.rb +37 -8
  26. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +1 -0
  27. data/lib/active_record/connection_adapters/column.rb +4 -0
  28. data/lib/active_record/connection_adapters/mysql/database_statements.rb +2 -2
  29. data/lib/active_record/connection_adapters/mysql/quoting.rb +23 -24
  30. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +1 -1
  31. data/lib/active_record/connection_adapters/pool_config.rb +7 -5
  32. data/lib/active_record/connection_adapters/postgresql/column.rb +17 -1
  33. data/lib/active_record/connection_adapters/postgresql/quoting.rb +44 -44
  34. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +21 -1
  35. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +18 -1
  36. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +25 -0
  37. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +15 -4
  38. data/lib/active_record/connection_adapters/postgresql_adapter.rb +48 -5
  39. data/lib/active_record/connection_adapters/schema_cache.rb +3 -1
  40. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +2 -2
  41. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +15 -16
  42. data/lib/active_record/connection_handling.rb +31 -19
  43. data/lib/active_record/core.rb +13 -24
  44. data/lib/active_record/database_configurations/connection_url_resolver.rb +2 -1
  45. data/lib/active_record/database_configurations/database_config.rb +0 -9
  46. data/lib/active_record/database_configurations/hash_config.rb +40 -8
  47. data/lib/active_record/database_configurations.rb +2 -27
  48. data/lib/active_record/delegated_type.rb +19 -0
  49. data/lib/active_record/encryption/encrypted_attribute_type.rb +1 -1
  50. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +1 -2
  51. data/lib/active_record/encryption/message_serializer.rb +11 -1
  52. data/lib/active_record/encryption/scheme.rb +1 -1
  53. data/lib/active_record/enum.rb +8 -1
  54. data/lib/active_record/errors.rb +1 -1
  55. data/lib/active_record/explain_registry.rb +11 -6
  56. data/lib/active_record/fixture_set/table_row.rb +1 -1
  57. data/lib/active_record/fixtures.rb +1 -9
  58. data/lib/active_record/future_result.rb +2 -2
  59. data/lib/active_record/gem_version.rb +1 -1
  60. data/lib/active_record/insert_all.rb +52 -15
  61. data/lib/active_record/integration.rb +3 -2
  62. data/lib/active_record/legacy_yaml_adapter.rb +2 -39
  63. data/lib/active_record/locking/pessimistic.rb +9 -3
  64. data/lib/active_record/log_subscriber.rb +8 -1
  65. data/lib/active_record/middleware/shard_selector.rb +60 -0
  66. data/lib/active_record/model_schema.rb +1 -28
  67. data/lib/active_record/nested_attributes.rb +11 -10
  68. data/lib/active_record/no_touching.rb +1 -1
  69. data/lib/active_record/persistence.rb +99 -21
  70. data/lib/active_record/query_logs.rb +18 -83
  71. data/lib/active_record/railtie.rb +11 -1
  72. data/lib/active_record/railties/databases.rake +4 -91
  73. data/lib/active_record/reflection.rb +22 -6
  74. data/lib/active_record/relation/calculations.rb +1 -10
  75. data/lib/active_record/relation/finder_methods.rb +0 -13
  76. data/lib/active_record/relation/query_methods.rb +5 -14
  77. data/lib/active_record/relation/record_fetch_warning.rb +5 -7
  78. data/lib/active_record/relation/where_clause.rb +2 -15
  79. data/lib/active_record/relation.rb +11 -13
  80. data/lib/active_record/result.rb +0 -5
  81. data/lib/active_record/runtime_registry.rb +10 -12
  82. data/lib/active_record/schema_dumper.rb +7 -0
  83. data/lib/active_record/scoping.rb +34 -22
  84. data/lib/active_record/suppressor.rb +11 -15
  85. data/lib/active_record/tasks/database_tasks.rb +18 -44
  86. data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -1
  87. data/lib/active_record/validations/uniqueness.rb +1 -1
  88. data/lib/active_record.rb +41 -33
  89. data/lib/arel/crud.rb +12 -2
  90. data/lib/arel/delete_manager.rb +16 -0
  91. data/lib/arel/filter_predications.rb +9 -0
  92. data/lib/arel/nodes/delete_statement.rb +5 -1
  93. data/lib/arel/nodes/filter.rb +10 -0
  94. data/lib/arel/nodes/function.rb +1 -0
  95. data/lib/arel/nodes/update_statement.rb +5 -1
  96. data/lib/arel/nodes.rb +1 -0
  97. data/lib/arel/predications.rb +10 -2
  98. data/lib/arel/update_manager.rb +16 -0
  99. data/lib/arel/visitors/mysql.rb +2 -1
  100. data/lib/arel/visitors/to_sql.rb +15 -0
  101. data/lib/arel.rb +1 -0
  102. metadata +14 -10
@@ -10,6 +10,7 @@ module ActiveRecord
10
10
  included do
11
11
  class_attribute :_reflections, instance_writer: false, default: {}
12
12
  class_attribute :aggregate_reflections, instance_writer: false, default: {}
13
+ class_attribute :automatic_scope_inversing, instance_writer: false, default: false
13
14
  end
14
15
 
15
16
  class << self
@@ -234,6 +235,9 @@ module ActiveRecord
234
235
  if has_inverse? && inverse_of.nil?
235
236
  raise InverseOfAssociationNotFoundError.new(self)
236
237
  end
238
+ if has_inverse? && inverse_of == self
239
+ raise InverseOfAssociationRecursiveError.new(self)
240
+ end
237
241
  end
238
242
  end
239
243
 
@@ -631,9 +635,10 @@ module ActiveRecord
631
635
  # with the current reflection's klass name.
632
636
  def valid_inverse_reflection?(reflection)
633
637
  reflection &&
638
+ reflection != self &&
634
639
  foreign_key == reflection.foreign_key &&
635
640
  klass <= reflection.active_record &&
636
- can_find_inverse_of_automatically?(reflection)
641
+ can_find_inverse_of_automatically?(reflection, true)
637
642
  end
638
643
 
639
644
  # Checks to see if the reflection doesn't have any options that prevent
@@ -642,14 +647,25 @@ module ActiveRecord
642
647
  # have <tt>has_many</tt>, <tt>has_one</tt>, <tt>belongs_to</tt> associations.
643
648
  # Third, we must not have options such as <tt>:foreign_key</tt>
644
649
  # which prevent us from correctly guessing the inverse association.
645
- #
646
- # Anything with a scope can additionally ruin our attempt at finding an
647
- # inverse, so we exclude reflections with scopes.
648
- def can_find_inverse_of_automatically?(reflection)
650
+ def can_find_inverse_of_automatically?(reflection, inverse_reflection = false)
649
651
  reflection.options[:inverse_of] != false &&
650
652
  !reflection.options[:through] &&
651
653
  !reflection.options[:foreign_key] &&
654
+ scope_allows_automatic_inverse_of?(reflection, inverse_reflection)
655
+ end
656
+
657
+ # Scopes on the potential inverse reflection prevent automatic
658
+ # <tt>inverse_of</tt>, since the scope could exclude the owner record
659
+ # we would inverse from. Scopes on the reflection itself allow for
660
+ # automatic <tt>inverse_of</tt> as long as
661
+ # <tt>config.active_record.automatic_scope_inversing<tt> is set to
662
+ # +true+ (the default for new applications).
663
+ def scope_allows_automatic_inverse_of?(reflection, inverse_reflection)
664
+ if inverse_reflection
652
665
  !reflection.scope
666
+ else
667
+ !reflection.scope || reflection.klass.automatic_scope_inversing
668
+ end
653
669
  end
654
670
 
655
671
  def derive_class_name
@@ -736,7 +752,7 @@ module ActiveRecord
736
752
  end
737
753
 
738
754
  private
739
- def can_find_inverse_of_automatically?(_)
755
+ def can_find_inverse_of_automatically?(*)
740
756
  !polymorphic? && super
741
757
  end
742
758
  end
@@ -31,7 +31,7 @@ module ActiveRecord
31
31
  #
32
32
  # Article.group(:status, :category).count
33
33
  # # => {["draft", "business"]=>10, ["draft", "technology"]=>4,
34
- # ["published", "business"]=>0, ["published", "technology"]=>2}
34
+ # # ["published", "business"]=>0, ["published", "technology"]=>2}
35
35
  #
36
36
  # If #count is used with {Relation#select}[rdoc-ref:QueryMethods#select], it will count the selected columns:
37
37
  #
@@ -329,15 +329,6 @@ module ActiveRecord
329
329
  group_fields = group_values
330
330
  group_fields = group_fields.uniq if group_fields.size > 1
331
331
 
332
- unless group_fields == group_values
333
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
334
- `#{operation}` with group by duplicated fields does no longer affect to result in Rails 7.0.
335
- To migrate to Rails 7.0's behavior, use `uniq!(:group)` to deduplicate group fields
336
- (`#{klass.name&.tableize || klass.table_name}.uniq!(:group).#{operation}(#{column_name.inspect})`).
337
- MSG
338
- group_fields = group_values
339
- end
340
-
341
332
  if group_fields.size == 1 && group_fields.first.respond_to?(:to_sym)
342
333
  association = klass._reflect_on_association(group_fields.first)
343
334
  associated = association && association.belongs_to? # only count belongs_to associations
@@ -140,8 +140,6 @@ module ActiveRecord
140
140
  # Person.first(3) # returns the first three objects fetched by SELECT * FROM people ORDER BY people.id LIMIT 3
141
141
  #
142
142
  def first(limit = nil)
143
- check_reorder_deprecation unless loaded?
144
-
145
143
  if limit
146
144
  find_nth_with_limit(0, limit)
147
145
  else
@@ -390,17 +388,6 @@ module ActiveRecord
390
388
  end
391
389
 
392
390
  private
393
- def check_reorder_deprecation
394
- if !order_values.empty? && order_values.all?(&:blank?)
395
- blank_value = order_values.first
396
- ActiveSupport::Deprecation.warn(<<~MSG.squish)
397
- `.reorder(#{blank_value.inspect})` with `.first` / `.first!` no longer
398
- takes non-deterministic result in Rails 7.0.
399
- To continue taking non-deterministic result, use `.take` / `.take!` instead.
400
- MSG
401
- end
402
- end
403
-
404
391
  def construct_relation_for_exists(conditions)
405
392
  conditions = sanitize_forbidden_attributes(conditions)
406
393
 
@@ -432,6 +432,7 @@ module ActiveRecord
432
432
  references = column_references([column])
433
433
  self.references_values |= references unless references.empty?
434
434
 
435
+ values = values.map { |value| type_caster.type_cast_for_database(column, value) }
435
436
  column = order_column(column.to_s) if column.is_a?(Symbol)
436
437
 
437
438
  spawn.order!(connection.field_ordered_value(column, values))
@@ -448,14 +449,14 @@ module ActiveRecord
448
449
  # generates a query with 'ORDER BY id ASC, name ASC'.
449
450
  def reorder(*args)
450
451
  check_if_method_has_arguments!(__callee__, args) do
451
- sanitize_order_arguments(args) unless args.all?(&:blank?)
452
+ sanitize_order_arguments(args)
452
453
  end
453
454
  spawn.reorder!(*args)
454
455
  end
455
456
 
456
457
  # Same as #reorder but operates on relation in-place instead of copying.
457
458
  def reorder!(*args) # :nodoc:
458
- preprocess_order_args(args) unless args.all?(&:blank?)
459
+ preprocess_order_args(args)
459
460
  args.uniq!
460
461
  self.reordering_value = true
461
462
  self.order_values = args
@@ -1339,14 +1340,6 @@ module ActiveRecord
1339
1340
  unless annotate_values.empty?
1340
1341
  annotates = annotate_values
1341
1342
  annotates = annotates.uniq if annotates.size > 1
1342
- unless annotates == annotate_values
1343
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
1344
- Duplicated query annotations are no longer shown in queries in Rails 7.0.
1345
- To migrate to Rails 7.0's behavior, use `uniq!(:annotate)` to deduplicate query annotations
1346
- (`#{klass.name&.tableize || klass.table_name}.uniq!(:annotate)`).
1347
- MSG
1348
- annotates = annotate_values
1349
- end
1350
1343
  arel.comment(*annotates)
1351
1344
  end
1352
1345
 
@@ -1606,8 +1599,6 @@ module ActiveRecord
1606
1599
  order_args.map! do |arg|
1607
1600
  klass.sanitize_sql_for_order(arg)
1608
1601
  end
1609
- order_args.flatten!
1610
- order_args.compact_blank!
1611
1602
  end
1612
1603
 
1613
1604
  def column_references(order_args)
@@ -1676,9 +1667,9 @@ module ActiveRecord
1676
1667
  def check_if_method_has_arguments!(method_name, args, message = nil)
1677
1668
  if args.blank?
1678
1669
  raise ArgumentError, message || "The method .#{method_name}() must contain arguments."
1679
- elsif block_given?
1680
- yield args
1681
1670
  else
1671
+ yield args if block_given?
1672
+
1682
1673
  args.flatten!
1683
1674
  args.compact_blank!
1684
1675
  end
@@ -31,17 +31,15 @@ module ActiveRecord
31
31
  end
32
32
  # :startdoc:
33
33
 
34
- class QueryRegistry # :nodoc:
35
- extend ActiveSupport::PerThreadRegistry
34
+ module QueryRegistry # :nodoc:
35
+ extend self
36
36
 
37
- attr_reader :queries
38
-
39
- def initialize
40
- @queries = []
37
+ def queries
38
+ ActiveSupport::IsolatedExecutionState[:active_record_query_registry] ||= []
41
39
  end
42
40
 
43
41
  def reset
44
- @queries.clear
42
+ queries.clear
45
43
  end
46
44
  end
47
45
  end
@@ -163,21 +163,8 @@ module ActiveRecord
163
163
  attr = extract_attribute(node) || begin
164
164
  node.left if equality_node?(node) && node.left.is_a?(Arel::Predications)
165
165
  end
166
- next false unless attr
167
-
168
- ref = referenced_columns[attr]
169
- next false unless ref
170
-
171
- if equality_node?(node) && equality_node?(ref) || node == ref
172
- true
173
- else
174
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
175
- Merging (#{node.to_sql}) and (#{ref.to_sql}) no longer maintain
176
- both conditions, and will be replaced by the latter in Rails 7.0.
177
- To migrate to Rails 7.0's behavior, use `relation.merge(other, rewhere: true)`.
178
- MSG
179
- false
180
- end
166
+
167
+ attr && referenced_columns[attr]
181
168
  end
182
169
  end
183
170
 
@@ -11,7 +11,7 @@ module ActiveRecord
11
11
  :reverse_order, :distinct, :create_with, :skip_query_cache]
12
12
 
13
13
  CLAUSE_METHODS = [:where, :having, :from]
14
- INVALID_METHODS_FOR_DELETE_ALL = [:distinct, :group, :having]
14
+ INVALID_METHODS_FOR_DELETE_ALL = [:distinct]
15
15
 
16
16
  VALUE_METHODS = MULTI_VALUE_METHODS + SINGLE_VALUE_METHODS + CLAUSE_METHODS
17
17
 
@@ -41,11 +41,6 @@ module ActiveRecord
41
41
  reset
42
42
  end
43
43
 
44
- def arel_attribute(name) # :nodoc:
45
- table[name]
46
- end
47
- deprecate :arel_attribute
48
-
49
44
  def bind_attribute(name, value) # :nodoc:
50
45
  if reflection = klass._reflect_on_association(name)
51
46
  name = reflection.foreign_key
@@ -295,14 +290,14 @@ module ActiveRecord
295
290
  # Returns true if there is exactly one record.
296
291
  def one?
297
292
  return super if block_given?
298
- return records.one? if limit_value || loaded?
293
+ return records.one? if loaded?
299
294
  limited_count == 1
300
295
  end
301
296
 
302
297
  # Returns true if there is more than one record.
303
298
  def many?
304
299
  return super if block_given?
305
- return records.many? if limit_value || loaded?
300
+ return records.many? if loaded?
306
301
  limited_count > 1
307
302
  end
308
303
 
@@ -394,7 +389,7 @@ module ActiveRecord
394
389
  end
395
390
 
396
391
  if timestamp
397
- "#{size}-#{timestamp.utc.to_s(cache_timestamp_format)}"
392
+ "#{size}-#{timestamp.utc.to_formatted_s(cache_timestamp_format)}"
398
393
  else
399
394
  "#{size}"
400
395
  end
@@ -485,8 +480,9 @@ module ActiveRecord
485
480
  arel = eager_loading? ? apply_join_dependency.arel : build_arel
486
481
  arel.source.left = table
487
482
 
488
- stmt = arel.compile_update(values, table[primary_key])
489
-
483
+ group_values_arel_columns = arel_columns(group_values.uniq)
484
+ having_clause_ast = having_clause.ast unless having_clause.empty?
485
+ stmt = arel.compile_update(values, table[primary_key], having_clause_ast, group_values_arel_columns)
490
486
  klass.connection.update(stmt, "#{klass} Update All").tap { reset }
491
487
  end
492
488
 
@@ -615,7 +611,9 @@ module ActiveRecord
615
611
  arel = eager_loading? ? apply_join_dependency.arel : build_arel
616
612
  arel.source.left = table
617
613
 
618
- stmt = arel.compile_delete(table[primary_key])
614
+ group_values_arel_columns = arel_columns(group_values.uniq)
615
+ having_clause_ast = having_clause.ast unless having_clause.empty?
616
+ stmt = arel.compile_delete(table[primary_key], having_clause_ast, group_values_arel_columns)
619
617
 
620
618
  klass.connection.delete(stmt, "#{klass} Delete All").tap { reset }
621
619
  end
@@ -976,7 +974,7 @@ module ActiveRecord
976
974
  end
977
975
 
978
976
  def limited_count
979
- @limited_count ||= limit(2).count
977
+ @limited_count ||= limit_value ? count : limit(2).count
980
978
  end
981
979
  end
982
980
  end
@@ -72,11 +72,6 @@ module ActiveRecord
72
72
  end
73
73
  end
74
74
 
75
- alias :map! :map
76
- alias :collect! :map
77
- deprecate "map!": :map
78
- deprecate "collect!": :map
79
-
80
75
  # Returns true if there are no records, otherwise false.
81
76
  def empty?
82
77
  rows.empty?
@@ -1,22 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/per_thread_registry"
4
-
5
3
  module ActiveRecord
6
4
  # This is a thread locals registry for Active Record. For example:
7
5
  #
8
- # ActiveRecord::RuntimeRegistry.connection_handler
9
- #
10
- # returns the connection handler local to the current thread.
6
+ # ActiveRecord::RuntimeRegistry.sql_runtime
11
7
  #
12
- # See the documentation of ActiveSupport::PerThreadRegistry
13
- # for further details.
14
- class RuntimeRegistry # :nodoc:
15
- extend ActiveSupport::PerThreadRegistry
8
+ # returns the connection handler local to the current unit of execution (either thread of fiber).
9
+ module RuntimeRegistry # :nodoc:
10
+ extend self
16
11
 
17
- attr_accessor :sql_runtime
12
+ def sql_runtime
13
+ ActiveSupport::IsolatedExecutionState[:active_record_sql_runtime]
14
+ end
18
15
 
19
- def self.sql_runtime; instance.sql_runtime; end
20
- def self.sql_runtime=(x); instance.sql_runtime = x; end
16
+ def sql_runtime=(runtime)
17
+ ActiveSupport::IsolatedExecutionState[:active_record_sql_runtime] = runtime
18
+ end
21
19
  end
22
20
  end
@@ -47,6 +47,7 @@ module ActiveRecord
47
47
  def dump(stream)
48
48
  header(stream)
49
49
  extensions(stream)
50
+ types(stream)
50
51
  tables(stream)
51
52
  trailer(stream)
52
53
  stream
@@ -99,6 +100,10 @@ HEADER
99
100
  def extensions(stream)
100
101
  end
101
102
 
103
+ # (enum) types are only supported by PostgreSQL
104
+ def types(stream)
105
+ end
106
+
102
107
  def tables(stream)
103
108
  sorted_tables = @connection.tables.sort
104
109
 
@@ -154,6 +159,7 @@ HEADER
154
159
  columns.each do |column|
155
160
  raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type)
156
161
  next if column.name == pk
162
+
157
163
  type, colspec = column_spec(column)
158
164
  if type.is_a?(Symbol)
159
165
  tbl.print " t.#{type} #{column.name.inspect}"
@@ -259,6 +265,7 @@ HEADER
259
265
 
260
266
  parts << "on_update: #{foreign_key.on_update.inspect}" if foreign_key.on_update
261
267
  parts << "on_delete: #{foreign_key.on_delete.inspect}" if foreign_key.on_delete
268
+ parts << "deferrable: #{foreign_key.deferrable.inspect}" if foreign_key.deferrable
262
269
 
263
270
  " #{parts.join(', ')}"
264
271
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/per_thread_registry"
3
+ require "active_support/core_ext/module/delegation"
4
4
 
5
5
  module ActiveRecord
6
6
  module Scoping
@@ -57,8 +57,8 @@ module ActiveRecord
57
57
  end
58
58
 
59
59
  # This class stores the +:current_scope+ and +:ignore_default_scope+ values
60
- # for different classes. The registry is stored as a thread local, which is
61
- # accessed through +ScopeRegistry.current+.
60
+ # for different classes. The registry is stored as either a thread or fiber
61
+ # local depending on the application configuration.
62
62
  #
63
63
  # This class allows you to store and get the scope values on different
64
64
  # classes and different types of scopes. For example, if you are attempting
@@ -66,22 +66,22 @@ module ActiveRecord
66
66
  # following code:
67
67
  #
68
68
  # registry = ActiveRecord::Scoping::ScopeRegistry
69
- # registry.set_value_for(:current_scope, Board, some_new_scope)
69
+ # registry.set_current_scope(Board, some_new_scope)
70
70
  #
71
71
  # Now when you run:
72
72
  #
73
- # registry.value_for(:current_scope, Board)
73
+ # registry.current_scope(Board)
74
74
  #
75
- # You will obtain whatever was defined in +some_new_scope+. The #value_for
76
- # and #set_value_for methods are delegated to the current ScopeRegistry
77
- # object, so the above example code can also be called as:
78
- #
79
- # ActiveRecord::Scoping::ScopeRegistry.set_value_for(:current_scope,
80
- # Board, some_new_scope)
75
+ # You will obtain whatever was defined in +some_new_scope+.
81
76
  class ScopeRegistry # :nodoc:
82
- extend ActiveSupport::PerThreadRegistry
77
+ class << self
78
+ delegate :current_scope, :set_current_scope, :ignore_default_scope, :set_ignore_default_scope,
79
+ :global_current_scope, :set_global_current_scope, to: :instance
83
80
 
84
- VALID_SCOPE_TYPES = [:current_scope, :ignore_default_scope, :global_current_scope]
81
+ def instance
82
+ ActiveSupport::IsolatedExecutionState[:active_record_scope_registry] ||= new
83
+ end
84
+ end
85
85
 
86
86
  def initialize
87
87
  @current_scope = {}
@@ -89,16 +89,28 @@ module ActiveRecord
89
89
  @global_current_scope = {}
90
90
  end
91
91
 
92
- VALID_SCOPE_TYPES.each do |type|
93
- class_eval <<-eorb, __FILE__, __LINE__
94
- def #{type}(model, skip_inherited_scope = false)
95
- value_for(@#{type}, model, skip_inherited_scope)
96
- end
92
+ def current_scope(model, skip_inherited_scope = false)
93
+ value_for(@current_scope, model, skip_inherited_scope)
94
+ end
97
95
 
98
- def set_#{type}(model, value)
99
- set_value_for(@#{type}, model, value)
100
- end
101
- eorb
96
+ def set_current_scope(model, value)
97
+ set_value_for(@current_scope, model, value)
98
+ end
99
+
100
+ def ignore_default_scope(model, skip_inherited_scope = false)
101
+ value_for(@ignore_default_scope, model, skip_inherited_scope)
102
+ end
103
+
104
+ def set_ignore_default_scope(model, value)
105
+ set_value_for(@ignore_default_scope, model, value)
106
+ end
107
+
108
+ def global_current_scope(model, skip_inherited_scope = false)
109
+ value_for(@global_current_scope, model, skip_inherited_scope)
110
+ end
111
+
112
+ def set_global_current_scope(model, value)
113
+ set_value_for(@global_current_scope, model, value)
102
114
  end
103
115
 
104
116
  private
@@ -30,32 +30,28 @@ module ActiveRecord
30
30
  module Suppressor
31
31
  extend ActiveSupport::Concern
32
32
 
33
+ class << self
34
+ def registry # :nodoc:
35
+ ActiveSupport::IsolatedExecutionState[:active_record_suppresor_registry] ||= {}
36
+ end
37
+ end
38
+
33
39
  module ClassMethods
34
40
  def suppress(&block)
35
- previous_state = SuppressorRegistry.suppressed[name]
36
- SuppressorRegistry.suppressed[name] = true
41
+ previous_state = Suppressor.registry[name]
42
+ Suppressor.registry[name] = true
37
43
  yield
38
44
  ensure
39
- SuppressorRegistry.suppressed[name] = previous_state
45
+ Suppressor.registry[name] = previous_state
40
46
  end
41
47
  end
42
48
 
43
49
  def save(**) # :nodoc:
44
- SuppressorRegistry.suppressed[self.class.name] ? true : super
50
+ Suppressor.registry[self.class.name] ? true : super
45
51
  end
46
52
 
47
53
  def save!(**) # :nodoc:
48
- SuppressorRegistry.suppressed[self.class.name] ? true : super
49
- end
50
- end
51
-
52
- class SuppressorRegistry # :nodoc:
53
- extend ActiveSupport::PerThreadRegistry
54
-
55
- attr_reader :suppressed
56
-
57
- def initialize
58
- @suppressed = {}
54
+ Suppressor.registry[self.class.name] ? true : super
59
55
  end
60
56
  end
61
57
  end
@@ -55,8 +55,7 @@ module ActiveRecord
55
55
 
56
56
  extend self
57
57
 
58
- attr_writer :current_config, :db_dir, :migrations_paths, :fixtures_path, :root, :env, :seed_loader
59
- deprecate :current_config=
58
+ attr_writer :db_dir, :migrations_paths, :fixtures_path, :root, :env, :seed_loader
60
59
  attr_accessor :database_configuration
61
60
 
62
61
  LOCAL_HOSTS = ["127.0.0.1", "localhost"]
@@ -110,11 +109,6 @@ module ActiveRecord
110
109
  @env ||= Rails.env
111
110
  end
112
111
 
113
- def spec
114
- @spec ||= "primary"
115
- end
116
- deprecate spec: "please use name instead"
117
-
118
112
  def name
119
113
  @name ||= "primary"
120
114
  end
@@ -123,18 +117,6 @@ module ActiveRecord
123
117
  @seed_loader ||= Rails.application
124
118
  end
125
119
 
126
- def current_config(options = {})
127
- if options.has_key?(:config)
128
- @current_config = options[:config]
129
- else
130
- env_name = options[:env] || env
131
- name = options[:spec] || "primary"
132
-
133
- @current_config ||= configs_for(env_name: env_name, name: name)&.configuration_hash
134
- end
135
- end
136
- deprecate :current_config
137
-
138
120
  def create(configuration, *arguments)
139
121
  db_config = resolve_configuration(configuration)
140
122
  database_adapter_for(db_config, *arguments).create
@@ -216,10 +198,9 @@ module ActiveRecord
216
198
  dump_schema(db_config, ActiveRecord.schema_format)
217
199
  end
218
200
  rescue ActiveRecord::NoDatabaseError
219
- config_name = db_config.name
220
- create_current(db_config.env_name, config_name)
201
+ create_current(db_config.env_name, db_config.name)
221
202
 
222
- if File.exist?(dump_filename(config_name))
203
+ if File.exist?(schema_dump_path(db_config))
223
204
  load_schema(
224
205
  db_config,
225
206
  ActiveRecord.schema_format,
@@ -378,7 +359,7 @@ module ActiveRecord
378
359
  end
379
360
 
380
361
  def load_schema(db_config, format = ActiveRecord.schema_format, file = nil) # :nodoc:
381
- file ||= dump_filename(db_config.name, format)
362
+ file ||= schema_dump_path(db_config, format)
382
363
 
383
364
  verbose_was, Migration.verbose = Migration.verbose, verbose? && ENV["VERBOSE"]
384
365
  check_schema_file(file)
@@ -399,16 +380,10 @@ module ActiveRecord
399
380
  Migration.verbose = verbose_was
400
381
  end
401
382
 
402
- def schema_up_to_date?(configuration, format = ActiveRecord.schema_format, file = nil, environment = nil, name = nil)
383
+ def schema_up_to_date?(configuration, format = ActiveRecord.schema_format, file = nil)
403
384
  db_config = resolve_configuration(configuration)
404
385
 
405
- if environment || name
406
- ActiveSupport::Deprecation.warn("`environment` and `name` will be removed as parameters in 7.0.0, you may now pass an ActiveRecord::DatabaseConfigurations::DatabaseConfig as `configuration` instead.")
407
- end
408
-
409
- name ||= db_config.name
410
-
411
- file ||= dump_filename(name, format)
386
+ file ||= schema_dump_path(db_config)
412
387
 
413
388
  return true unless File.exist?(file)
414
389
 
@@ -421,7 +396,7 @@ module ActiveRecord
421
396
  end
422
397
 
423
398
  def reconstruct_from_schema(db_config, format = ActiveRecord.schema_format, file = nil) # :nodoc:
424
- file ||= dump_filename(db_config.name, format)
399
+ file ||= schema_dump_path(db_config, format)
425
400
 
426
401
  check_schema_file(file)
427
402
 
@@ -440,7 +415,7 @@ module ActiveRecord
440
415
 
441
416
  def dump_schema(db_config, format = ActiveRecord.schema_format) # :nodoc:
442
417
  require "active_record/schema_dumper"
443
- filename = dump_filename(db_config.name, format)
418
+ filename = schema_dump_path(db_config, format)
444
419
  connection = ActiveRecord::Base.connection
445
420
 
446
421
  FileUtils.mkdir_p(db_dir)
@@ -460,11 +435,6 @@ module ActiveRecord
460
435
  end
461
436
  end
462
437
 
463
- def schema_file(format = ActiveRecord.schema_format)
464
- File.join(db_dir, schema_file_type(format))
465
- end
466
- deprecate :schema_file
467
-
468
438
  def schema_file_type(format = ActiveRecord.schema_format)
469
439
  case format
470
440
  when :ruby
@@ -473,15 +443,19 @@ module ActiveRecord
473
443
  "structure.sql"
474
444
  end
475
445
  end
446
+ deprecate :schema_file_type
476
447
 
477
- def dump_filename(db_config_name, format = ActiveRecord.schema_format)
478
- filename = if ActiveRecord::Base.configurations.primary?(db_config_name)
479
- schema_file_type(format)
448
+ def schema_dump_path(db_config, format = ActiveRecord.schema_format)
449
+ return ENV["SCHEMA"] if ENV["SCHEMA"]
450
+
451
+ filename = db_config.schema_dump(format)
452
+ return unless filename
453
+
454
+ if File.dirname(filename) == ActiveRecord::Tasks::DatabaseTasks.db_dir
455
+ filename
480
456
  else
481
- "#{db_config_name}_#{schema_file_type(format)}"
457
+ File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
482
458
  end
483
-
484
- ENV["SCHEMA"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
485
459
  end
486
460
 
487
461
  def cache_dump_filename(db_config_name, schema_cache_path: nil)
@@ -57,8 +57,12 @@ module ActiveRecord
57
57
  ActiveRecord.dump_schemas
58
58
  end
59
59
 
60
- args = ["--schema-only", "--no-privileges", "--no-owner", "--file", filename]
60
+ args = ["--schema-only", "--no-privileges", "--no-owner"]
61
+ args << "--no-comment" if connection.database_version >= 110_000
62
+ args.concat(["--file", filename])
63
+
61
64
  args.concat(Array(extra_flags)) if extra_flags
65
+
62
66
  unless search_path.blank?
63
67
  args += search_path.split(",").map do |part|
64
68
  "--schema=#{part.strip}"