activerecord 7.2.2.1 → 8.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +564 -753
- data/README.rdoc +2 -2
- data/lib/active_record/association_relation.rb +2 -1
- data/lib/active_record/associations/alias_tracker.rb +6 -4
- data/lib/active_record/associations/association.rb +35 -11
- data/lib/active_record/associations/belongs_to_association.rb +18 -2
- data/lib/active_record/associations/builder/association.rb +23 -11
- data/lib/active_record/associations/builder/belongs_to.rb +17 -4
- data/lib/active_record/associations/builder/collection_association.rb +7 -3
- data/lib/active_record/associations/builder/has_one.rb +1 -1
- data/lib/active_record/associations/builder/singular_association.rb +33 -5
- data/lib/active_record/associations/collection_association.rb +10 -8
- data/lib/active_record/associations/collection_proxy.rb +22 -4
- data/lib/active_record/associations/deprecation.rb +88 -0
- data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
- data/lib/active_record/associations/errors.rb +3 -0
- data/lib/active_record/associations/has_many_through_association.rb +3 -2
- data/lib/active_record/associations/join_dependency/join_association.rb +25 -27
- data/lib/active_record/associations/join_dependency.rb +4 -2
- data/lib/active_record/associations/preloader/association.rb +2 -2
- data/lib/active_record/associations/preloader/batch.rb +7 -1
- data/lib/active_record/associations/preloader/branch.rb +1 -0
- data/lib/active_record/associations/singular_association.rb +8 -3
- data/lib/active_record/associations.rb +192 -24
- data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
- data/lib/active_record/attribute_methods/primary_key.rb +4 -8
- data/lib/active_record/attribute_methods/query.rb +34 -0
- data/lib/active_record/attribute_methods/serialization.rb +17 -4
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -14
- data/lib/active_record/attribute_methods.rb +24 -19
- data/lib/active_record/attributes.rb +40 -26
- data/lib/active_record/autosave_association.rb +91 -39
- data/lib/active_record/base.rb +3 -4
- data/lib/active_record/coders/json.rb +14 -5
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +35 -28
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +16 -4
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +51 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +458 -117
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +136 -74
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +44 -11
- data/lib/active_record/connection_adapters/abstract/quoting.rb +16 -25
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +11 -7
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +37 -36
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +122 -29
- data/lib/active_record/connection_adapters/abstract/transaction.rb +40 -8
- data/lib/active_record/connection_adapters/abstract_adapter.rb +175 -87
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +77 -58
- data/lib/active_record/connection_adapters/column.rb +17 -4
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +4 -4
- data/lib/active_record/connection_adapters/mysql/quoting.rb +7 -9
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +41 -10
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +73 -46
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +89 -94
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +10 -11
- data/lib/active_record/connection_adapters/pool_config.rb +7 -7
- data/lib/active_record/connection_adapters/postgresql/column.rb +4 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +76 -45
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +21 -10
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +9 -17
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +28 -45
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +69 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +140 -64
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +83 -105
- data/lib/active_record/connection_adapters/schema_cache.rb +3 -5
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +90 -98
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +13 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +0 -6
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +27 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +13 -13
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +112 -42
- data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +38 -67
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +2 -19
- data/lib/active_record/connection_adapters.rb +1 -56
- data/lib/active_record/connection_handling.rb +37 -10
- data/lib/active_record/core.rb +61 -25
- data/lib/active_record/counter_cache.rb +34 -9
- data/lib/active_record/database_configurations/connection_url_resolver.rb +3 -1
- data/lib/active_record/database_configurations/database_config.rb +9 -1
- data/lib/active_record/database_configurations/hash_config.rb +67 -9
- data/lib/active_record/database_configurations/url_config.rb +13 -3
- data/lib/active_record/database_configurations.rb +7 -3
- data/lib/active_record/delegated_type.rb +19 -19
- data/lib/active_record/dynamic_matchers.rb +54 -69
- data/lib/active_record/encryption/config.rb +3 -1
- data/lib/active_record/encryption/encryptable_record.rb +9 -9
- data/lib/active_record/encryption/encrypted_attribute_type.rb +12 -3
- data/lib/active_record/encryption/encryptor.rb +49 -28
- data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
- data/lib/active_record/encryption/scheme.rb +9 -2
- data/lib/active_record/enum.rb +46 -42
- data/lib/active_record/errors.rb +36 -12
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/explain_registry.rb +51 -2
- data/lib/active_record/filter_attribute_handler.rb +73 -0
- data/lib/active_record/fixture_set/table_row.rb +19 -2
- data/lib/active_record/fixtures.rb +2 -4
- data/lib/active_record/future_result.rb +13 -9
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +1 -1
- data/lib/active_record/insert_all.rb +12 -7
- data/lib/active_record/locking/optimistic.rb +8 -1
- data/lib/active_record/locking/pessimistic.rb +5 -0
- data/lib/active_record/log_subscriber.rb +3 -13
- data/lib/active_record/middleware/shard_selector.rb +34 -17
- data/lib/active_record/migration/command_recorder.rb +44 -11
- data/lib/active_record/migration/compatibility.rb +37 -24
- data/lib/active_record/migration/default_schema_versions_formatter.rb +30 -0
- data/lib/active_record/migration.rb +50 -43
- data/lib/active_record/model_schema.rb +38 -13
- data/lib/active_record/nested_attributes.rb +6 -6
- data/lib/active_record/persistence.rb +162 -133
- data/lib/active_record/query_cache.rb +22 -15
- data/lib/active_record/query_logs.rb +104 -52
- data/lib/active_record/query_logs_formatter.rb +17 -28
- data/lib/active_record/querying.rb +12 -12
- data/lib/active_record/railtie.rb +37 -32
- data/lib/active_record/railties/controller_runtime.rb +11 -6
- data/lib/active_record/railties/databases.rake +26 -37
- data/lib/active_record/railties/job_checkpoints.rb +15 -0
- data/lib/active_record/railties/job_runtime.rb +10 -11
- data/lib/active_record/reflection.rb +53 -21
- data/lib/active_record/relation/batches/batch_enumerator.rb +4 -3
- data/lib/active_record/relation/batches.rb +147 -73
- data/lib/active_record/relation/calculations.rb +80 -63
- data/lib/active_record/relation/delegation.rb +25 -15
- data/lib/active_record/relation/finder_methods.rb +54 -37
- data/lib/active_record/relation/merger.rb +8 -8
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +11 -9
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +8 -8
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
- data/lib/active_record/relation/predicate_builder.rb +22 -7
- data/lib/active_record/relation/query_attribute.rb +4 -2
- data/lib/active_record/relation/query_methods.rb +156 -95
- data/lib/active_record/relation/spawn_methods.rb +7 -7
- data/lib/active_record/relation/where_clause.rb +10 -11
- data/lib/active_record/relation.rb +122 -80
- data/lib/active_record/result.rb +109 -24
- data/lib/active_record/runtime_registry.rb +42 -58
- data/lib/active_record/sanitization.rb +9 -6
- data/lib/active_record/schema_dumper.rb +47 -22
- data/lib/active_record/schema_migration.rb +2 -1
- data/lib/active_record/scoping/named.rb +5 -2
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/secure_token.rb +3 -3
- data/lib/active_record/signed_id.rb +47 -18
- data/lib/active_record/statement_cache.rb +24 -20
- data/lib/active_record/store.rb +51 -22
- data/lib/active_record/structured_event_subscriber.rb +85 -0
- data/lib/active_record/table_metadata.rb +6 -23
- data/lib/active_record/tasks/abstract_tasks.rb +76 -0
- data/lib/active_record/tasks/database_tasks.rb +85 -85
- data/lib/active_record/tasks/mysql_database_tasks.rb +3 -42
- data/lib/active_record/tasks/postgresql_database_tasks.rb +14 -40
- data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -28
- data/lib/active_record/test_databases.rb +14 -4
- data/lib/active_record/test_fixtures.rb +39 -2
- data/lib/active_record/testing/query_assertions.rb +8 -2
- data/lib/active_record/timestamp.rb +4 -2
- data/lib/active_record/token_for.rb +1 -1
- data/lib/active_record/transaction.rb +2 -5
- data/lib/active_record/transactions.rb +39 -16
- data/lib/active_record/type/hash_lookup_type_map.rb +2 -1
- data/lib/active_record/type/internal/timezone.rb +7 -0
- data/lib/active_record/type/json.rb +15 -2
- data/lib/active_record/type/serialized.rb +11 -4
- data/lib/active_record/type/type_map.rb +1 -1
- data/lib/active_record/type_caster/connection.rb +2 -1
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record/validations/uniqueness.rb +8 -8
- data/lib/active_record.rb +85 -50
- data/lib/arel/alias_predication.rb +2 -0
- data/lib/arel/collectors/bind.rb +2 -2
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +2 -2
- data/lib/arel/crud.rb +8 -11
- data/lib/arel/delete_manager.rb +5 -0
- data/lib/arel/nodes/binary.rb +1 -1
- data/lib/arel/nodes/count.rb +2 -2
- data/lib/arel/nodes/delete_statement.rb +4 -2
- data/lib/arel/nodes/function.rb +4 -10
- data/lib/arel/nodes/named_function.rb +2 -2
- data/lib/arel/nodes/node.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +1 -1
- data/lib/arel/nodes/update_statement.rb +4 -2
- data/lib/arel/nodes.rb +0 -2
- data/lib/arel/select_manager.rb +13 -4
- data/lib/arel/table.rb +3 -7
- data/lib/arel/update_manager.rb +5 -0
- data/lib/arel/visitors/dot.rb +2 -3
- data/lib/arel/visitors/postgresql.rb +55 -0
- data/lib/arel/visitors/sqlite.rb +55 -8
- data/lib/arel/visitors/to_sql.rb +6 -22
- data/lib/arel.rb +3 -1
- data/lib/rails/generators/active_record/application_record/USAGE +1 -1
- metadata +17 -17
- data/lib/active_record/explain_subscriber.rb +0 -34
- data/lib/active_record/normalization.rb +0 -163
- data/lib/active_record/relation/record_fetch_warning.rb +0 -52
|
@@ -9,25 +9,40 @@ module ActiveRecord
|
|
|
9
9
|
# shard to switch to and allows for applications to write custom strategies
|
|
10
10
|
# for swapping if needed.
|
|
11
11
|
#
|
|
12
|
-
#
|
|
13
|
-
# that can be used by the middleware to alter behavior. +lock+ is
|
|
14
|
-
# true by default and will prohibit the request from switching shards once
|
|
15
|
-
# inside the block. If +lock+ is false, then shard swapping will be allowed.
|
|
16
|
-
# For tenant based sharding, +lock+ should always be true to prevent application
|
|
17
|
-
# code from mistakenly switching between tenants.
|
|
12
|
+
# == Setup
|
|
18
13
|
#
|
|
19
|
-
#
|
|
14
|
+
# Applications must provide a resolver that will provide application-specific logic for
|
|
15
|
+
# selecting the appropriate shard. Setting +config.active_record.shard_resolver+ will cause
|
|
16
|
+
# Rails to add ShardSelector to the default middleware stack.
|
|
20
17
|
#
|
|
21
|
-
#
|
|
18
|
+
# The resolver, along with any configuration options, can be set in the application
|
|
19
|
+
# configuration using an initializer like so:
|
|
22
20
|
#
|
|
23
|
-
#
|
|
24
|
-
#
|
|
21
|
+
# Rails.application.configure do
|
|
22
|
+
# config.active_record.shard_selector = { lock: false, class_name: "AnimalsRecord" }
|
|
23
|
+
# config.active_record.shard_resolver = ->(request) {
|
|
24
|
+
# subdomain = request.subdomain
|
|
25
|
+
# tenant = Tenant.find_by_subdomain!(subdomain)
|
|
26
|
+
# tenant.shard
|
|
27
|
+
# }
|
|
28
|
+
# end
|
|
29
|
+
#
|
|
30
|
+
# == Configuration
|
|
31
|
+
#
|
|
32
|
+
# The behavior of ShardSelector can be altered through some configuration options.
|
|
33
|
+
#
|
|
34
|
+
# [+lock:+]
|
|
35
|
+
# +lock+ is true by default and will prohibit the request from switching shards once inside
|
|
36
|
+
# the block. If +lock+ is false, then shard switching will be allowed. For tenant based
|
|
37
|
+
# sharding, +lock+ should always be true to prevent application code from mistakenly switching
|
|
38
|
+
# between tenants.
|
|
39
|
+
#
|
|
40
|
+
# [+class_name:+]
|
|
41
|
+
# +class_name+ is the name of the abstract connection class to switch. By
|
|
42
|
+
# default, the ShardSelector will use ActiveRecord::Base, but if the
|
|
43
|
+
# application has multiple databases, then this option should be set to
|
|
44
|
+
# the name of the sharded database's abstract connection class.
|
|
25
45
|
#
|
|
26
|
-
# config.active_record.shard_resolver = ->(request) {
|
|
27
|
-
# subdomain = request.subdomain
|
|
28
|
-
# tenant = Tenant.find_by_subdomain!(subdomain)
|
|
29
|
-
# tenant.shard
|
|
30
|
-
# }
|
|
31
46
|
class ShardSelector
|
|
32
47
|
def initialize(app, resolver, options = {})
|
|
33
48
|
@app = app
|
|
@@ -53,8 +68,10 @@ module ActiveRecord
|
|
|
53
68
|
end
|
|
54
69
|
|
|
55
70
|
def set_shard(shard, &block)
|
|
56
|
-
ActiveRecord::Base
|
|
57
|
-
|
|
71
|
+
klass = options[:class_name]&.constantize || ActiveRecord::Base
|
|
72
|
+
|
|
73
|
+
klass.connected_to(shard: shard.to_sym) do
|
|
74
|
+
klass.prohibit_shard_swapping(options.fetch(:lock, true), &block)
|
|
58
75
|
end
|
|
59
76
|
end
|
|
60
77
|
end
|
|
@@ -22,10 +22,12 @@ module ActiveRecord
|
|
|
22
22
|
# * change_table_comment (must supply a +:from+ and +:to+ option)
|
|
23
23
|
# * create_enum
|
|
24
24
|
# * create_join_table
|
|
25
|
+
# * create_virtual_table
|
|
25
26
|
# * create_table
|
|
26
27
|
# * disable_extension
|
|
27
28
|
# * drop_enum (must supply a list of values)
|
|
28
29
|
# * drop_join_table
|
|
30
|
+
# * drop_virtual_table (must supply options)
|
|
29
31
|
# * drop_table (must supply a block)
|
|
30
32
|
# * enable_extension
|
|
31
33
|
# * remove_column (must supply a type)
|
|
@@ -38,10 +40,12 @@ module ActiveRecord
|
|
|
38
40
|
# * remove_reference
|
|
39
41
|
# * remove_timestamps
|
|
40
42
|
# * rename_column
|
|
41
|
-
# * rename_enum
|
|
43
|
+
# * rename_enum
|
|
42
44
|
# * rename_enum_value (must supply a +:from+ and +:to+ option)
|
|
43
45
|
# * rename_index
|
|
44
46
|
# * rename_table
|
|
47
|
+
# * enable_index
|
|
48
|
+
# * disable_index
|
|
45
49
|
class CommandRecorder
|
|
46
50
|
ReversibleAndIrreversibleMethods = [
|
|
47
51
|
:create_table, :create_join_table, :rename_table, :add_column, :remove_column,
|
|
@@ -55,6 +59,9 @@ module ActiveRecord
|
|
|
55
59
|
:add_exclusion_constraint, :remove_exclusion_constraint,
|
|
56
60
|
:add_unique_constraint, :remove_unique_constraint,
|
|
57
61
|
:create_enum, :drop_enum, :rename_enum, :add_enum_value, :rename_enum_value,
|
|
62
|
+
:create_schema, :drop_schema,
|
|
63
|
+
:create_virtual_table, :drop_virtual_table,
|
|
64
|
+
:enable_index, :disable_index
|
|
58
65
|
]
|
|
59
66
|
include JoinTable
|
|
60
67
|
|
|
@@ -163,7 +170,9 @@ module ActiveRecord
|
|
|
163
170
|
add_exclusion_constraint: :remove_exclusion_constraint,
|
|
164
171
|
add_unique_constraint: :remove_unique_constraint,
|
|
165
172
|
enable_extension: :disable_extension,
|
|
166
|
-
create_enum: :drop_enum
|
|
173
|
+
create_enum: :drop_enum,
|
|
174
|
+
create_schema: :drop_schema,
|
|
175
|
+
create_virtual_table: :drop_virtual_table
|
|
167
176
|
}.each do |cmd, inv|
|
|
168
177
|
[[inv, cmd], [cmd, inv]].uniq.each do |method, inverse|
|
|
169
178
|
class_eval <<-EOV, __FILE__, __LINE__ + 1
|
|
@@ -177,6 +186,16 @@ module ActiveRecord
|
|
|
177
186
|
|
|
178
187
|
include StraightReversions
|
|
179
188
|
|
|
189
|
+
def invert_enable_index(args)
|
|
190
|
+
table_name, index_name = args
|
|
191
|
+
[:disable_index, [table_name, index_name]]
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def invert_disable_index(args)
|
|
195
|
+
table_name, index_name = args
|
|
196
|
+
[:enable_index, [table_name, index_name]]
|
|
197
|
+
end
|
|
198
|
+
|
|
180
199
|
def invert_transaction(args, &block)
|
|
181
200
|
sub_recorder = CommandRecorder.new(delegate)
|
|
182
201
|
sub_recorder.revert(&block)
|
|
@@ -196,13 +215,20 @@ module ActiveRecord
|
|
|
196
215
|
end
|
|
197
216
|
|
|
198
217
|
def invert_drop_table(args, &block)
|
|
199
|
-
|
|
200
|
-
|
|
218
|
+
options = args.extract_options!
|
|
219
|
+
options.delete(:if_exists)
|
|
220
|
+
|
|
221
|
+
if args.size > 1
|
|
222
|
+
raise ActiveRecord::IrreversibleMigration, "To avoid mistakes, drop_table is only reversible if given a single table name."
|
|
201
223
|
end
|
|
202
|
-
|
|
224
|
+
|
|
225
|
+
if args.size == 1 && options == {} && block == nil
|
|
203
226
|
raise ActiveRecord::IrreversibleMigration, "To avoid mistakes, drop_table is only reversible if given options or a block (can be empty)."
|
|
204
227
|
end
|
|
205
|
-
|
|
228
|
+
|
|
229
|
+
args << options unless options.empty?
|
|
230
|
+
|
|
231
|
+
super(args, &block)
|
|
206
232
|
end
|
|
207
233
|
|
|
208
234
|
def invert_rename_table(args)
|
|
@@ -353,13 +379,13 @@ module ActiveRecord
|
|
|
353
379
|
end
|
|
354
380
|
|
|
355
381
|
def invert_rename_enum(args)
|
|
356
|
-
name,
|
|
382
|
+
name, new_name, = args
|
|
357
383
|
|
|
358
|
-
|
|
359
|
-
|
|
384
|
+
if new_name.is_a?(Hash) && new_name.key?(:to)
|
|
385
|
+
new_name = new_name[:to]
|
|
360
386
|
end
|
|
361
387
|
|
|
362
|
-
[:rename_enum, [
|
|
388
|
+
[:rename_enum, [new_name, name]]
|
|
363
389
|
end
|
|
364
390
|
|
|
365
391
|
def invert_rename_enum_value(args)
|
|
@@ -369,7 +395,14 @@ module ActiveRecord
|
|
|
369
395
|
raise ActiveRecord::IrreversibleMigration, "rename_enum_value is only reversible if given a :from and :to option."
|
|
370
396
|
end
|
|
371
397
|
|
|
372
|
-
[:
|
|
398
|
+
options[:to], options[:from] = options[:from], options[:to]
|
|
399
|
+
[:rename_enum_value, [type_name, options]]
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
def invert_drop_virtual_table(args)
|
|
403
|
+
_enum, values = args.dup.tap(&:extract_options!)
|
|
404
|
+
raise ActiveRecord::IrreversibleMigration, "drop_virtual_table is only reversible if given options." unless values
|
|
405
|
+
super
|
|
373
406
|
end
|
|
374
407
|
|
|
375
408
|
def respond_to_missing?(method, _)
|
|
@@ -21,7 +21,7 @@ module ActiveRecord
|
|
|
21
21
|
# New migration functionality that will never be backward compatible should be added directly to `ActiveRecord::Migration`.
|
|
22
22
|
#
|
|
23
23
|
# There are classes for each prior Rails version. Each class descends from the *next* Rails version, so:
|
|
24
|
-
# 5.2 < 6.0 < 6.1 < 7.0 < 7.1 < 7.2
|
|
24
|
+
# 5.2 < 6.0 < 6.1 < 7.0 < 7.1 < 7.2 < 8.0 < 8.1
|
|
25
25
|
#
|
|
26
26
|
# If you are introducing new migration functionality that should only apply from Rails 7 onward, then you should
|
|
27
27
|
# find the class that immediately precedes it (6.1), and override the relevant migration methods to undo your changes.
|
|
@@ -29,7 +29,34 @@ module ActiveRecord
|
|
|
29
29
|
# For example, Rails 6 added a default value for the `precision` option on datetime columns. So in this file, the `V5_2`
|
|
30
30
|
# class sets the value of `precision` to `nil` if it's not explicitly provided. This way, the default value will not apply
|
|
31
31
|
# for migrations written for 5.2, but will for migrations written for 6.0.
|
|
32
|
-
|
|
32
|
+
V8_1 = Current
|
|
33
|
+
|
|
34
|
+
class V8_0 < V8_1
|
|
35
|
+
module RemoveForeignKeyColumnMatch
|
|
36
|
+
def remove_foreign_key(*args, **options)
|
|
37
|
+
options[:_skip_column_match] = true
|
|
38
|
+
super
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
module TableDefinition
|
|
43
|
+
def remove_foreign_key(to_table = nil, **options)
|
|
44
|
+
options[:_skip_column_match] = true
|
|
45
|
+
super
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
include RemoveForeignKeyColumnMatch
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
def compatible_table_definition(t)
|
|
53
|
+
t.singleton_class.prepend(TableDefinition)
|
|
54
|
+
super
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
class V7_2 < V8_0
|
|
59
|
+
end
|
|
33
60
|
|
|
34
61
|
class V7_1 < V7_2
|
|
35
62
|
end
|
|
@@ -151,9 +178,7 @@ module ActiveRecord
|
|
|
151
178
|
|
|
152
179
|
private
|
|
153
180
|
def compatible_table_definition(t)
|
|
154
|
-
|
|
155
|
-
prepend TableDefinition
|
|
156
|
-
end
|
|
181
|
+
t.singleton_class.prepend(TableDefinition)
|
|
157
182
|
super
|
|
158
183
|
end
|
|
159
184
|
end
|
|
@@ -214,9 +239,7 @@ module ActiveRecord
|
|
|
214
239
|
|
|
215
240
|
private
|
|
216
241
|
def compatible_table_definition(t)
|
|
217
|
-
|
|
218
|
-
prepend TableDefinition
|
|
219
|
-
end
|
|
242
|
+
t.singleton_class.prepend(TableDefinition)
|
|
220
243
|
super
|
|
221
244
|
end
|
|
222
245
|
end
|
|
@@ -257,9 +280,7 @@ module ActiveRecord
|
|
|
257
280
|
|
|
258
281
|
private
|
|
259
282
|
def compatible_table_definition(t)
|
|
260
|
-
|
|
261
|
-
prepend TableDefinition
|
|
262
|
-
end
|
|
283
|
+
t.singleton_class.prepend(TableDefinition)
|
|
263
284
|
super
|
|
264
285
|
end
|
|
265
286
|
end
|
|
@@ -305,17 +326,13 @@ module ActiveRecord
|
|
|
305
326
|
|
|
306
327
|
private
|
|
307
328
|
def compatible_table_definition(t)
|
|
308
|
-
|
|
309
|
-
prepend TableDefinition
|
|
310
|
-
end
|
|
329
|
+
t.singleton_class.prepend(TableDefinition)
|
|
311
330
|
super
|
|
312
331
|
end
|
|
313
332
|
|
|
314
333
|
def command_recorder
|
|
315
334
|
recorder = super
|
|
316
|
-
|
|
317
|
-
prepend CommandRecorder
|
|
318
|
-
end
|
|
335
|
+
recorder.singleton_class.prepend(CommandRecorder)
|
|
319
336
|
recorder
|
|
320
337
|
end
|
|
321
338
|
end
|
|
@@ -403,9 +420,7 @@ module ActiveRecord
|
|
|
403
420
|
|
|
404
421
|
private
|
|
405
422
|
def compatible_table_definition(t)
|
|
406
|
-
|
|
407
|
-
prepend TableDefinition
|
|
408
|
-
end
|
|
423
|
+
t.singleton_class.prepend(TableDefinition)
|
|
409
424
|
super
|
|
410
425
|
end
|
|
411
426
|
end
|
|
@@ -439,7 +454,7 @@ module ActiveRecord
|
|
|
439
454
|
super
|
|
440
455
|
end
|
|
441
456
|
|
|
442
|
-
def index_exists?(table_name, column_name, **options)
|
|
457
|
+
def index_exists?(table_name, column_name = nil, **options)
|
|
443
458
|
column_names = Array(column_name).map(&:to_s)
|
|
444
459
|
options[:name] =
|
|
445
460
|
if options[:name].present?
|
|
@@ -457,9 +472,7 @@ module ActiveRecord
|
|
|
457
472
|
|
|
458
473
|
private
|
|
459
474
|
def compatible_table_definition(t)
|
|
460
|
-
|
|
461
|
-
prepend TableDefinition
|
|
462
|
-
end
|
|
475
|
+
t.singleton_class.prepend(TableDefinition)
|
|
463
476
|
super
|
|
464
477
|
end
|
|
465
478
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
class Migration
|
|
5
|
+
# This class is used by the schema dumper to format versions information.
|
|
6
|
+
#
|
|
7
|
+
# The class receives the current +connection+ when initialized.
|
|
8
|
+
class DefaultSchemaVersionsFormatter # :nodoc:
|
|
9
|
+
def initialize(connection)
|
|
10
|
+
@connection = connection
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def format(versions)
|
|
14
|
+
sm_table = connection.quote_table_name(connection.pool.schema_migration.table_name)
|
|
15
|
+
|
|
16
|
+
if versions.is_a?(Array)
|
|
17
|
+
sql = +"INSERT INTO #{sm_table} (version) VALUES\n"
|
|
18
|
+
sql << versions.reverse.map { |v| "(#{connection.quote(v)})" }.join(",\n")
|
|
19
|
+
sql << ";"
|
|
20
|
+
sql
|
|
21
|
+
else
|
|
22
|
+
"INSERT INTO #{sm_table} (version) VALUES (#{connection.quote(versions)});"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
attr_reader :connection
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "benchmark"
|
|
4
|
-
require "set"
|
|
5
|
-
require "zlib"
|
|
6
3
|
require "active_support/core_ext/array/access"
|
|
7
4
|
require "active_support/core_ext/enumerable"
|
|
8
5
|
require "active_support/core_ext/module/attribute_accessors"
|
|
@@ -21,7 +18,7 @@ module ActiveRecord
|
|
|
21
18
|
# For example the following migration is not reversible.
|
|
22
19
|
# Rolling back this migration will raise an ActiveRecord::IrreversibleMigration error.
|
|
23
20
|
#
|
|
24
|
-
# class IrreversibleMigrationExample < ActiveRecord::Migration[
|
|
21
|
+
# class IrreversibleMigrationExample < ActiveRecord::Migration[8.1]
|
|
25
22
|
# def change
|
|
26
23
|
# create_table :distributors do |t|
|
|
27
24
|
# t.string :zipcode
|
|
@@ -39,7 +36,7 @@ module ActiveRecord
|
|
|
39
36
|
#
|
|
40
37
|
# 1. Define <tt>#up</tt> and <tt>#down</tt> methods instead of <tt>#change</tt>:
|
|
41
38
|
#
|
|
42
|
-
# class ReversibleMigrationExample < ActiveRecord::Migration[
|
|
39
|
+
# class ReversibleMigrationExample < ActiveRecord::Migration[8.1]
|
|
43
40
|
# def up
|
|
44
41
|
# create_table :distributors do |t|
|
|
45
42
|
# t.string :zipcode
|
|
@@ -64,7 +61,7 @@ module ActiveRecord
|
|
|
64
61
|
#
|
|
65
62
|
# 2. Use the #reversible method in <tt>#change</tt> method:
|
|
66
63
|
#
|
|
67
|
-
# class ReversibleMigrationExample < ActiveRecord::Migration[
|
|
64
|
+
# class ReversibleMigrationExample < ActiveRecord::Migration[8.1]
|
|
68
65
|
# def change
|
|
69
66
|
# create_table :distributors do |t|
|
|
70
67
|
# t.string :zipcode
|
|
@@ -151,11 +148,10 @@ module ActiveRecord
|
|
|
151
148
|
include ActiveSupport::ActionableError
|
|
152
149
|
|
|
153
150
|
action "Run pending migrations" do
|
|
154
|
-
ActiveRecord::Tasks::DatabaseTasks.
|
|
151
|
+
ActiveRecord::Tasks::DatabaseTasks.migrate_all
|
|
155
152
|
|
|
156
153
|
if ActiveRecord.dump_schema_after_migration
|
|
157
|
-
|
|
158
|
-
ActiveRecord::Tasks::DatabaseTasks.dump_schema(connection.pool.db_config)
|
|
154
|
+
ActiveRecord::Tasks::DatabaseTasks.dump_all
|
|
159
155
|
end
|
|
160
156
|
end
|
|
161
157
|
|
|
@@ -250,7 +246,7 @@ module ActiveRecord
|
|
|
250
246
|
#
|
|
251
247
|
# Example of a simple migration:
|
|
252
248
|
#
|
|
253
|
-
# class AddSsl < ActiveRecord::Migration[
|
|
249
|
+
# class AddSsl < ActiveRecord::Migration[8.1]
|
|
254
250
|
# def up
|
|
255
251
|
# add_column :accounts, :ssl_enabled, :boolean, default: true
|
|
256
252
|
# end
|
|
@@ -270,7 +266,7 @@ module ActiveRecord
|
|
|
270
266
|
#
|
|
271
267
|
# Example of a more complex migration that also needs to initialize data:
|
|
272
268
|
#
|
|
273
|
-
# class AddSystemSettings < ActiveRecord::Migration[
|
|
269
|
+
# class AddSystemSettings < ActiveRecord::Migration[8.1]
|
|
274
270
|
# def up
|
|
275
271
|
# create_table :system_settings do |t|
|
|
276
272
|
# t.string :name
|
|
@@ -357,7 +353,7 @@ module ActiveRecord
|
|
|
357
353
|
#
|
|
358
354
|
# === Deletion
|
|
359
355
|
#
|
|
360
|
-
# * <tt>drop_table(
|
|
356
|
+
# * <tt>drop_table(*names)</tt>: Drops the given tables.
|
|
361
357
|
# * <tt>drop_join_table(table_1, table_2, options)</tt>: Drops the join table
|
|
362
358
|
# specified by the given arguments.
|
|
363
359
|
# * <tt>remove_column(table_name, column_name, type, options)</tt>: Removes the column
|
|
@@ -399,7 +395,7 @@ module ActiveRecord
|
|
|
399
395
|
# $ bin/rails generate migration add_fieldname_to_tablename fieldname:string
|
|
400
396
|
#
|
|
401
397
|
# This will generate the file <tt>timestamp_add_fieldname_to_tablename.rb</tt>, which will look like this:
|
|
402
|
-
# class AddFieldnameToTablename < ActiveRecord::Migration[
|
|
398
|
+
# class AddFieldnameToTablename < ActiveRecord::Migration[8.1]
|
|
403
399
|
# def change
|
|
404
400
|
# add_column :tablenames, :fieldname, :string
|
|
405
401
|
# end
|
|
@@ -425,7 +421,7 @@ module ActiveRecord
|
|
|
425
421
|
#
|
|
426
422
|
# Not all migrations change the schema. Some just fix the data:
|
|
427
423
|
#
|
|
428
|
-
# class RemoveEmptyTags < ActiveRecord::Migration[
|
|
424
|
+
# class RemoveEmptyTags < ActiveRecord::Migration[8.1]
|
|
429
425
|
# def up
|
|
430
426
|
# Tag.all.each { |tag| tag.destroy if tag.pages.empty? }
|
|
431
427
|
# end
|
|
@@ -438,7 +434,7 @@ module ActiveRecord
|
|
|
438
434
|
#
|
|
439
435
|
# Others remove columns when they migrate up instead of down:
|
|
440
436
|
#
|
|
441
|
-
# class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[
|
|
437
|
+
# class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[8.1]
|
|
442
438
|
# def up
|
|
443
439
|
# remove_column :items, :incomplete_items_count
|
|
444
440
|
# remove_column :items, :completed_items_count
|
|
@@ -452,7 +448,7 @@ module ActiveRecord
|
|
|
452
448
|
#
|
|
453
449
|
# And sometimes you need to do something in SQL not abstracted directly by migrations:
|
|
454
450
|
#
|
|
455
|
-
# class MakeJoinUnique < ActiveRecord::Migration[
|
|
451
|
+
# class MakeJoinUnique < ActiveRecord::Migration[8.1]
|
|
456
452
|
# def up
|
|
457
453
|
# execute "ALTER TABLE `pages_linked_pages` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`)"
|
|
458
454
|
# end
|
|
@@ -469,7 +465,7 @@ module ActiveRecord
|
|
|
469
465
|
# <tt>Base#reset_column_information</tt> in order to ensure that the model has the
|
|
470
466
|
# latest column data from after the new column was added. Example:
|
|
471
467
|
#
|
|
472
|
-
# class AddPeopleSalary < ActiveRecord::Migration[
|
|
468
|
+
# class AddPeopleSalary < ActiveRecord::Migration[8.1]
|
|
473
469
|
# def up
|
|
474
470
|
# add_column :people, :salary, :integer
|
|
475
471
|
# Person.reset_column_information
|
|
@@ -531,7 +527,7 @@ module ActiveRecord
|
|
|
531
527
|
# To define a reversible migration, define the +change+ method in your
|
|
532
528
|
# migration like this:
|
|
533
529
|
#
|
|
534
|
-
# class TenderloveMigration < ActiveRecord::Migration[
|
|
530
|
+
# class TenderloveMigration < ActiveRecord::Migration[8.1]
|
|
535
531
|
# def change
|
|
536
532
|
# create_table(:horses) do |t|
|
|
537
533
|
# t.column :content, :text
|
|
@@ -561,7 +557,7 @@ module ActiveRecord
|
|
|
561
557
|
# can't execute inside a transaction though, and for these situations
|
|
562
558
|
# you can turn the automatic transactions off.
|
|
563
559
|
#
|
|
564
|
-
# class ChangeEnum < ActiveRecord::Migration[
|
|
560
|
+
# class ChangeEnum < ActiveRecord::Migration[8.1]
|
|
565
561
|
# disable_ddl_transaction!
|
|
566
562
|
#
|
|
567
563
|
# def up
|
|
@@ -574,6 +570,7 @@ module ActiveRecord
|
|
|
574
570
|
class Migration
|
|
575
571
|
autoload :CommandRecorder, "active_record/migration/command_recorder"
|
|
576
572
|
autoload :Compatibility, "active_record/migration/compatibility"
|
|
573
|
+
autoload :DefaultSchemaVersionsFormatter, "active_record/migration/default_schema_versions_formatter"
|
|
577
574
|
autoload :JoinTable, "active_record/migration/join_table"
|
|
578
575
|
autoload :ExecutionStrategy, "active_record/migration/execution_strategy"
|
|
579
576
|
autoload :DefaultStrategy, "active_record/migration/default_strategy"
|
|
@@ -604,7 +601,7 @@ module ActiveRecord
|
|
|
604
601
|
end
|
|
605
602
|
end
|
|
606
603
|
|
|
607
|
-
def drop_table(
|
|
604
|
+
def drop_table(*table_names, **options)
|
|
608
605
|
if block_given?
|
|
609
606
|
super { |t| yield compatible_table_definition(t) }
|
|
610
607
|
else
|
|
@@ -681,10 +678,6 @@ module ActiveRecord
|
|
|
681
678
|
paths = all_configs.flat_map { |config| config.migrations_paths || Migrator.migrations_paths }.uniq
|
|
682
679
|
@file_watcher.new([], paths.index_with(["rb"]), &block)
|
|
683
680
|
end
|
|
684
|
-
|
|
685
|
-
def connection
|
|
686
|
-
ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
|
687
|
-
end
|
|
688
681
|
end
|
|
689
682
|
|
|
690
683
|
class << self
|
|
@@ -715,13 +708,7 @@ module ActiveRecord
|
|
|
715
708
|
|
|
716
709
|
def load_schema_if_pending!
|
|
717
710
|
if any_schema_needs_update?
|
|
718
|
-
|
|
719
|
-
root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
|
|
720
|
-
|
|
721
|
-
FileUtils.cd(root) do
|
|
722
|
-
Base.connection_handler.clear_all_connections!(:all)
|
|
723
|
-
system("bin/rails db:test:prepare")
|
|
724
|
-
end
|
|
711
|
+
load_schema!
|
|
725
712
|
end
|
|
726
713
|
|
|
727
714
|
check_pending_migrations
|
|
@@ -760,7 +747,7 @@ module ActiveRecord
|
|
|
760
747
|
private
|
|
761
748
|
def any_schema_needs_update?
|
|
762
749
|
!db_configs_in_current_env.all? do |db_config|
|
|
763
|
-
Tasks::DatabaseTasks.schema_up_to_date?(db_config
|
|
750
|
+
Tasks::DatabaseTasks.schema_up_to_date?(db_config)
|
|
764
751
|
end
|
|
765
752
|
end
|
|
766
753
|
|
|
@@ -785,6 +772,21 @@ module ActiveRecord
|
|
|
785
772
|
def env
|
|
786
773
|
ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
|
|
787
774
|
end
|
|
775
|
+
|
|
776
|
+
def load_schema!
|
|
777
|
+
# Roundtrip to Rake to allow plugins to hook into database initialization.
|
|
778
|
+
root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
|
|
779
|
+
|
|
780
|
+
FileUtils.cd(root) do
|
|
781
|
+
Base.connection_handler.clear_all_connections!(:all)
|
|
782
|
+
system("bin/rails db:test:prepare")
|
|
783
|
+
end
|
|
784
|
+
end
|
|
785
|
+
|
|
786
|
+
def respond_to_missing?(method, include_private = false)
|
|
787
|
+
return false if nearest_delegate == delegate
|
|
788
|
+
nearest_delegate.respond_to?(method, include_private)
|
|
789
|
+
end
|
|
788
790
|
end
|
|
789
791
|
|
|
790
792
|
def disable_ddl_transaction # :nodoc:
|
|
@@ -822,7 +824,7 @@ module ActiveRecord
|
|
|
822
824
|
# and create the table 'apples' on the way up, and the reverse
|
|
823
825
|
# on the way down.
|
|
824
826
|
#
|
|
825
|
-
# class FixTLMigration < ActiveRecord::Migration[
|
|
827
|
+
# class FixTLMigration < ActiveRecord::Migration[8.1]
|
|
826
828
|
# def change
|
|
827
829
|
# revert do
|
|
828
830
|
# create_table(:horses) do |t|
|
|
@@ -841,7 +843,7 @@ module ActiveRecord
|
|
|
841
843
|
#
|
|
842
844
|
# require_relative "20121212123456_tenderlove_migration"
|
|
843
845
|
#
|
|
844
|
-
# class FixupTLMigration < ActiveRecord::Migration[
|
|
846
|
+
# class FixupTLMigration < ActiveRecord::Migration[8.1]
|
|
845
847
|
# def change
|
|
846
848
|
# revert TenderloveMigration
|
|
847
849
|
#
|
|
@@ -892,7 +894,7 @@ module ActiveRecord
|
|
|
892
894
|
# when the three columns 'first_name', 'last_name' and 'full_name' exist,
|
|
893
895
|
# even when migrating down:
|
|
894
896
|
#
|
|
895
|
-
# class SplitNameMigration < ActiveRecord::Migration[
|
|
897
|
+
# class SplitNameMigration < ActiveRecord::Migration[8.1]
|
|
896
898
|
# def change
|
|
897
899
|
# add_column :users, :first_name, :string
|
|
898
900
|
# add_column :users, :last_name, :string
|
|
@@ -920,7 +922,7 @@ module ActiveRecord
|
|
|
920
922
|
# In the following example, the new column +published+ will be given
|
|
921
923
|
# the value +true+ for all existing records.
|
|
922
924
|
#
|
|
923
|
-
# class AddPublishedToPosts < ActiveRecord::Migration[
|
|
925
|
+
# class AddPublishedToPosts < ActiveRecord::Migration[8.1]
|
|
924
926
|
# def change
|
|
925
927
|
# add_column :posts, :published, :boolean, default: false
|
|
926
928
|
# up_only do
|
|
@@ -972,16 +974,16 @@ module ActiveRecord
|
|
|
972
974
|
when :down then announce "reverting"
|
|
973
975
|
end
|
|
974
976
|
|
|
975
|
-
|
|
977
|
+
time_elapsed = nil
|
|
976
978
|
ActiveRecord::Tasks::DatabaseTasks.migration_connection.pool.with_connection do |conn|
|
|
977
|
-
|
|
979
|
+
time_elapsed = ActiveSupport::Benchmark.realtime do
|
|
978
980
|
exec_migration(conn, direction)
|
|
979
981
|
end
|
|
980
982
|
end
|
|
981
983
|
|
|
982
984
|
case direction
|
|
983
|
-
when :up then announce "migrated (%.4fs)" %
|
|
984
|
-
when :down then announce "reverted (%.4fs)" %
|
|
985
|
+
when :up then announce "migrated (%.4fs)" % time_elapsed; write
|
|
986
|
+
when :down then announce "reverted (%.4fs)" % time_elapsed; write
|
|
985
987
|
end
|
|
986
988
|
end
|
|
987
989
|
|
|
@@ -1022,8 +1024,8 @@ module ActiveRecord
|
|
|
1022
1024
|
def say_with_time(message)
|
|
1023
1025
|
say(message)
|
|
1024
1026
|
result = nil
|
|
1025
|
-
|
|
1026
|
-
say "%.4fs" %
|
|
1027
|
+
time_elapsed = ActiveSupport::Benchmark.realtime { result = yield }
|
|
1028
|
+
say "%.4fs" % time_elapsed, :subitem
|
|
1027
1029
|
say("#{result} rows", :subitem) if result.is_a?(Integer)
|
|
1028
1030
|
result
|
|
1029
1031
|
end
|
|
@@ -1173,6 +1175,10 @@ module ActiveRecord
|
|
|
1173
1175
|
def command_recorder
|
|
1174
1176
|
CommandRecorder.new(connection)
|
|
1175
1177
|
end
|
|
1178
|
+
|
|
1179
|
+
def respond_to_missing?(method, include_private = false)
|
|
1180
|
+
execution_strategy.respond_to?(method, include_private) || super
|
|
1181
|
+
end
|
|
1176
1182
|
end
|
|
1177
1183
|
|
|
1178
1184
|
# MigrationProxy is used to defer loading of the actual migration classes
|
|
@@ -1532,7 +1538,8 @@ module ActiveRecord
|
|
|
1532
1538
|
return if down? && !migrated.include?(migration.version.to_i)
|
|
1533
1539
|
return if up? && migrated.include?(migration.version.to_i)
|
|
1534
1540
|
|
|
1535
|
-
|
|
1541
|
+
message = up? ? "Migrating to" : "Reverting"
|
|
1542
|
+
Base.logger.info "#{message} #{migration.name} (#{migration.version})" if Base.logger
|
|
1536
1543
|
|
|
1537
1544
|
ddl_transaction(migration) do
|
|
1538
1545
|
migration.migrate(@direction)
|