activerecord 6.1.4 → 7.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1049 -977
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/lib/active_record/aggregations.rb +1 -1
- data/lib/active_record/association_relation.rb +0 -10
- data/lib/active_record/associations/association.rb +33 -17
- data/lib/active_record/associations/association_scope.rb +1 -3
- data/lib/active_record/associations/belongs_to_association.rb +15 -4
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
- data/lib/active_record/associations/builder/association.rb +8 -2
- data/lib/active_record/associations/builder/belongs_to.rb +19 -6
- data/lib/active_record/associations/builder/collection_association.rb +10 -3
- data/lib/active_record/associations/builder/has_many.rb +3 -2
- data/lib/active_record/associations/builder/has_one.rb +2 -1
- data/lib/active_record/associations/builder/singular_association.rb +2 -2
- data/lib/active_record/associations/collection_association.rb +34 -27
- data/lib/active_record/associations/collection_proxy.rb +8 -3
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +2 -1
- data/lib/active_record/associations/has_one_association.rb +10 -7
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/preloader/association.rb +187 -55
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +147 -0
- data/lib/active_record/associations/preloader/through_association.rb +49 -13
- data/lib/active_record/associations/preloader.rb +39 -113
- data/lib/active_record/associations/singular_association.rb +8 -2
- data/lib/active_record/associations/through_association.rb +3 -3
- data/lib/active_record/associations.rb +90 -82
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +1 -1
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -2
- data/lib/active_record/attribute_methods/dirty.rb +49 -16
- data/lib/active_record/attribute_methods/primary_key.rb +2 -2
- data/lib/active_record/attribute_methods/query.rb +2 -2
- data/lib/active_record/attribute_methods/read.rb +7 -5
- data/lib/active_record/attribute_methods/serialization.rb +66 -12
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -3
- data/lib/active_record/attribute_methods/write.rb +7 -10
- data/lib/active_record/attribute_methods.rb +13 -14
- data/lib/active_record/attributes.rb +24 -35
- data/lib/active_record/autosave_association.rb +6 -21
- data/lib/active_record/base.rb +19 -1
- data/lib/active_record/callbacks.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +292 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +209 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +76 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +47 -561
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +0 -17
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +46 -22
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +24 -12
- data/lib/active_record/connection_adapters/abstract/quoting.rb +42 -72
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -17
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +34 -9
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +69 -18
- data/lib/active_record/connection_adapters/abstract/transaction.rb +15 -22
- data/lib/active_record/connection_adapters/abstract_adapter.rb +149 -74
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +97 -81
- data/lib/active_record/connection_adapters/column.rb +4 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +35 -23
- data/lib/active_record/connection_adapters/mysql/quoting.rb +35 -21
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +4 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -6
- data/lib/active_record/connection_adapters/pool_config.rb +7 -7
- data/lib/active_record/connection_adapters/postgresql/column.rb +17 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +19 -12
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +50 -50
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +32 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +21 -1
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +22 -1
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +27 -16
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +205 -105
- data/lib/active_record/connection_adapters/schema_cache.rb +29 -4
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +25 -19
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +15 -16
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +4 -2
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -30
- data/lib/active_record/connection_adapters.rb +6 -5
- data/lib/active_record/connection_handling.rb +47 -53
- data/lib/active_record/core.rb +122 -132
- data/lib/active_record/database_configurations/connection_url_resolver.rb +2 -1
- data/lib/active_record/database_configurations/database_config.rb +12 -9
- data/lib/active_record/database_configurations/hash_config.rb +63 -5
- data/lib/active_record/database_configurations/url_config.rb +2 -2
- data/lib/active_record/database_configurations.rb +16 -32
- data/lib/active_record/delegated_type.rb +52 -11
- data/lib/active_record/destroy_association_async_job.rb +1 -1
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +1 -1
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +98 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +44 -0
- data/lib/active_record/encryption/configurable.rb +61 -0
- data/lib/active_record/encryption/context.rb +35 -0
- data/lib/active_record/encryption/contexts.rb +72 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +12 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +208 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +140 -0
- data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
- data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
- data/lib/active_record/encryption/encryptor.rb +155 -0
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
- data/lib/active_record/encryption/errors.rb +15 -0
- data/lib/active_record/encryption/extended_deterministic_queries.rb +160 -0
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
- data/lib/active_record/encryption/key.rb +28 -0
- data/lib/active_record/encryption/key_generator.rb +42 -0
- data/lib/active_record/encryption/key_provider.rb +46 -0
- data/lib/active_record/encryption/message.rb +33 -0
- data/lib/active_record/encryption/message_serializer.rb +90 -0
- data/lib/active_record/encryption/null_encryptor.rb +21 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
- data/lib/active_record/encryption/scheme.rb +99 -0
- data/lib/active_record/encryption.rb +55 -0
- data/lib/active_record/enum.rb +49 -42
- data/lib/active_record/errors.rb +67 -4
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/fixture_set/file.rb +15 -1
- data/lib/active_record/fixture_set/table_row.rb +41 -6
- data/lib/active_record/fixture_set/table_rows.rb +4 -4
- data/lib/active_record/fixtures.rb +17 -20
- data/lib/active_record/future_result.rb +139 -0
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +55 -17
- data/lib/active_record/insert_all.rb +80 -14
- data/lib/active_record/integration.rb +4 -3
- data/lib/active_record/internal_metadata.rb +3 -5
- data/lib/active_record/legacy_yaml_adapter.rb +2 -39
- data/lib/active_record/locking/optimistic.rb +10 -9
- data/lib/active_record/locking/pessimistic.rb +9 -3
- data/lib/active_record/log_subscriber.rb +14 -3
- data/lib/active_record/middleware/database_selector/resolver.rb +6 -10
- data/lib/active_record/middleware/database_selector.rb +8 -3
- data/lib/active_record/middleware/shard_selector.rb +60 -0
- data/lib/active_record/migration/command_recorder.rb +4 -4
- data/lib/active_record/migration/compatibility.rb +83 -1
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration.rb +109 -79
- data/lib/active_record/model_schema.rb +45 -58
- data/lib/active_record/nested_attributes.rb +13 -12
- data/lib/active_record/no_touching.rb +3 -3
- data/lib/active_record/null_relation.rb +2 -6
- data/lib/active_record/persistence.rb +219 -52
- data/lib/active_record/query_cache.rb +2 -2
- data/lib/active_record/query_logs.rb +138 -0
- data/lib/active_record/querying.rb +15 -5
- data/lib/active_record/railtie.rb +127 -17
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +66 -129
- data/lib/active_record/readonly_attributes.rb +11 -0
- data/lib/active_record/reflection.rb +67 -50
- data/lib/active_record/relation/batches/batch_enumerator.rb +19 -5
- data/lib/active_record/relation/batches.rb +3 -3
- data/lib/active_record/relation/calculations.rb +40 -36
- data/lib/active_record/relation/delegation.rb +6 -6
- data/lib/active_record/relation/finder_methods.rb +31 -35
- data/lib/active_record/relation/merger.rb +20 -13
- data/lib/active_record/relation/predicate_builder.rb +1 -6
- data/lib/active_record/relation/query_attribute.rb +5 -11
- data/lib/active_record/relation/query_methods.rb +235 -61
- data/lib/active_record/relation/record_fetch_warning.rb +7 -9
- data/lib/active_record/relation/spawn_methods.rb +2 -2
- data/lib/active_record/relation/where_clause.rb +10 -19
- data/lib/active_record/relation.rb +171 -84
- data/lib/active_record/result.rb +17 -7
- data/lib/active_record/runtime_registry.rb +9 -13
- data/lib/active_record/sanitization.rb +11 -7
- data/lib/active_record/schema_dumper.rb +10 -3
- data/lib/active_record/schema_migration.rb +0 -4
- data/lib/active_record/scoping/default.rb +61 -12
- data/lib/active_record/scoping/named.rb +3 -11
- data/lib/active_record/scoping.rb +64 -34
- data/lib/active_record/serialization.rb +1 -1
- data/lib/active_record/signed_id.rb +1 -1
- data/lib/active_record/suppressor.rb +11 -15
- data/lib/active_record/tasks/database_tasks.rb +116 -58
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/postgresql_database_tasks.rb +19 -12
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +4 -4
- data/lib/active_record/timestamp.rb +3 -4
- data/lib/active_record/transactions.rb +9 -14
- data/lib/active_record/translation.rb +2 -2
- data/lib/active_record/type/adapter_specific_registry.rb +32 -7
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
- data/lib/active_record/type/internal/timezone.rb +2 -2
- data/lib/active_record/type/serialized.rb +1 -1
- data/lib/active_record/type/type_map.rb +17 -20
- data/lib/active_record/type.rb +1 -2
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record/validations/uniqueness.rb +1 -1
- data/lib/active_record.rb +204 -28
- data/lib/arel/attributes/attribute.rb +0 -8
- data/lib/arel/crud.rb +28 -22
- data/lib/arel/delete_manager.rb +18 -4
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +2 -3
- data/lib/arel/nodes/casted.rb +1 -1
- data/lib/arel/nodes/delete_statement.rb +12 -13
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/function.rb +1 -0
- data/lib/arel/nodes/insert_statement.rb +2 -2
- data/lib/arel/nodes/select_core.rb +2 -2
- data/lib/arel/nodes/select_statement.rb +2 -2
- data/lib/arel/nodes/update_statement.rb +8 -3
- data/lib/arel/nodes.rb +1 -0
- data/lib/arel/predications.rb +11 -3
- data/lib/arel/select_manager.rb +10 -4
- data/lib/arel/table.rb +0 -1
- data/lib/arel/tree_manager.rb +0 -12
- data/lib/arel/update_manager.rb +18 -4
- data/lib/arel/visitors/dot.rb +80 -90
- data/lib/arel/visitors/mysql.rb +8 -2
- data/lib/arel/visitors/postgresql.rb +0 -10
- data/lib/arel/visitors/to_sql.rb +58 -2
- data/lib/arel.rb +2 -1
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
- metadata +56 -13
@@ -37,7 +37,11 @@ module ActiveRecord
|
|
37
37
|
|
38
38
|
return if IGNORE_PAYLOAD_NAMES.include?(payload[:name])
|
39
39
|
|
40
|
-
name
|
40
|
+
name = if payload[:async]
|
41
|
+
"ASYNC #{payload[:name]} (#{payload[:lock_wait].round(1)}ms) (db time #{event.duration.round(1)}ms)"
|
42
|
+
else
|
43
|
+
"#{payload[:name]} (#{event.duration.round(1)}ms)"
|
44
|
+
end
|
41
45
|
name = "CACHE #{name}" if payload[:cached]
|
42
46
|
sql = payload[:sql]
|
43
47
|
binds = nil
|
@@ -47,7 +51,10 @@ module ActiveRecord
|
|
47
51
|
|
48
52
|
binds = []
|
49
53
|
payload[:binds].each_with_index do |attr, i|
|
50
|
-
|
54
|
+
attribute_name = attr.respond_to?(:name) ? attr.name : attr[i].name
|
55
|
+
filtered_params = filter(attribute_name, casted_params[i])
|
56
|
+
|
57
|
+
binds << render_bind(attr, filtered_params)
|
51
58
|
end
|
52
59
|
binds = binds.inspect
|
53
60
|
binds.prepend(" ")
|
@@ -115,7 +122,7 @@ module ActiveRecord
|
|
115
122
|
def debug(progname = nil, &block)
|
116
123
|
return unless super
|
117
124
|
|
118
|
-
if ActiveRecord
|
125
|
+
if ActiveRecord.verbose_query_logs
|
119
126
|
log_query_source
|
120
127
|
end
|
121
128
|
end
|
@@ -131,6 +138,10 @@ module ActiveRecord
|
|
131
138
|
def extract_query_source_location(locations)
|
132
139
|
backtrace_cleaner.clean(locations.lazy).first
|
133
140
|
end
|
141
|
+
|
142
|
+
def filter(name, value)
|
143
|
+
ActiveRecord::Base.inspection_filter.filter_param(name, value)
|
144
|
+
end
|
134
145
|
end
|
135
146
|
end
|
136
147
|
|
@@ -50,23 +50,19 @@ module ActiveRecord
|
|
50
50
|
|
51
51
|
private
|
52
52
|
def read_from_primary(&blk)
|
53
|
-
ActiveRecord::Base.connected_to(role: ActiveRecord
|
54
|
-
instrumenter.instrument("database_selector.active_record.read_from_primary")
|
55
|
-
yield
|
56
|
-
end
|
53
|
+
ActiveRecord::Base.connected_to(role: ActiveRecord.writing_role, prevent_writes: true) do
|
54
|
+
instrumenter.instrument("database_selector.active_record.read_from_primary", &blk)
|
57
55
|
end
|
58
56
|
end
|
59
57
|
|
60
58
|
def read_from_replica(&blk)
|
61
|
-
ActiveRecord::Base.connected_to(role: ActiveRecord
|
62
|
-
instrumenter.instrument("database_selector.active_record.read_from_replica")
|
63
|
-
yield
|
64
|
-
end
|
59
|
+
ActiveRecord::Base.connected_to(role: ActiveRecord.reading_role, prevent_writes: true) do
|
60
|
+
instrumenter.instrument("database_selector.active_record.read_from_replica", &blk)
|
65
61
|
end
|
66
62
|
end
|
67
63
|
|
68
|
-
def write_to_primary
|
69
|
-
ActiveRecord::Base.connected_to(role: ActiveRecord
|
64
|
+
def write_to_primary
|
65
|
+
ActiveRecord::Base.connected_to(role: ActiveRecord.writing_role, prevent_writes: false) do
|
70
66
|
instrumenter.instrument("database_selector.active_record.wrote_to_primary") do
|
71
67
|
yield
|
72
68
|
ensure
|
@@ -22,9 +22,14 @@ module ActiveRecord
|
|
22
22
|
# To use the DatabaseSelector in your application with default settings add
|
23
23
|
# the following options to your environment config:
|
24
24
|
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
25
|
+
# # This require is only necessary when using `rails new app --minimal`
|
26
|
+
# require "active_support/core_ext/integer/time"
|
27
|
+
#
|
28
|
+
# class Application < Rails::Application
|
29
|
+
# config.active_record.database_selector = { delay: 2.seconds }
|
30
|
+
# config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
|
31
|
+
# config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
|
32
|
+
# end
|
28
33
|
#
|
29
34
|
# New applications will include these lines commented out in the production.rb.
|
30
35
|
#
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module Middleware
|
5
|
+
# The ShardSelector Middleware provides a framework for automatically
|
6
|
+
# swapping shards. Rails provides a basic framework to determine which
|
7
|
+
# shard to switch to and allows for applications to write custom strategies
|
8
|
+
# for swapping if needed.
|
9
|
+
#
|
10
|
+
# The ShardSelector takes a set of options (currently only `lock` is supported)
|
11
|
+
# that can be used by the middleware to alter behavior. `lock` is
|
12
|
+
# true by default and will prohibit the request from switching shards once
|
13
|
+
# inside the block. If `lock` is false, then shard swapping will be allowed.
|
14
|
+
# For tenant based sharding, `lock` should always be true to prevent application
|
15
|
+
# code from mistakenly switching between tenants.
|
16
|
+
#
|
17
|
+
# Options can be set in the config:
|
18
|
+
#
|
19
|
+
# config.active_record.shard_selector = { lock: true }
|
20
|
+
#
|
21
|
+
# Applications must also provide the code for the resolver as it depends on application
|
22
|
+
# specific models. An example resolver would look like this:
|
23
|
+
#
|
24
|
+
# config.active_record.shard_resolver = ->(request) {
|
25
|
+
# subdomain = request.subdomain
|
26
|
+
# tenant = Tenant.find_by_subdomain!(subdomain)
|
27
|
+
# tenant.shard
|
28
|
+
# }
|
29
|
+
class ShardSelector
|
30
|
+
def initialize(app, resolver, options = {})
|
31
|
+
@app = app
|
32
|
+
@resolver = resolver
|
33
|
+
@options = options
|
34
|
+
end
|
35
|
+
|
36
|
+
attr_reader :resolver, :options
|
37
|
+
|
38
|
+
def call(env)
|
39
|
+
request = ActionDispatch::Request.new(env)
|
40
|
+
|
41
|
+
shard = selected_shard(request)
|
42
|
+
|
43
|
+
set_shard(shard) do
|
44
|
+
@app.call(env)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
def selected_shard(request)
|
50
|
+
resolver.call(request)
|
51
|
+
end
|
52
|
+
|
53
|
+
def set_shard(shard, &block)
|
54
|
+
ActiveRecord::Base.connected_to(shard: shard.to_sym) do
|
55
|
+
ActiveRecord::Base.prohibit_shard_swapping(options.fetch(:lock, true), &block)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -112,7 +112,7 @@ module ActiveRecord
|
|
112
112
|
record(:"#{method}", args, &block) # record(:create_table, args, &block)
|
113
113
|
end # end
|
114
114
|
EOV
|
115
|
-
ruby2_keywords(method)
|
115
|
+
ruby2_keywords(method)
|
116
116
|
end
|
117
117
|
alias :add_belongs_to :add_reference
|
118
118
|
alias :remove_belongs_to :remove_reference
|
@@ -154,9 +154,9 @@ module ActiveRecord
|
|
154
154
|
|
155
155
|
include StraightReversions
|
156
156
|
|
157
|
-
def invert_transaction(args)
|
157
|
+
def invert_transaction(args, &block)
|
158
158
|
sub_recorder = CommandRecorder.new(delegate)
|
159
|
-
sub_recorder.revert
|
159
|
+
sub_recorder.revert(&block)
|
160
160
|
|
161
161
|
invertions_proc = proc {
|
162
162
|
sub_recorder.replay(self)
|
@@ -286,7 +286,7 @@ module ActiveRecord
|
|
286
286
|
super
|
287
287
|
end
|
288
288
|
end
|
289
|
-
ruby2_keywords(:method_missing)
|
289
|
+
ruby2_keywords(:method_missing)
|
290
290
|
end
|
291
291
|
end
|
292
292
|
end
|
@@ -13,7 +13,77 @@ module ActiveRecord
|
|
13
13
|
const_get(name)
|
14
14
|
end
|
15
15
|
|
16
|
-
|
16
|
+
# This file exists to ensure that old migrations run the same way they did before a Rails upgrade.
|
17
|
+
# e.g. if you write a migration on Rails 6.1, then upgrade to Rails 7, the migration should do the same thing to your
|
18
|
+
# database as it did when you were running Rails 6.1
|
19
|
+
#
|
20
|
+
# "Current" is an alias for `ActiveRecord::Migration`, it represents the current Rails version.
|
21
|
+
# New migration functionality that will never be backward compatible should be added directly to `ActiveRecord::Migration`.
|
22
|
+
#
|
23
|
+
# There are classes for each prior Rails version. Each class descends from the *next* Rails version, so:
|
24
|
+
# 6.1 < 7.0
|
25
|
+
# 5.2 < 6.0 < 6.1 < 7.0
|
26
|
+
#
|
27
|
+
# If you are introducing new migration functionality that should only apply from Rails 7 onward, then you should
|
28
|
+
# find the class that immediately precedes it (6.1), and override the relevant migration methods to undo your changes.
|
29
|
+
#
|
30
|
+
# For example, Rails 6 added a default value for the `precision` option on datetime columns. So in this file, the `V5_2`
|
31
|
+
# class sets the value of `precision` to `nil` if it's not explicitly provided. This way, the default value will not apply
|
32
|
+
# for migrations written for 5.2, but will for migrations written for 6.0.
|
33
|
+
V7_0 = Current
|
34
|
+
|
35
|
+
class V6_1 < V7_0
|
36
|
+
class PostgreSQLCompat
|
37
|
+
def self.compatible_timestamp_type(type, connection)
|
38
|
+
if connection.adapter_name == "PostgreSQL"
|
39
|
+
# For Rails <= 6.1, :datetime was aliased to :timestamp
|
40
|
+
# See: https://github.com/rails/rails/blob/v6.1.3.2/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L108
|
41
|
+
# From Rails 7 onwards, you can define what :datetime resolves to (the default is still :timestamp)
|
42
|
+
# See `ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.datetime_type`
|
43
|
+
type.to_sym == :datetime ? :timestamp : type
|
44
|
+
else
|
45
|
+
type
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def add_column(table_name, column_name, type, **options)
|
51
|
+
if type == :datetime
|
52
|
+
options[:precision] ||= nil
|
53
|
+
end
|
54
|
+
|
55
|
+
type = PostgreSQLCompat.compatible_timestamp_type(type, connection)
|
56
|
+
super
|
57
|
+
end
|
58
|
+
|
59
|
+
def create_table(table_name, **options)
|
60
|
+
if block_given?
|
61
|
+
super { |t| yield compatible_table_definition(t) }
|
62
|
+
else
|
63
|
+
super
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
module TableDefinition
|
68
|
+
def new_column_definition(name, type, **options)
|
69
|
+
type = PostgreSQLCompat.compatible_timestamp_type(type, @conn)
|
70
|
+
super
|
71
|
+
end
|
72
|
+
|
73
|
+
def column(name, type, index: nil, **options)
|
74
|
+
options[:precision] ||= nil
|
75
|
+
super
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
def compatible_table_definition(t)
|
81
|
+
class << t
|
82
|
+
prepend TableDefinition
|
83
|
+
end
|
84
|
+
t
|
85
|
+
end
|
86
|
+
end
|
17
87
|
|
18
88
|
class V6_0 < V6_1
|
19
89
|
class ReferenceDefinition < ConnectionAdapters::ReferenceDefinition
|
@@ -29,6 +99,11 @@ module ActiveRecord
|
|
29
99
|
end
|
30
100
|
end
|
31
101
|
alias :belongs_to :references
|
102
|
+
|
103
|
+
def column(name, type, index: nil, **options)
|
104
|
+
options[:precision] ||= nil
|
105
|
+
super
|
106
|
+
end
|
32
107
|
end
|
33
108
|
|
34
109
|
def create_table(table_name, **options)
|
@@ -76,6 +151,11 @@ module ActiveRecord
|
|
76
151
|
options[:precision] ||= nil
|
77
152
|
super
|
78
153
|
end
|
154
|
+
|
155
|
+
def column(name, type, index: nil, **options)
|
156
|
+
options[:precision] ||= nil
|
157
|
+
super
|
158
|
+
end
|
79
159
|
end
|
80
160
|
|
81
161
|
module CommandRecorder
|
@@ -204,6 +284,8 @@ module ActiveRecord
|
|
204
284
|
if type == :primary_key
|
205
285
|
type = :integer
|
206
286
|
options[:primary_key] = true
|
287
|
+
elsif type == :datetime
|
288
|
+
options[:precision] ||= nil
|
207
289
|
end
|
208
290
|
super
|
209
291
|
end
|