activerecord 7.2.3 → 8.0.4
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 +391 -958
- data/README.rdoc +1 -1
- data/lib/active_record/association_relation.rb +1 -0
- data/lib/active_record/associations/association.rb +34 -10
- data/lib/active_record/associations/builder/association.rb +7 -6
- data/lib/active_record/associations/collection_association.rb +1 -1
- data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +3 -2
- data/lib/active_record/associations/preloader/association.rb +2 -2
- data/lib/active_record/associations/singular_association.rb +8 -3
- data/lib/active_record/associations.rb +34 -4
- 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/time_zone_conversion.rb +2 -12
- data/lib/active_record/autosave_association.rb +69 -27
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +34 -25
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +0 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +0 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +6 -15
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +90 -43
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +8 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -5
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +7 -2
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +34 -7
- data/lib/active_record/connection_adapters/abstract/transaction.rb +15 -5
- data/lib/active_record/connection_adapters/abstract_adapter.rb +31 -43
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +21 -40
- data/lib/active_record/connection_adapters/mysql/quoting.rb +0 -8
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +2 -8
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +50 -45
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +84 -94
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -8
- data/lib/active_record/connection_adapters/pool_config.rb +7 -7
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +72 -43
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +1 -11
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +6 -12
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +59 -16
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +46 -96
- data/lib/active_record/connection_adapters/schema_cache.rb +1 -3
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +80 -100
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +0 -6
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +13 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +9 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +53 -12
- data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +37 -67
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +0 -17
- data/lib/active_record/connection_adapters.rb +0 -56
- data/lib/active_record/connection_handling.rb +23 -1
- data/lib/active_record/core.rb +29 -14
- data/lib/active_record/database_configurations/database_config.rb +4 -0
- data/lib/active_record/database_configurations/hash_config.rb +16 -2
- data/lib/active_record/encryption/config.rb +3 -1
- data/lib/active_record/encryption/encryptable_record.rb +4 -4
- data/lib/active_record/encryption/encrypted_attribute_type.rb +10 -1
- data/lib/active_record/encryption/encryptor.rb +16 -8
- data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
- data/lib/active_record/encryption/scheme.rb +8 -1
- data/lib/active_record/enum.rb +9 -22
- data/lib/active_record/errors.rb +13 -5
- data/lib/active_record/fixtures.rb +0 -2
- data/lib/active_record/future_result.rb +13 -9
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/insert_all.rb +1 -1
- data/lib/active_record/locking/optimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +5 -11
- data/lib/active_record/migration/command_recorder.rb +31 -11
- data/lib/active_record/migration/compatibility.rb +5 -2
- data/lib/active_record/migration.rb +38 -42
- data/lib/active_record/model_schema.rb +3 -4
- data/lib/active_record/nested_attributes.rb +4 -6
- data/lib/active_record/persistence.rb +128 -130
- data/lib/active_record/query_logs.rb +102 -50
- data/lib/active_record/query_logs_formatter.rb +17 -28
- data/lib/active_record/querying.rb +8 -8
- data/lib/active_record/railtie.rb +2 -26
- data/lib/active_record/railties/databases.rake +11 -35
- data/lib/active_record/reflection.rb +18 -21
- data/lib/active_record/relation/batches/batch_enumerator.rb +4 -3
- data/lib/active_record/relation/batches.rb +132 -72
- data/lib/active_record/relation/calculations.rb +40 -39
- data/lib/active_record/relation/delegation.rb +25 -14
- data/lib/active_record/relation/finder_methods.rb +18 -18
- data/lib/active_record/relation/merger.rb +8 -8
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -1
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
- data/lib/active_record/relation/predicate_builder.rb +13 -0
- data/lib/active_record/relation/query_methods.rb +105 -61
- data/lib/active_record/relation/spawn_methods.rb +7 -7
- data/lib/active_record/relation.rb +79 -61
- data/lib/active_record/result.rb +66 -4
- data/lib/active_record/sanitization.rb +7 -6
- data/lib/active_record/schema_dumper.rb +5 -0
- data/lib/active_record/schema_migration.rb +2 -1
- data/lib/active_record/scoping/named.rb +5 -2
- data/lib/active_record/statement_cache.rb +14 -14
- data/lib/active_record/store.rb +7 -3
- data/lib/active_record/table_metadata.rb +1 -3
- data/lib/active_record/tasks/database_tasks.rb +69 -60
- data/lib/active_record/tasks/mysql_database_tasks.rb +0 -2
- data/lib/active_record/tasks/postgresql_database_tasks.rb +2 -1
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -2
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +12 -0
- data/lib/active_record/token_for.rb +1 -1
- data/lib/active_record/transactions.rb +5 -6
- data/lib/active_record/validations/uniqueness.rb +8 -8
- data/lib/active_record.rb +21 -48
- 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/nodes/binary.rb +1 -1
- data/lib/arel/nodes/node.rb +1 -1
- data/lib/arel/nodes/sql_literal.rb +1 -1
- data/lib/arel/table.rb +3 -7
- metadata +9 -10
- data/lib/active_record/relation/record_fetch_warning.rb +0 -52
|
@@ -100,7 +100,7 @@ module ActiveRecord
|
|
|
100
100
|
end
|
|
101
101
|
|
|
102
102
|
def decrypt(value)
|
|
103
|
-
text_to_database_type decrypt_as_text(value)
|
|
103
|
+
text_to_database_type decrypt_as_text(database_type_to_text(value))
|
|
104
104
|
end
|
|
105
105
|
|
|
106
106
|
def try_to_deserialize_with_previous_encrypted_types(value)
|
|
@@ -170,6 +170,15 @@ module ActiveRecord
|
|
|
170
170
|
value
|
|
171
171
|
end
|
|
172
172
|
end
|
|
173
|
+
|
|
174
|
+
def database_type_to_text(value)
|
|
175
|
+
if value && cast_type.binary?
|
|
176
|
+
binary_cast_type = cast_type.serialized? ? cast_type.subtype : cast_type
|
|
177
|
+
binary_cast_type.deserialize(value)
|
|
178
|
+
else
|
|
179
|
+
value
|
|
180
|
+
end
|
|
181
|
+
end
|
|
173
182
|
end
|
|
174
183
|
end
|
|
175
184
|
end
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "openssl"
|
|
4
|
-
require "zlib"
|
|
5
4
|
require "active_support/core_ext/numeric"
|
|
6
5
|
|
|
7
6
|
module ActiveRecord
|
|
@@ -12,13 +11,22 @@ module ActiveRecord
|
|
|
12
11
|
# It interacts with a KeyProvider for getting the keys, and delegate to
|
|
13
12
|
# ActiveRecord::Encryption::Cipher the actual encryption algorithm.
|
|
14
13
|
class Encryptor
|
|
14
|
+
# The compressor to use for compressing the payload.
|
|
15
|
+
attr_reader :compressor
|
|
16
|
+
|
|
15
17
|
# ==== Options
|
|
16
18
|
#
|
|
17
19
|
# [+:compress+]
|
|
18
20
|
# Boolean indicating whether records should be compressed before
|
|
19
21
|
# encryption. Defaults to +true+.
|
|
20
|
-
|
|
22
|
+
#
|
|
23
|
+
# [+:compressor+]
|
|
24
|
+
# The compressor to use. It must respond to +deflate+ and +inflate+.
|
|
25
|
+
# If not provided, will default to +ActiveRecord::Encryption.config.compressor+,
|
|
26
|
+
# which itself defaults to +Zlib+.
|
|
27
|
+
def initialize(compress: true, compressor: nil)
|
|
21
28
|
@compress = compress
|
|
29
|
+
@compressor = compressor || ActiveRecord::Encryption.config.compressor
|
|
22
30
|
end
|
|
23
31
|
|
|
24
32
|
# Encrypts +clean_text+ and returns the encrypted result.
|
|
@@ -79,6 +87,10 @@ module ActiveRecord
|
|
|
79
87
|
serializer.binary?
|
|
80
88
|
end
|
|
81
89
|
|
|
90
|
+
def compress? # :nodoc:
|
|
91
|
+
@compress
|
|
92
|
+
end
|
|
93
|
+
|
|
82
94
|
private
|
|
83
95
|
DECRYPT_ERRORS = [OpenSSL::Cipher::CipherError, Errors::EncryptedContentIntegrity, Errors::Decryption]
|
|
84
96
|
ENCODING_ERRORS = [EncodingError, Errors::Encoding]
|
|
@@ -131,12 +143,8 @@ module ActiveRecord
|
|
|
131
143
|
end
|
|
132
144
|
end
|
|
133
145
|
|
|
134
|
-
def compress?
|
|
135
|
-
@compress
|
|
136
|
-
end
|
|
137
|
-
|
|
138
146
|
def compress(data)
|
|
139
|
-
|
|
147
|
+
@compressor.deflate(data).tap do |compressed_data|
|
|
140
148
|
compressed_data.force_encoding(data.encoding)
|
|
141
149
|
end
|
|
142
150
|
end
|
|
@@ -150,7 +158,7 @@ module ActiveRecord
|
|
|
150
158
|
end
|
|
151
159
|
|
|
152
160
|
def uncompress(data)
|
|
153
|
-
|
|
161
|
+
@compressor.inflate(data).tap do |uncompressed_data|
|
|
154
162
|
uncompressed_data.force_encoding(data.encoding)
|
|
155
163
|
end
|
|
156
164
|
end
|
|
@@ -41,6 +41,8 @@ module ActiveRecord
|
|
|
41
41
|
module EncryptedQuery # :nodoc:
|
|
42
42
|
class << self
|
|
43
43
|
def process_arguments(owner, args, check_for_additional_values)
|
|
44
|
+
owner = owner.model if owner.is_a?(Relation)
|
|
45
|
+
|
|
44
46
|
return args if owner.deterministic_encrypted_attributes&.empty?
|
|
45
47
|
|
|
46
48
|
if args.is_a?(Array) && (options = args.first).is_a?(Hash)
|
|
@@ -102,12 +104,12 @@ module ActiveRecord
|
|
|
102
104
|
end
|
|
103
105
|
|
|
104
106
|
def scope_for_create
|
|
105
|
-
return super unless
|
|
107
|
+
return super unless model.deterministic_encrypted_attributes&.any?
|
|
106
108
|
|
|
107
109
|
scope_attributes = super
|
|
108
110
|
wheres = where_values_hash
|
|
109
111
|
|
|
110
|
-
|
|
112
|
+
model.deterministic_encrypted_attributes.each do |attribute_name|
|
|
111
113
|
attribute_name = attribute_name.to_s
|
|
112
114
|
values = wheres[attribute_name]
|
|
113
115
|
if values.is_a?(Array) && values[1..].all?(AdditionalValue)
|
|
@@ -11,7 +11,7 @@ module ActiveRecord
|
|
|
11
11
|
attr_accessor :previous_schemes
|
|
12
12
|
|
|
13
13
|
def initialize(key_provider: nil, key: nil, deterministic: nil, support_unencrypted_data: nil, downcase: nil, ignore_case: nil,
|
|
14
|
-
previous_schemes: nil, **context_properties)
|
|
14
|
+
previous_schemes: nil, compress: true, compressor: nil, **context_properties)
|
|
15
15
|
# Initializing all attributes to +nil+ as we want to allow a "not set" semantics so that we
|
|
16
16
|
# can merge schemes without overriding values with defaults. See +#merge+
|
|
17
17
|
|
|
@@ -24,8 +24,13 @@ module ActiveRecord
|
|
|
24
24
|
@previous_schemes_param = previous_schemes
|
|
25
25
|
@previous_schemes = Array.wrap(previous_schemes)
|
|
26
26
|
@context_properties = context_properties
|
|
27
|
+
@compress = compress
|
|
28
|
+
@compressor = compressor
|
|
27
29
|
|
|
28
30
|
validate_config!
|
|
31
|
+
|
|
32
|
+
@context_properties[:encryptor] = Encryptor.new(compress: @compress) unless @compress
|
|
33
|
+
@context_properties[:encryptor] = Encryptor.new(compressor: compressor) if compressor
|
|
29
34
|
end
|
|
30
35
|
|
|
31
36
|
def ignore_case?
|
|
@@ -78,6 +83,8 @@ module ActiveRecord
|
|
|
78
83
|
def validate_config!
|
|
79
84
|
raise Errors::Configuration, "ignore_case: can only be used with deterministic encryption" if @ignore_case && !@deterministic
|
|
80
85
|
raise Errors::Configuration, "key_provider: and key: can't be used simultaneously" if @key_provider_param && @key
|
|
86
|
+
raise Errors::Configuration, "compressor: can't be used with compress: false" if !@compress && @compressor
|
|
87
|
+
raise Errors::Configuration, "compressor: can't be used with encryptor" if @compressor && @context_properties[:encryptor]
|
|
81
88
|
end
|
|
82
89
|
|
|
83
90
|
def key_provider_from_key
|
data/lib/active_record/enum.rb
CHANGED
|
@@ -214,34 +214,16 @@ module ActiveRecord
|
|
|
214
214
|
attr_reader :name, :mapping
|
|
215
215
|
end
|
|
216
216
|
|
|
217
|
-
def enum(name
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
return _enum(name, values, **options)
|
|
221
|
-
end
|
|
222
|
-
|
|
223
|
-
definitions = options.slice!(:_prefix, :_suffix, :_scopes, :_default, :_instance_methods)
|
|
224
|
-
options.transform_keys! { |key| :"#{key[1..-1]}" }
|
|
225
|
-
|
|
226
|
-
definitions.each { |name, values| _enum(name, values, **options) }
|
|
227
|
-
|
|
228
|
-
ActiveRecord.deprecator.warn(<<~MSG)
|
|
229
|
-
Defining enums with keyword arguments is deprecated and will be removed
|
|
230
|
-
in Rails 8.0. Positional arguments should be used instead:
|
|
231
|
-
|
|
232
|
-
#{definitions.map { |name, values| "enum :#{name}, #{values}" }.join("\n")}
|
|
233
|
-
MSG
|
|
217
|
+
def enum(name, values = nil, **options)
|
|
218
|
+
values, options = options, {} unless values
|
|
219
|
+
_enum(name, values, **options)
|
|
234
220
|
end
|
|
235
221
|
|
|
236
222
|
private
|
|
237
|
-
def inherited(base)
|
|
238
|
-
base.defined_enums = defined_enums.deep_dup
|
|
239
|
-
super
|
|
240
|
-
end
|
|
241
|
-
|
|
242
223
|
def _enum(name, values, prefix: nil, suffix: nil, scopes: true, instance_methods: true, validate: false, **options)
|
|
243
224
|
assert_valid_enum_definition_values(values)
|
|
244
225
|
assert_valid_enum_options(options)
|
|
226
|
+
|
|
245
227
|
# statuses = { }
|
|
246
228
|
enum_values = ActiveSupport::HashWithIndifferentAccess.new
|
|
247
229
|
name = name.to_s
|
|
@@ -305,6 +287,11 @@ module ActiveRecord
|
|
|
305
287
|
enum_values.freeze
|
|
306
288
|
end
|
|
307
289
|
|
|
290
|
+
def inherited(base)
|
|
291
|
+
base.defined_enums = defined_enums.deep_dup
|
|
292
|
+
super
|
|
293
|
+
end
|
|
294
|
+
|
|
308
295
|
class EnumMethods < Module # :nodoc:
|
|
309
296
|
def initialize(klass)
|
|
310
297
|
@klass = klass
|
data/lib/active_record/errors.rb
CHANGED
|
@@ -84,6 +84,19 @@ module ActiveRecord
|
|
|
84
84
|
class ConnectionTimeoutError < ConnectionNotEstablished
|
|
85
85
|
end
|
|
86
86
|
|
|
87
|
+
# Raised when a database connection pool is requested but
|
|
88
|
+
# has not been defined.
|
|
89
|
+
class ConnectionNotDefined < ConnectionNotEstablished
|
|
90
|
+
def initialize(message = nil, connection_name: nil, role: nil, shard: nil)
|
|
91
|
+
super(message)
|
|
92
|
+
@connection_name = connection_name
|
|
93
|
+
@role = role
|
|
94
|
+
@shard = shard
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
attr_reader :connection_name, :role, :shard
|
|
98
|
+
end
|
|
99
|
+
|
|
87
100
|
# Raised when connection to the database could not been established because it was not
|
|
88
101
|
# able to connect to the host or when the authorization failed.
|
|
89
102
|
class DatabaseConnectionError < ConnectionNotEstablished
|
|
@@ -484,11 +497,6 @@ module ActiveRecord
|
|
|
484
497
|
# relation.limit!(5) # => ActiveRecord::UnmodifiableRelation
|
|
485
498
|
class UnmodifiableRelation < ActiveRecordError
|
|
486
499
|
end
|
|
487
|
-
deprecate_constant(
|
|
488
|
-
:ImmutableRelation,
|
|
489
|
-
"ActiveRecord::UnmodifiableRelation",
|
|
490
|
-
deprecator: ActiveRecord.deprecator
|
|
491
|
-
)
|
|
492
500
|
|
|
493
501
|
# TransactionIsolationError will be raised under the following conditions:
|
|
494
502
|
#
|
|
@@ -100,17 +100,21 @@ module ActiveRecord
|
|
|
100
100
|
def execute_or_skip
|
|
101
101
|
return unless pending?
|
|
102
102
|
|
|
103
|
-
@
|
|
104
|
-
return unless
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
103
|
+
@session.synchronize do
|
|
104
|
+
return unless pending?
|
|
105
|
+
|
|
106
|
+
@pool.with_connection do |connection|
|
|
107
|
+
return unless @mutex.try_lock
|
|
108
|
+
begin
|
|
109
|
+
if pending?
|
|
110
|
+
@event_buffer = EventBuffer.new(self, @instrumenter)
|
|
111
|
+
ActiveSupport::IsolatedExecutionState[:active_record_instrumenter] = @event_buffer
|
|
112
|
+
|
|
109
113
|
execute_query(connection, async: true)
|
|
110
114
|
end
|
|
115
|
+
ensure
|
|
116
|
+
@mutex.unlock
|
|
111
117
|
end
|
|
112
|
-
ensure
|
|
113
|
-
@mutex.unlock
|
|
114
118
|
end
|
|
115
119
|
end
|
|
116
120
|
end
|
|
@@ -163,7 +167,7 @@ module ActiveRecord
|
|
|
163
167
|
end
|
|
164
168
|
|
|
165
169
|
def exec_query(connection, *args, **kwargs)
|
|
166
|
-
connection.
|
|
170
|
+
connection.raw_exec_query(*args, **kwargs)
|
|
167
171
|
end
|
|
168
172
|
|
|
169
173
|
class SelectAll < FutureResult # :nodoc:
|
|
@@ -240,7 +240,7 @@ module ActiveRecord
|
|
|
240
240
|
|
|
241
241
|
values_list = insert_all.map_key_with_value do |key, value|
|
|
242
242
|
next value if Arel::Nodes::SqlLiteral === value
|
|
243
|
-
|
|
243
|
+
ActiveModel::Type::SerializeCastValue.serialize(type = types[key], type.cast(value))
|
|
244
244
|
end
|
|
245
245
|
|
|
246
246
|
connection.visitor.compile(Arel::Nodes::ValuesList.new(values_list))
|
|
@@ -9,7 +9,7 @@ module ActiveRecord
|
|
|
9
9
|
# it was opened, an ActiveRecord::StaleObjectError exception is thrown if that has occurred
|
|
10
10
|
# and the update is ignored.
|
|
11
11
|
#
|
|
12
|
-
# Check out
|
|
12
|
+
# Check out ActiveRecord::Locking::Pessimistic for an alternative.
|
|
13
13
|
#
|
|
14
14
|
# == Usage
|
|
15
15
|
#
|
|
@@ -126,18 +126,12 @@ module ActiveRecord
|
|
|
126
126
|
end
|
|
127
127
|
end
|
|
128
128
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
return frame if frame
|
|
134
|
-
end
|
|
135
|
-
nil
|
|
136
|
-
end
|
|
137
|
-
else
|
|
138
|
-
def query_source_location
|
|
139
|
-
backtrace_cleaner.clean(caller(1).lazy).first
|
|
129
|
+
def query_source_location
|
|
130
|
+
Thread.each_caller_location do |location|
|
|
131
|
+
frame = backtrace_cleaner.clean_frame(location)
|
|
132
|
+
return frame if frame
|
|
140
133
|
end
|
|
134
|
+
nil
|
|
141
135
|
end
|
|
142
136
|
|
|
143
137
|
def filter(name, value)
|
|
@@ -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,7 +40,7 @@ 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
|
|
@@ -55,6 +57,8 @@ module ActiveRecord
|
|
|
55
57
|
:add_exclusion_constraint, :remove_exclusion_constraint,
|
|
56
58
|
:add_unique_constraint, :remove_unique_constraint,
|
|
57
59
|
:create_enum, :drop_enum, :rename_enum, :add_enum_value, :rename_enum_value,
|
|
60
|
+
:create_schema, :drop_schema,
|
|
61
|
+
:create_virtual_table, :drop_virtual_table
|
|
58
62
|
]
|
|
59
63
|
include JoinTable
|
|
60
64
|
|
|
@@ -163,7 +167,9 @@ module ActiveRecord
|
|
|
163
167
|
add_exclusion_constraint: :remove_exclusion_constraint,
|
|
164
168
|
add_unique_constraint: :remove_unique_constraint,
|
|
165
169
|
enable_extension: :disable_extension,
|
|
166
|
-
create_enum: :drop_enum
|
|
170
|
+
create_enum: :drop_enum,
|
|
171
|
+
create_schema: :drop_schema,
|
|
172
|
+
create_virtual_table: :drop_virtual_table
|
|
167
173
|
}.each do |cmd, inv|
|
|
168
174
|
[[inv, cmd], [cmd, inv]].uniq.each do |method, inverse|
|
|
169
175
|
class_eval <<-EOV, __FILE__, __LINE__ + 1
|
|
@@ -196,13 +202,20 @@ module ActiveRecord
|
|
|
196
202
|
end
|
|
197
203
|
|
|
198
204
|
def invert_drop_table(args, &block)
|
|
199
|
-
|
|
200
|
-
|
|
205
|
+
options = args.extract_options!
|
|
206
|
+
options.delete(:if_exists)
|
|
207
|
+
|
|
208
|
+
if args.size > 1
|
|
209
|
+
raise ActiveRecord::IrreversibleMigration, "To avoid mistakes, drop_table is only reversible if given a single table name."
|
|
201
210
|
end
|
|
202
|
-
|
|
211
|
+
|
|
212
|
+
if args.size == 1 && options == {} && block == nil
|
|
203
213
|
raise ActiveRecord::IrreversibleMigration, "To avoid mistakes, drop_table is only reversible if given options or a block (can be empty)."
|
|
204
214
|
end
|
|
205
|
-
|
|
215
|
+
|
|
216
|
+
args << options unless options.empty?
|
|
217
|
+
|
|
218
|
+
super(args, &block)
|
|
206
219
|
end
|
|
207
220
|
|
|
208
221
|
def invert_rename_table(args)
|
|
@@ -353,13 +366,13 @@ module ActiveRecord
|
|
|
353
366
|
end
|
|
354
367
|
|
|
355
368
|
def invert_rename_enum(args)
|
|
356
|
-
name,
|
|
369
|
+
name, new_name, = args
|
|
357
370
|
|
|
358
|
-
|
|
359
|
-
|
|
371
|
+
if new_name.is_a?(Hash) && new_name.key?(:to)
|
|
372
|
+
new_name = new_name[:to]
|
|
360
373
|
end
|
|
361
374
|
|
|
362
|
-
[:rename_enum, [
|
|
375
|
+
[:rename_enum, [new_name, name]]
|
|
363
376
|
end
|
|
364
377
|
|
|
365
378
|
def invert_rename_enum_value(args)
|
|
@@ -369,7 +382,14 @@ module ActiveRecord
|
|
|
369
382
|
raise ActiveRecord::IrreversibleMigration, "rename_enum_value is only reversible if given a :from and :to option."
|
|
370
383
|
end
|
|
371
384
|
|
|
372
|
-
[:
|
|
385
|
+
options[:to], options[:from] = options[:from], options[:to]
|
|
386
|
+
[:rename_enum_value, [type_name, options]]
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
def invert_drop_virtual_table(args)
|
|
390
|
+
_enum, values = args.dup.tap(&:extract_options!)
|
|
391
|
+
raise ActiveRecord::IrreversibleMigration, "drop_virtual_table is only reversible if given options." unless values
|
|
392
|
+
super
|
|
373
393
|
end
|
|
374
394
|
|
|
375
395
|
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
|
|
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,10 @@ 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_0 = Current
|
|
33
|
+
|
|
34
|
+
class V7_2 < V8_0
|
|
35
|
+
end
|
|
33
36
|
|
|
34
37
|
class V7_1 < V7_2
|
|
35
38
|
end
|