activerecord 7.1.3.1 → 7.1.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +266 -0
  3. data/lib/active_record/associations/belongs_to_association.rb +4 -4
  4. data/lib/active_record/associations/collection_association.rb +4 -4
  5. data/lib/active_record/associations/has_many_association.rb +2 -2
  6. data/lib/active_record/associations/has_one_association.rb +2 -2
  7. data/lib/active_record/associations/join_dependency.rb +6 -8
  8. data/lib/active_record/associations.rb +6 -0
  9. data/lib/active_record/attribute_methods/dirty.rb +2 -2
  10. data/lib/active_record/attribute_methods/read.rb +3 -3
  11. data/lib/active_record/attribute_methods/write.rb +3 -3
  12. data/lib/active_record/attribute_methods.rb +46 -6
  13. data/lib/active_record/autosave_association.rb +5 -2
  14. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +8 -1
  15. data/lib/active_record/connection_adapters/abstract/database_statements.rb +1 -1
  16. data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
  17. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +8 -4
  18. data/lib/active_record/connection_adapters/abstract_adapter.rb +14 -15
  19. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +37 -13
  20. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +2 -1
  21. data/lib/active_record/connection_adapters/mysql2_adapter.rb +16 -10
  22. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
  23. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +1 -1
  24. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +2 -2
  25. data/lib/active_record/connection_adapters/trilogy_adapter.rb +16 -20
  26. data/lib/active_record/core.rb +7 -2
  27. data/lib/active_record/counter_cache.rb +7 -3
  28. data/lib/active_record/database_configurations/hash_config.rb +6 -2
  29. data/lib/active_record/delegated_type.rb +6 -6
  30. data/lib/active_record/destroy_association_async_job.rb +1 -1
  31. data/lib/active_record/encryption/encrypted_attribute_type.rb +2 -2
  32. data/lib/active_record/encryption/scheme.rb +8 -4
  33. data/lib/active_record/future_result.rb +9 -0
  34. data/lib/active_record/gem_version.rb +1 -1
  35. data/lib/active_record/locking/optimistic.rb +1 -1
  36. data/lib/active_record/marshalling.rb +1 -1
  37. data/lib/active_record/message_pack.rb +1 -1
  38. data/lib/active_record/migration/compatibility.rb +6 -0
  39. data/lib/active_record/model_schema.rb +6 -2
  40. data/lib/active_record/persistence.rb +2 -2
  41. data/lib/active_record/query_cache.rb +1 -1
  42. data/lib/active_record/query_logs_formatter.rb +1 -1
  43. data/lib/active_record/railtie.rb +10 -13
  44. data/lib/active_record/railties/databases.rake +2 -2
  45. data/lib/active_record/reflection.rb +8 -2
  46. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +6 -1
  47. data/lib/active_record/relation/query_methods.rb +21 -7
  48. data/lib/active_record/relation.rb +13 -3
  49. data/lib/active_record/result.rb +1 -1
  50. data/lib/active_record/tasks/database_tasks.rb +19 -8
  51. data/lib/active_record/test_fixtures.rb +1 -0
  52. data/lib/active_record/timestamp.rb +3 -1
  53. data/lib/active_record.rb +2 -2
  54. data/lib/arel/tree_manager.rb +5 -1
  55. data/lib/arel/visitors/to_sql.rb +2 -1
  56. metadata +13 -13
@@ -146,6 +146,7 @@ To keep using the current cache store, you can turn off cache versioning entirel
146
146
  config.after_initialize do |app|
147
147
  ActiveSupport.on_load(:active_record) do
148
148
  db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env).first
149
+ next if db_config.nil?
149
150
 
150
151
  filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(
151
152
  db_config.name,
@@ -261,8 +262,7 @@ To keep using the current cache store, you can turn off cache versioning entirel
261
262
  end
262
263
 
263
264
  ActiveSupport.on_load(:active_record) do
264
- # Configs used in other initializers
265
- configs = configs.except(
265
+ configs_used_in_other_initializers = configs.except(
266
266
  :migration_error,
267
267
  :database_selector,
268
268
  :database_resolver,
@@ -279,7 +279,7 @@ To keep using the current cache store, you can turn off cache versioning entirel
279
279
  :use_schema_cache_dump
280
280
  )
281
281
 
282
- configs.each do |k, v|
282
+ configs_used_in_other_initializers.each do |k, v|
283
283
  next if k == :encryption
284
284
  setter = "#{k}="
285
285
  # Some existing initializers might rely on Active Record configuration
@@ -377,23 +377,20 @@ To keep using the current cache store, you can turn off cache versioning entirel
377
377
  end
378
378
 
379
379
  initializer "active_record_encryption.configuration" do |app|
380
- auto_filtered_parameters = ActiveRecord::Encryption::AutoFilteredParameters.new(app)
381
-
382
- config.after_initialize do |app|
380
+ ActiveSupport.on_load(:active_record) do
383
381
  ActiveRecord::Encryption.configure \
384
382
  primary_key: app.credentials.dig(:active_record_encryption, :primary_key),
385
383
  deterministic_key: app.credentials.dig(:active_record_encryption, :deterministic_key),
386
384
  key_derivation_salt: app.credentials.dig(:active_record_encryption, :key_derivation_salt),
387
- **config.active_record.encryption
385
+ **app.config.active_record.encryption
388
386
 
387
+ auto_filtered_parameters = ActiveRecord::Encryption::AutoFilteredParameters.new(app)
389
388
  auto_filtered_parameters.enable if ActiveRecord::Encryption.config.add_to_filter_parameters
390
389
 
391
- ActiveSupport.on_load(:active_record) do
392
- # Support extended queries for deterministic attributes and validations
393
- if ActiveRecord::Encryption.config.extend_queries
394
- ActiveRecord::Encryption::ExtendedDeterministicQueries.install_support
395
- ActiveRecord::Encryption::ExtendedDeterministicUniquenessValidator.install_support
396
- end
390
+ # Support extended queries for deterministic attributes and validations
391
+ if ActiveRecord::Encryption.config.extend_queries
392
+ ActiveRecord::Encryption::ExtendedDeterministicQueries.install_support
393
+ ActiveRecord::Encryption::ExtendedDeterministicUniquenessValidator.install_support
397
394
  end
398
395
  end
399
396
 
@@ -89,10 +89,10 @@ db_namespace = namespace :db do
89
89
  task migrate: :load_config do
90
90
  db_configs = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env)
91
91
 
92
- if db_configs.size == 1
92
+ if db_configs.size == 1 && db_configs.first.primary?
93
93
  ActiveRecord::Tasks::DatabaseTasks.migrate
94
94
  else
95
- mapped_versions = ActiveRecord::Tasks::DatabaseTasks.db_configs_with_versions(db_configs)
95
+ mapped_versions = ActiveRecord::Tasks::DatabaseTasks.db_configs_with_versions
96
96
 
97
97
  mapped_versions.sort.each do |version, db_configs|
98
98
  db_configs.each do |db_config|
@@ -786,7 +786,7 @@ module ActiveRecord
786
786
  primary_query_constraints = active_record.query_constraints_list
787
787
  owner_pk = active_record.primary_key
788
788
 
789
- if primary_query_constraints.size != 2
789
+ if primary_query_constraints.size > 2
790
790
  raise ArgumentError, <<~MSG.squish
791
791
  The query constraints list on the `#{active_record}` model has more than 2
792
792
  attributes. Active Record is unable to derive the query constraints
@@ -804,6 +804,8 @@ module ActiveRecord
804
804
  MSG
805
805
  end
806
806
 
807
+ return foreign_key if primary_query_constraints.include?(foreign_key)
808
+
807
809
  first_key, last_key = primary_query_constraints
808
810
 
809
811
  if first_key == owner_pk
@@ -869,7 +871,11 @@ module ActiveRecord
869
871
  # klass option is necessary to support loading polymorphic associations
870
872
  def association_primary_key(klass = nil)
871
873
  if primary_key = options[:primary_key]
872
- @association_primary_key ||= -primary_key.to_s
874
+ @association_primary_key ||= if primary_key.is_a?(Array)
875
+ primary_key.map { |pk| pk.to_s.freeze }.freeze
876
+ else
877
+ -primary_key.to_s
878
+ end
873
879
  elsif (klass || self.klass).has_query_constraints? || options[:query_constraints]
874
880
  (klass || self.klass).composite_query_constraints_list
875
881
  elsif (klass || self.klass).composite_primary_key?
@@ -43,7 +43,12 @@ module ActiveRecord
43
43
 
44
44
  def convert_to_id(value)
45
45
  if value.is_a?(Base)
46
- value._read_attribute(primary_key(value))
46
+ primary_key = primary_key(value)
47
+ if primary_key.is_a?(Array)
48
+ primary_key.map { |column| value._read_attribute(column) }
49
+ else
50
+ value._read_attribute(primary_key)
51
+ end
47
52
  elsif value.is_a?(Relation)
48
53
  value.select(primary_key(value))
49
54
  else
@@ -1909,18 +1909,32 @@ module ActiveRecord
1909
1909
  end
1910
1910
 
1911
1911
  def column_references(order_args)
1912
- references = order_args.flat_map do |arg|
1912
+ order_args.flat_map do |arg|
1913
1913
  case arg
1914
1914
  when String, Symbol
1915
- arg
1915
+ extract_table_name_from(arg)
1916
1916
  when Hash
1917
- arg.keys.map do |key|
1918
- key if key.is_a?(String) || key.is_a?(Symbol)
1917
+ arg
1918
+ .map do |key, value|
1919
+ case value
1920
+ when Hash
1921
+ key.to_s
1922
+ else
1923
+ extract_table_name_from(key) if key.is_a?(String) || key.is_a?(Symbol)
1924
+ end
1925
+ end
1926
+ when Arel::Attribute
1927
+ arg.relation.name
1928
+ when Arel::Nodes::Ordering
1929
+ if arg.expr.is_a?(Arel::Attribute)
1930
+ arg.expr.relation.name
1919
1931
  end
1920
1932
  end
1921
- end
1922
- references.map! { |arg| arg =~ /^\W?(\w+)\W?\./ && $1 }.compact!
1923
- references
1933
+ end.compact
1934
+ end
1935
+
1936
+ def extract_table_name_from(string)
1937
+ string.match(/^\W?(\w+)\W?\./) && $1
1924
1938
  end
1925
1939
 
1926
1940
  def order_column(field)
@@ -526,7 +526,12 @@ module ActiveRecord
526
526
 
527
527
  group_values_arel_columns = arel_columns(group_values.uniq)
528
528
  having_clause_ast = having_clause.ast unless having_clause.empty?
529
- stmt = arel.compile_update(values, table[primary_key], having_clause_ast, group_values_arel_columns)
529
+ key = if klass.composite_primary_key?
530
+ primary_key.map { |pk| table[pk] }
531
+ else
532
+ table[primary_key]
533
+ end
534
+ stmt = arel.compile_update(values, key, having_clause_ast, group_values_arel_columns)
530
535
  klass.connection.update(stmt, "#{klass} Update All").tap { reset }
531
536
  end
532
537
 
@@ -659,7 +664,12 @@ module ActiveRecord
659
664
 
660
665
  group_values_arel_columns = arel_columns(group_values.uniq)
661
666
  having_clause_ast = having_clause.ast unless having_clause.empty?
662
- stmt = arel.compile_delete(table[primary_key], having_clause_ast, group_values_arel_columns)
667
+ key = if klass.composite_primary_key?
668
+ primary_key.map { |pk| table[pk] }
669
+ else
670
+ table[primary_key]
671
+ end
672
+ stmt = arel.compile_delete(key, having_clause_ast, group_values_arel_columns)
663
673
 
664
674
  klass.connection.delete(stmt, "#{klass} Delete All").tap { reset }
665
675
  end
@@ -975,7 +985,7 @@ module ActiveRecord
975
985
  def exec_main_query(async: false)
976
986
  if @none
977
987
  if async
978
- return FutureResult::Complete.new([])
988
+ return FutureResult.wrap([])
979
989
  else
980
990
  return []
981
991
  end
@@ -195,7 +195,7 @@ module ActiveRecord
195
195
  EMPTY = new([].freeze, [].freeze, {}.freeze).freeze
196
196
  private_constant :EMPTY
197
197
 
198
- EMPTY_ASYNC = FutureResult::Complete.new(EMPTY).freeze
198
+ EMPTY_ASYNC = FutureResult.wrap(EMPTY).freeze
199
199
  private_constant :EMPTY_ASYNC
200
200
  end
201
201
  end
@@ -192,9 +192,17 @@ module ActiveRecord
192
192
 
193
193
  seed = true
194
194
  end
195
+ end
196
+ end
195
197
 
196
- migrate
197
- dump_schema(db_config) if ActiveRecord.dump_schema_after_migration
198
+ each_current_environment(env) do |environment|
199
+ db_configs_with_versions(environment).sort.each do |version, db_configs|
200
+ db_configs.each do |db_config|
201
+ with_temporary_pool(db_config) do
202
+ migrate(version)
203
+ dump_schema(db_config) if ActiveRecord.dump_schema_after_migration
204
+ end
205
+ end
198
206
  end
199
207
  end
200
208
 
@@ -255,10 +263,10 @@ module ActiveRecord
255
263
  Migration.verbose = verbose_was
256
264
  end
257
265
 
258
- def db_configs_with_versions(db_configs) # :nodoc:
266
+ def db_configs_with_versions(environment = env) # :nodoc:
259
267
  db_configs_with_versions = Hash.new { |h, k| h[k] = [] }
260
268
 
261
- with_temporary_connection_for_each do |conn|
269
+ with_temporary_connection_for_each(env: environment) do |conn|
262
270
  db_config = conn.pool.db_config
263
271
  versions_to_run = conn.migration_context.pending_migration_versions
264
272
  target_version = ActiveRecord::Tasks::DatabaseTasks.target_version
@@ -552,10 +560,7 @@ module ActiveRecord
552
560
  end
553
561
 
554
562
  def each_current_configuration(environment, name = nil)
555
- environments = [environment]
556
- environments << "test" if environment == "development" && !ENV["SKIP_TEST_DATABASE"] && !ENV["DATABASE_URL"]
557
-
558
- environments.each do |env|
563
+ each_current_environment(environment) do |env|
559
564
  configs_for(env_name: env).each do |db_config|
560
565
  next if name && name != db_config.name
561
566
 
@@ -564,6 +569,12 @@ module ActiveRecord
564
569
  end
565
570
  end
566
571
 
572
+ def each_current_environment(environment, &block)
573
+ environments = [environment]
574
+ environments << "test" if environment == "development" && !ENV["SKIP_TEST_DATABASE"] && !ENV["DATABASE_URL"]
575
+ environments.each(&block)
576
+ end
577
+
567
578
  def each_local_configuration
568
579
  configs_for.each do |db_config|
569
580
  next unless db_config.database
@@ -13,6 +13,7 @@ module ActiveRecord
13
13
 
14
14
  def after_teardown # :nodoc:
15
15
  super
16
+ ensure
16
17
  teardown_fixtures
17
18
  end
18
19
 
@@ -54,8 +54,10 @@ module ActiveRecord
54
54
 
55
55
  module ClassMethods # :nodoc:
56
56
  def touch_attributes_with_time(*names, time: nil)
57
+ names = names.map(&:to_s)
58
+ names = names.map { |name| attribute_aliases[name] || name }
57
59
  attribute_names = timestamp_attributes_for_update_in_model
58
- attribute_names |= names.map(&:to_s)
60
+ attribute_names |= names
59
61
  attribute_names.index_with(time || current_time_from_proper_timezone)
60
62
  end
61
63
 
data/lib/active_record.rb CHANGED
@@ -34,7 +34,7 @@ require "active_record/deprecator"
34
34
  require "active_model/attribute_set"
35
35
  require "active_record/errors"
36
36
 
37
- # :include: activerecord/README.rdoc
37
+ # :include: ../README.rdoc
38
38
  module ActiveRecord
39
39
  extend ActiveSupport::Autoload
40
40
 
@@ -277,7 +277,7 @@ module ActiveRecord
277
277
  # with the global thread pool async query executor.
278
278
  def self.global_executor_concurrency=(global_executor_concurrency)
279
279
  if self.async_query_executor.nil? || self.async_query_executor == :multi_thread_pool
280
- raise ArgumentError, "`global_executor_concurrency` cannot be set when using the executor is nil or set to multi_thead_pool. For multiple thread pools, please set the concurrency in your database configuration."
280
+ raise ArgumentError, "`global_executor_concurrency` cannot be set when the executor is nil or set to `:multi_thread_pool`. For multiple thread pools, please set the concurrency in your database configuration."
281
281
  end
282
282
 
283
283
  @global_executor_concurrency = global_executor_concurrency
@@ -21,7 +21,11 @@ module Arel # :nodoc: all
21
21
  end
22
22
 
23
23
  def key=(key)
24
- @ast.key = Nodes.build_quoted(key)
24
+ @ast.key = if key.is_a?(Array)
25
+ key.map { |k| Nodes.build_quoted(k) }
26
+ else
27
+ Nodes.build_quoted(key)
28
+ end
25
29
  end
26
30
 
27
31
  def key
@@ -930,7 +930,8 @@ module Arel # :nodoc: all
930
930
  stmt.limit = nil
931
931
  stmt.offset = nil
932
932
  stmt.orders = []
933
- stmt.wheres = [Nodes::In.new(o.key, [build_subselect(o.key, o)])]
933
+ columns = Arel::Nodes::Grouping.new(o.key)
934
+ stmt.wheres = [Nodes::In.new(columns, [build_subselect(o.key, o)])]
934
935
  stmt.relation = o.relation.left if has_join_sources?(o)
935
936
  stmt.groups = o.groups unless o.groups.empty?
936
937
  stmt.havings = o.havings unless o.havings.empty?
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.1.3.1
4
+ version: 7.1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-02-21 00:00:00.000000000 Z
11
+ date: 2024-10-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 7.1.3.1
19
+ version: 7.1.4.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 7.1.3.1
26
+ version: 7.1.4.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activemodel
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 7.1.3.1
33
+ version: 7.1.4.1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 7.1.3.1
40
+ version: 7.1.4.1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: timeout
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -470,12 +470,12 @@ licenses:
470
470
  - MIT
471
471
  metadata:
472
472
  bug_tracker_uri: https://github.com/rails/rails/issues
473
- changelog_uri: https://github.com/rails/rails/blob/v7.1.3.1/activerecord/CHANGELOG.md
474
- documentation_uri: https://api.rubyonrails.org/v7.1.3.1/
473
+ changelog_uri: https://github.com/rails/rails/blob/v7.1.4.1/activerecord/CHANGELOG.md
474
+ documentation_uri: https://api.rubyonrails.org/v7.1.4.1/
475
475
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
476
- source_code_uri: https://github.com/rails/rails/tree/v7.1.3.1/activerecord
476
+ source_code_uri: https://github.com/rails/rails/tree/v7.1.4.1/activerecord
477
477
  rubygems_mfa_required: 'true'
478
- post_install_message:
478
+ post_install_message:
479
479
  rdoc_options:
480
480
  - "--main"
481
481
  - README.rdoc
@@ -492,8 +492,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
492
492
  - !ruby/object:Gem::Version
493
493
  version: '0'
494
494
  requirements: []
495
- rubygems_version: 3.4.10
496
- signing_key:
495
+ rubygems_version: 3.5.16
496
+ signing_key:
497
497
  specification_version: 4
498
498
  summary: Object-relational mapper framework (part of Rails).
499
499
  test_files: []