activerecord 7.2.2 → 8.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +173 -920
  3. data/README.rdoc +1 -1
  4. data/lib/active_record/associations/association.rb +25 -5
  5. data/lib/active_record/associations/builder/association.rb +7 -6
  6. data/lib/active_record/associations/collection_association.rb +10 -8
  7. data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
  8. data/lib/active_record/associations/has_many_through_association.rb +4 -9
  9. data/lib/active_record/associations/preloader/association.rb +2 -2
  10. data/lib/active_record/associations/singular_association.rb +8 -3
  11. data/lib/active_record/associations.rb +50 -32
  12. data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
  13. data/lib/active_record/autosave_association.rb +69 -27
  14. data/lib/active_record/callbacks.rb +1 -1
  15. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +16 -10
  16. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +0 -1
  17. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +0 -1
  18. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +0 -27
  19. data/lib/active_record/connection_adapters/abstract/database_statements.rb +90 -43
  20. data/lib/active_record/connection_adapters/abstract/query_cache.rb +8 -2
  21. data/lib/active_record/connection_adapters/abstract/quoting.rb +1 -1
  22. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +1 -1
  23. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +27 -6
  24. data/lib/active_record/connection_adapters/abstract/transaction.rb +15 -5
  25. data/lib/active_record/connection_adapters/abstract_adapter.rb +24 -25
  26. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +23 -45
  27. data/lib/active_record/connection_adapters/mysql/quoting.rb +0 -8
  28. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +2 -8
  29. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +43 -45
  30. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +42 -98
  31. data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -8
  32. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -42
  33. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
  34. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +0 -1
  35. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +50 -8
  36. data/lib/active_record/connection_adapters/postgresql_adapter.rb +41 -93
  37. data/lib/active_record/connection_adapters/schema_cache.rb +1 -3
  38. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +76 -100
  39. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +0 -6
  40. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +13 -0
  41. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +8 -1
  42. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +55 -12
  43. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +37 -67
  44. data/lib/active_record/connection_adapters/trilogy_adapter.rb +0 -17
  45. data/lib/active_record/connection_handling.rb +22 -0
  46. data/lib/active_record/core.rb +7 -32
  47. data/lib/active_record/encryption/config.rb +3 -1
  48. data/lib/active_record/encryption/encryptable_record.rb +4 -4
  49. data/lib/active_record/encryption/encrypted_attribute_type.rb +10 -1
  50. data/lib/active_record/encryption/encryptor.rb +15 -8
  51. data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
  52. data/lib/active_record/encryption/scheme.rb +8 -1
  53. data/lib/active_record/errors.rb +13 -5
  54. data/lib/active_record/fixtures.rb +0 -1
  55. data/lib/active_record/future_result.rb +14 -10
  56. data/lib/active_record/gem_version.rb +4 -4
  57. data/lib/active_record/insert_all.rb +1 -1
  58. data/lib/active_record/marshalling.rb +1 -4
  59. data/lib/active_record/migration/command_recorder.rb +22 -5
  60. data/lib/active_record/migration/compatibility.rb +5 -2
  61. data/lib/active_record/migration.rb +35 -33
  62. data/lib/active_record/model_schema.rb +1 -1
  63. data/lib/active_record/nested_attributes.rb +4 -6
  64. data/lib/active_record/persistence.rb +128 -130
  65. data/lib/active_record/query_cache.rb +5 -4
  66. data/lib/active_record/query_logs.rb +98 -40
  67. data/lib/active_record/query_logs_formatter.rb +17 -28
  68. data/lib/active_record/querying.rb +6 -6
  69. data/lib/active_record/railtie.rb +3 -4
  70. data/lib/active_record/reflection.rb +9 -7
  71. data/lib/active_record/relation/batches/batch_enumerator.rb +4 -3
  72. data/lib/active_record/relation/batches.rb +132 -72
  73. data/lib/active_record/relation/calculations.rb +25 -20
  74. data/lib/active_record/relation/delegation.rb +25 -14
  75. data/lib/active_record/relation/finder_methods.rb +18 -18
  76. data/lib/active_record/relation/merger.rb +8 -8
  77. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -1
  78. data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
  79. data/lib/active_record/relation/predicate_builder.rb +5 -0
  80. data/lib/active_record/relation/query_methods.rb +81 -75
  81. data/lib/active_record/relation/record_fetch_warning.rb +2 -2
  82. data/lib/active_record/relation/spawn_methods.rb +1 -1
  83. data/lib/active_record/relation.rb +72 -61
  84. data/lib/active_record/result.rb +68 -7
  85. data/lib/active_record/sanitization.rb +7 -6
  86. data/lib/active_record/schema_dumper.rb +5 -0
  87. data/lib/active_record/schema_migration.rb +2 -1
  88. data/lib/active_record/scoping/named.rb +5 -2
  89. data/lib/active_record/statement_cache.rb +12 -12
  90. data/lib/active_record/store.rb +7 -3
  91. data/lib/active_record/tasks/database_tasks.rb +24 -15
  92. data/lib/active_record/tasks/mysql_database_tasks.rb +0 -2
  93. data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -2
  94. data/lib/active_record/test_fixtures.rb +12 -0
  95. data/lib/active_record/testing/query_assertions.rb +2 -2
  96. data/lib/active_record/token_for.rb +1 -1
  97. data/lib/active_record/validations/uniqueness.rb +8 -8
  98. data/lib/active_record.rb +15 -0
  99. data/lib/arel/collectors/bind.rb +1 -1
  100. data/lib/arel/visitors/sqlite.rb +0 -25
  101. metadata +10 -10
@@ -178,22 +178,9 @@ module ActiveRecord
178
178
  dump_db_configs = []
179
179
 
180
180
  each_current_configuration(env) do |db_config|
181
- with_temporary_pool(db_config) do
182
- begin
183
- database_initialized = migration_connection_pool.schema_migration.table_exists?
184
- rescue ActiveRecord::NoDatabaseError
185
- create(db_config)
186
- retry
187
- end
181
+ database_initialized = initialize_database(db_config)
188
182
 
189
- unless database_initialized
190
- if File.exist?(schema_dump_path(db_config))
191
- load_schema(db_config, ActiveRecord.schema_format, nil)
192
- end
193
-
194
- seed = true
195
- end
196
- end
183
+ seed = true if database_initialized
197
184
  end
198
185
 
199
186
  each_current_environment(env) do |environment|
@@ -259,6 +246,8 @@ module ActiveRecord
259
246
 
260
247
  check_target_version
261
248
 
249
+ initialize_database(migration_connection_pool.db_config)
250
+
262
251
  migration_connection_pool.migration_context.migrate(target_version) do |migration|
263
252
  if version.blank?
264
253
  scope.blank? || scope == migration.scope
@@ -667,6 +656,26 @@ module ActiveRecord
667
656
  rescue ActiveRecord::NoDatabaseError
668
657
  end
669
658
  end
659
+
660
+ def initialize_database(db_config)
661
+ with_temporary_pool(db_config) do
662
+ begin
663
+ database_already_initialized = migration_connection_pool.schema_migration.table_exists?
664
+ rescue ActiveRecord::NoDatabaseError
665
+ create(db_config)
666
+ retry
667
+ end
668
+
669
+ unless database_already_initialized
670
+ schema_dump_path = schema_dump_path(db_config)
671
+ if schema_dump_path && File.exist?(schema_dump_path)
672
+ load_schema(db_config, ActiveRecord.schema_format, nil)
673
+ end
674
+ end
675
+
676
+ !database_already_initialized
677
+ end
678
+ end
670
679
  end
671
680
  end
672
681
  end
@@ -3,8 +3,6 @@
3
3
  module ActiveRecord
4
4
  module Tasks # :nodoc:
5
5
  class MySQLDatabaseTasks # :nodoc:
6
- ER_DB_CREATE_EXISTS = 1007
7
-
8
6
  def self.using_database_configurations?
9
7
  true
10
8
  end
@@ -50,9 +50,9 @@ module ActiveRecord
50
50
  if ignore_tables.any?
51
51
  ignore_tables = connection.data_sources.select { |table| ignore_tables.any? { |pattern| pattern === table } }
52
52
  condition = ignore_tables.map { |table| connection.quote(table) }.join(", ")
53
- args << "SELECT sql FROM sqlite_master WHERE tbl_name NOT IN (#{condition}) ORDER BY tbl_name, type DESC, name"
53
+ args << "SELECT sql || ';' FROM sqlite_master WHERE tbl_name NOT IN (#{condition}) ORDER BY tbl_name, type DESC, name"
54
54
  else
55
- args << ".schema"
55
+ args << ".schema --nosys"
56
56
  end
57
57
  run_cmd("sqlite3", args, filename)
58
58
  end
@@ -137,12 +137,15 @@ module ActiveRecord
137
137
  invalidate_already_loaded_fixtures
138
138
  @loaded_fixtures = load_fixtures(config)
139
139
  end
140
+ setup_asynchronous_queries_session
140
141
 
141
142
  # Instantiate fixtures for every test if requested.
142
143
  instantiate_fixtures if use_instantiated_fixtures
143
144
  end
144
145
 
145
146
  def teardown_fixtures
147
+ teardown_asynchronous_queries_session
148
+
146
149
  # Rollback changes if a transaction is active.
147
150
  if run_in_transaction?
148
151
  teardown_transactional_fixtures
@@ -154,6 +157,14 @@ module ActiveRecord
154
157
  ActiveRecord::Base.connection_handler.clear_active_connections!(:all)
155
158
  end
156
159
 
160
+ def setup_asynchronous_queries_session
161
+ @_async_queries_session = ActiveRecord::Base.asynchronous_queries_tracker.start_session
162
+ end
163
+
164
+ def teardown_asynchronous_queries_session
165
+ ActiveRecord::Base.asynchronous_queries_tracker.finalize_session(true) if @_async_queries_session
166
+ end
167
+
157
168
  def invalidate_already_loaded_fixtures
158
169
  @@already_loaded_fixtures.clear
159
170
  end
@@ -190,6 +201,7 @@ module ActiveRecord
190
201
 
191
202
  def teardown_transactional_fixtures
192
203
  ActiveSupport::Notifications.unsubscribe(@connection_subscriber) if @connection_subscriber
204
+
193
205
  unless @fixture_connection_pools.map(&:unpin_connection!).all?
194
206
  # Something caused the transaction to be committed or rolled back
195
207
  # We can no longer trust the database is in a clean state.
@@ -52,7 +52,7 @@ module ActiveRecord
52
52
  # assert_queries_match(/LIMIT \?/) { Post.first }
53
53
  #
54
54
  # If the +:include_schema+ option is provided, any queries (including schema related)
55
- # that match the matcher are considered.
55
+ # that match the matcher are considered.
56
56
  #
57
57
  # assert_queries_match(/FROM pg_attribute/i, include_schema: true) { Post.columns }
58
58
  #
@@ -80,7 +80,7 @@ module ActiveRecord
80
80
  # assert_no_queries_match(/SELECT/i) { post.comments }
81
81
  #
82
82
  # If the +:include_schema+ option is provided, any queries (including schema related)
83
- # that match the matcher are counted.
83
+ # that match the matcher are counted.
84
84
  #
85
85
  # assert_no_queries_match(/FROM pg_attribute/i, include_schema: true) { Post.columns }
86
86
  #
@@ -40,7 +40,7 @@ module ActiveRecord
40
40
  # +nil+ if the token is invalid or the record was not found.
41
41
  def find_by_token_for(purpose, token)
42
42
  raise UnknownPrimaryKey.new(self) unless model.primary_key
43
- model.token_definitions.fetch(purpose).resolve_token(token) { |id| find_by(model.primary_key => id) }
43
+ model.token_definitions.fetch(purpose).resolve_token(token) { |id| find_by(model.primary_key => [id]) }
44
44
  end
45
45
 
46
46
  # Finds a record using a given +token+ for a predefined +purpose+. Raises
@@ -54,17 +54,17 @@ module ActiveRecord
54
54
  private
55
55
  # The check for an existing value should be run from a class that
56
56
  # isn't abstract. This means working down from the current class
57
- # (self), to the first non-abstract class. Since classes don't know
58
- # their subclasses, we have to build the hierarchy between self and
59
- # the record's class.
57
+ # (self), to the first non-abstract class.
60
58
  def find_finder_class_for(record)
61
- class_hierarchy = [record.class]
62
-
63
- while class_hierarchy.first != @klass
64
- class_hierarchy.unshift(class_hierarchy.first.superclass)
59
+ current_class = record.class
60
+ found_class = nil
61
+ loop do
62
+ found_class = current_class unless current_class.abstract_class?
63
+ break if current_class == @klass
64
+ current_class = current_class.superclass
65
65
  end
66
66
 
67
- class_hierarchy.detect { |klass| !klass.abstract_class? }
67
+ found_class
68
68
  end
69
69
 
70
70
  def validation_needed?(klass, record, attribute)
data/lib/active_record.rb CHANGED
@@ -29,6 +29,7 @@ require "active_support/ordered_options"
29
29
  require "active_model"
30
30
  require "arel"
31
31
  require "yaml"
32
+ require "zlib"
32
33
 
33
34
  require "active_record/version"
34
35
  require "active_record/deprecator"
@@ -196,6 +197,20 @@ module ActiveRecord
196
197
  singleton_class.attr_accessor :schema_cache_ignored_tables
197
198
  self.schema_cache_ignored_tables = []
198
199
 
200
+ # Checks to see if the +table_name+ is ignored by checking
201
+ # against the +schema_cache_ignored_tables+ option.
202
+ #
203
+ # ActiveRecord.schema_cache_ignored_table?(:developers)
204
+ #
205
+ def self.schema_cache_ignored_table?(table_name)
206
+ ActiveRecord.schema_cache_ignored_tables.any? do |ignored|
207
+ ignored === table_name
208
+ end
209
+ end
210
+
211
+ singleton_class.attr_accessor :database_cli
212
+ self.database_cli = { postgresql: "psql", mysql: %w[mysql mysql5], sqlite: "sqlite3" }
213
+
199
214
  singleton_class.attr_reader :default_timezone
200
215
 
201
216
  # Determines whether to use Time.utc (using :utc) or Time.local (using :local) when pulling
@@ -13,7 +13,7 @@ module Arel # :nodoc: all
13
13
  self
14
14
  end
15
15
 
16
- def add_bind(bind)
16
+ def add_bind(bind, &)
17
17
  @binds << bind
18
18
  self
19
19
  end
@@ -33,31 +33,6 @@ module Arel # :nodoc: all
33
33
  collector << " IS NOT "
34
34
  visit o.right, collector
35
35
  end
36
-
37
- # Queries used in UNION should not be wrapped by parentheses,
38
- # because it is an invalid syntax in SQLite.
39
- def infix_value_with_paren(o, collector, value, suppress_parens = false)
40
- collector << "( " unless suppress_parens
41
-
42
- left = o.left.is_a?(Nodes::Grouping) ? o.left.expr : o.left
43
- collector = if left.class == o.class
44
- infix_value_with_paren(left, collector, value, true)
45
- else
46
- grouping_parentheses left, collector, false
47
- end
48
-
49
- collector << value
50
-
51
- right = o.right.is_a?(Nodes::Grouping) ? o.right.expr : o.right
52
- collector = if right.class == o.class
53
- infix_value_with_paren(right, collector, value, true)
54
- else
55
- grouping_parentheses right, collector, false
56
- end
57
-
58
- collector << " )" unless suppress_parens
59
- collector
60
- end
61
36
  end
62
37
  end
63
38
  end
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.2.2
4
+ version: 8.0.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-10-31 00:00:00.000000000 Z
11
+ date: 2024-09-26 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.2.2
19
+ version: 8.0.0.beta1
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.2.2
26
+ version: 8.0.0.beta1
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.2.2
33
+ version: 8.0.0.beta1
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.2.2
40
+ version: 8.0.0.beta1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: timeout
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -476,10 +476,10 @@ licenses:
476
476
  - MIT
477
477
  metadata:
478
478
  bug_tracker_uri: https://github.com/rails/rails/issues
479
- changelog_uri: https://github.com/rails/rails/blob/v7.2.2/activerecord/CHANGELOG.md
480
- documentation_uri: https://api.rubyonrails.org/v7.2.2/
479
+ changelog_uri: https://github.com/rails/rails/blob/v8.0.0.beta1/activerecord/CHANGELOG.md
480
+ documentation_uri: https://api.rubyonrails.org/v8.0.0.beta1/
481
481
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
482
- source_code_uri: https://github.com/rails/rails/tree/v7.2.2/activerecord
482
+ source_code_uri: https://github.com/rails/rails/tree/v8.0.0.beta1/activerecord
483
483
  rubygems_mfa_required: 'true'
484
484
  post_install_message:
485
485
  rdoc_options:
@@ -491,7 +491,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
491
491
  requirements:
492
492
  - - ">="
493
493
  - !ruby/object:Gem::Version
494
- version: 3.1.0
494
+ version: 3.2.0
495
495
  required_rubygems_version: !ruby/object:Gem::Requirement
496
496
  requirements:
497
497
  - - ">="