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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +266 -0
- data/lib/active_record/associations/belongs_to_association.rb +4 -4
- data/lib/active_record/associations/collection_association.rb +4 -4
- data/lib/active_record/associations/has_many_association.rb +2 -2
- data/lib/active_record/associations/has_one_association.rb +2 -2
- data/lib/active_record/associations/join_dependency.rb +6 -8
- data/lib/active_record/associations.rb +6 -0
- data/lib/active_record/attribute_methods/dirty.rb +2 -2
- data/lib/active_record/attribute_methods/read.rb +3 -3
- data/lib/active_record/attribute_methods/write.rb +3 -3
- data/lib/active_record/attribute_methods.rb +46 -6
- data/lib/active_record/autosave_association.rb +5 -2
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +8 -1
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +8 -4
- data/lib/active_record/connection_adapters/abstract_adapter.rb +14 -15
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +37 -13
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +2 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +16 -10
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +2 -2
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +16 -20
- data/lib/active_record/core.rb +7 -2
- data/lib/active_record/counter_cache.rb +7 -3
- data/lib/active_record/database_configurations/hash_config.rb +6 -2
- data/lib/active_record/delegated_type.rb +6 -6
- data/lib/active_record/destroy_association_async_job.rb +1 -1
- data/lib/active_record/encryption/encrypted_attribute_type.rb +2 -2
- data/lib/active_record/encryption/scheme.rb +8 -4
- data/lib/active_record/future_result.rb +9 -0
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/locking/optimistic.rb +1 -1
- data/lib/active_record/marshalling.rb +1 -1
- data/lib/active_record/message_pack.rb +1 -1
- data/lib/active_record/migration/compatibility.rb +6 -0
- data/lib/active_record/model_schema.rb +6 -2
- data/lib/active_record/persistence.rb +2 -2
- data/lib/active_record/query_cache.rb +1 -1
- data/lib/active_record/query_logs_formatter.rb +1 -1
- data/lib/active_record/railtie.rb +10 -13
- data/lib/active_record/railties/databases.rake +2 -2
- data/lib/active_record/reflection.rb +8 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +6 -1
- data/lib/active_record/relation/query_methods.rb +21 -7
- data/lib/active_record/relation.rb +13 -3
- data/lib/active_record/result.rb +1 -1
- data/lib/active_record/tasks/database_tasks.rb +19 -8
- data/lib/active_record/test_fixtures.rb +1 -0
- data/lib/active_record/timestamp.rb +3 -1
- data/lib/active_record.rb +2 -2
- data/lib/arel/tree_manager.rb +5 -1
- data/lib/arel/visitors/to_sql.rb +2 -1
- 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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
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
|
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
|
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 ||=
|
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
|
-
|
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
|
-
|
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
|
1918
|
-
|
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
|
-
|
1923
|
-
|
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
|
-
|
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
|
-
|
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
|
988
|
+
return FutureResult.wrap([])
|
979
989
|
else
|
980
990
|
return []
|
981
991
|
end
|
data/lib/active_record/result.rb
CHANGED
@@ -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
|
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
|
-
|
197
|
-
|
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(
|
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
|
-
|
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
|
@@ -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
|
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:
|
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
|
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
|
data/lib/arel/tree_manager.rb
CHANGED
data/lib/arel/visitors/to_sql.rb
CHANGED
@@ -930,7 +930,8 @@ module Arel # :nodoc: all
|
|
930
930
|
stmt.limit = nil
|
931
931
|
stmt.offset = nil
|
932
932
|
stmt.orders = []
|
933
|
-
|
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.
|
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-
|
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.
|
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.
|
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.
|
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.
|
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.
|
474
|
-
documentation_uri: https://api.rubyonrails.org/v7.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.
|
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.
|
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: []
|