activerecord 6.1.4.1 → 7.0.0.rc2
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 +1050 -981
- 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 +55 -12
@@ -15,6 +15,7 @@ module ActiveRecord
|
|
15
15
|
# = Active Record Railtie
|
16
16
|
class Railtie < Rails::Railtie # :nodoc:
|
17
17
|
config.active_record = ActiveSupport::OrderedOptions.new
|
18
|
+
config.active_record.encryption = ActiveSupport::OrderedOptions.new
|
18
19
|
|
19
20
|
config.app_generators.orm :active_record, migration: true,
|
20
21
|
timestamps: true
|
@@ -30,6 +31,10 @@ module ActiveRecord
|
|
30
31
|
config.active_record.check_schema_cache_dump_version = true
|
31
32
|
config.active_record.maintain_test_schema = true
|
32
33
|
config.active_record.has_many_inversing = false
|
34
|
+
config.active_record.sqlite3_production_warning = true
|
35
|
+
config.active_record.query_log_tags_enabled = false
|
36
|
+
config.active_record.query_log_tags = [ :application ]
|
37
|
+
config.active_record.cache_query_log_tags = false
|
33
38
|
|
34
39
|
config.active_record.queues = ActiveSupport::InheritableOptions.new
|
35
40
|
|
@@ -60,7 +65,7 @@ module ActiveRecord
|
|
60
65
|
console.level = Rails.logger.level
|
61
66
|
Rails.logger.extend ActiveSupport::Logger.broadcast console
|
62
67
|
end
|
63
|
-
ActiveRecord
|
68
|
+
ActiveRecord.verbose_query_logs = false
|
64
69
|
end
|
65
70
|
|
66
71
|
runner do
|
@@ -70,7 +75,6 @@ module ActiveRecord
|
|
70
75
|
initializer "active_record.initialize_timezone" do
|
71
76
|
ActiveSupport.on_load(:active_record) do
|
72
77
|
self.time_zone_aware_attributes = true
|
73
|
-
self.default_timezone = :utc
|
74
78
|
end
|
75
79
|
end
|
76
80
|
|
@@ -83,7 +87,7 @@ module ActiveRecord
|
|
83
87
|
end
|
84
88
|
|
85
89
|
initializer "active_record.migration_error" do |app|
|
86
|
-
if config.active_record.
|
90
|
+
if config.active_record.migration_error == :page_load
|
87
91
|
config.app_middleware.insert_after ::ActionDispatch::Callbacks,
|
88
92
|
ActiveRecord::Migration::CheckPending,
|
89
93
|
file_watcher: app.config.file_watcher
|
@@ -91,13 +95,21 @@ module ActiveRecord
|
|
91
95
|
end
|
92
96
|
|
93
97
|
initializer "active_record.database_selector" do
|
94
|
-
if options = config.active_record.
|
95
|
-
resolver = config.active_record.
|
96
|
-
operations = config.active_record.
|
98
|
+
if options = config.active_record.database_selector
|
99
|
+
resolver = config.active_record.database_resolver
|
100
|
+
operations = config.active_record.database_resolver_context
|
97
101
|
config.app_middleware.use ActiveRecord::Middleware::DatabaseSelector, resolver, operations, options
|
98
102
|
end
|
99
103
|
end
|
100
104
|
|
105
|
+
initializer "active_record.shard_selector" do
|
106
|
+
if resolver = config.active_record.shard_resolver
|
107
|
+
options = config.active_record.shard_selector || {}
|
108
|
+
|
109
|
+
config.app_middleware.use ActiveRecord::Middleware::ShardSelector, resolver, options
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
101
113
|
initializer "Check for cache versioning support" do
|
102
114
|
config.after_initialize do |app|
|
103
115
|
ActiveSupport.on_load(:active_record) do
|
@@ -124,9 +136,9 @@ To keep using the current cache store, you can turn off cache versioning entirel
|
|
124
136
|
end
|
125
137
|
|
126
138
|
initializer "active_record.check_schema_cache_dump" do
|
127
|
-
check_schema_cache_dump_version = config.active_record.
|
139
|
+
check_schema_cache_dump_version = config.active_record.check_schema_cache_dump_version
|
128
140
|
|
129
|
-
if config.active_record.
|
141
|
+
if config.active_record.use_schema_cache_dump && !config.active_record.lazily_load_schema_cache
|
130
142
|
config.after_initialize do |app|
|
131
143
|
ActiveSupport.on_load(:active_record) do
|
132
144
|
db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env).first
|
@@ -149,11 +161,12 @@ To keep using the current cache store, you can turn off cache versioning entirel
|
|
149
161
|
next if current_version.nil?
|
150
162
|
|
151
163
|
if cache.version != current_version
|
152
|
-
warn "Ignoring #{filename} because it has expired. The current schema version is #{current_version}, but the one in the cache is #{cache.version}."
|
164
|
+
warn "Ignoring #{filename} because it has expired. The current schema version is #{current_version}, but the one in the schema cache file is #{cache.version}."
|
153
165
|
next
|
154
166
|
end
|
155
167
|
end
|
156
168
|
|
169
|
+
Rails.logger.info("Using schema cache file #{filename}")
|
157
170
|
connection_pool.set_schema_cache(cache)
|
158
171
|
end
|
159
172
|
end
|
@@ -166,10 +179,6 @@ To keep using the current cache store, you can turn off cache versioning entirel
|
|
166
179
|
if app.config.eager_load
|
167
180
|
begin
|
168
181
|
descendants.each do |model|
|
169
|
-
# SchemaMigration and InternalMetadata both override `table_exists?`
|
170
|
-
# to bypass the schema cache, so skip them to avoid the extra queries.
|
171
|
-
next if model._internal?
|
172
|
-
|
173
182
|
# If the schema cache was loaded from a dump, we can use it without connecting
|
174
183
|
schema_cache = model.connection_pool.schema_cache
|
175
184
|
|
@@ -201,12 +210,58 @@ To keep using the current cache store, you can turn off cache versioning entirel
|
|
201
210
|
end
|
202
211
|
end
|
203
212
|
|
213
|
+
SQLITE3_PRODUCTION_WARN = "You are running SQLite in production, this is generally not recommended."\
|
214
|
+
" You can disable this warning by setting \"config.active_record.sqlite3_production_warning=false\"."
|
215
|
+
initializer "active_record.sqlite3_production_warning" do
|
216
|
+
if config.active_record.sqlite3_production_warning && Rails.env.production?
|
217
|
+
ActiveSupport.on_load(:active_record_sqlite3adapter) do
|
218
|
+
Rails.logger.warn(SQLITE3_PRODUCTION_WARN)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
204
223
|
initializer "active_record.set_configs" do |app|
|
224
|
+
configs = app.config.active_record
|
225
|
+
|
226
|
+
config.after_initialize do
|
227
|
+
configs.each do |k, v|
|
228
|
+
next if k == :encryption
|
229
|
+
setter = "#{k}="
|
230
|
+
if ActiveRecord.respond_to?(setter)
|
231
|
+
ActiveRecord.send(setter, v)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
205
236
|
ActiveSupport.on_load(:active_record) do
|
206
|
-
|
237
|
+
# Configs used in other initializers
|
238
|
+
configs = configs.except(
|
239
|
+
:migration_error,
|
240
|
+
:database_selector,
|
241
|
+
:database_resolver,
|
242
|
+
:database_resolver_context,
|
243
|
+
:shard_selector,
|
244
|
+
:shard_resolver,
|
245
|
+
:query_log_tags_enabled,
|
246
|
+
:query_log_tags,
|
247
|
+
:cache_query_log_tags,
|
248
|
+
:sqlite3_production_warning,
|
249
|
+
:check_schema_cache_dump_version,
|
250
|
+
:use_schema_cache_dump
|
251
|
+
)
|
207
252
|
|
208
253
|
configs.each do |k, v|
|
209
|
-
|
254
|
+
next if k == :encryption
|
255
|
+
setter = "#{k}="
|
256
|
+
# Some existing initializers might rely on Active Record configuration
|
257
|
+
# being copied from the config object to their actual destination when
|
258
|
+
# `ActiveRecord::Base` is loaded.
|
259
|
+
# So to preserve backward compatibility we copy the config a second time.
|
260
|
+
if ActiveRecord.respond_to?(setter)
|
261
|
+
ActiveRecord.send(setter, v)
|
262
|
+
else
|
263
|
+
send(setter, v)
|
264
|
+
end
|
210
265
|
end
|
211
266
|
end
|
212
267
|
end
|
@@ -215,10 +270,11 @@ To keep using the current cache store, you can turn off cache versioning entirel
|
|
215
270
|
# and then establishes the connection.
|
216
271
|
initializer "active_record.initialize_database" do
|
217
272
|
ActiveSupport.on_load(:active_record) do
|
218
|
-
if ActiveRecord
|
219
|
-
self.connection_handlers = { writing_role => ActiveRecord::Base.default_connection_handler }
|
273
|
+
if ActiveRecord.legacy_connection_handling
|
274
|
+
self.connection_handlers = { ActiveRecord.writing_role => ActiveRecord::Base.default_connection_handler }
|
220
275
|
end
|
221
276
|
self.configurations = Rails.application.config.database_configuration
|
277
|
+
|
222
278
|
establish_connection
|
223
279
|
end
|
224
280
|
end
|
@@ -244,6 +300,7 @@ To keep using the current cache store, you can turn off cache versioning entirel
|
|
244
300
|
|
245
301
|
initializer "active_record.set_executor_hooks" do
|
246
302
|
ActiveRecord::QueryCache.install_executor_hooks
|
303
|
+
ActiveRecord::AsynchronousQueriesTracker.install_executor_hooks
|
247
304
|
end
|
248
305
|
|
249
306
|
initializer "active_record.add_watchable_files" do |app|
|
@@ -279,5 +336,58 @@ To keep using the current cache store, you can turn off cache versioning entirel
|
|
279
336
|
self.signed_id_verifier_secret ||= -> { Rails.application.key_generator.generate_key("active_record/signed_id") }
|
280
337
|
end
|
281
338
|
end
|
339
|
+
|
340
|
+
initializer "active_record_encryption.configuration" do |app|
|
341
|
+
ActiveRecord::Encryption.configure \
|
342
|
+
primary_key: app.credentials.dig(:active_record_encryption, :primary_key),
|
343
|
+
deterministic_key: app.credentials.dig(:active_record_encryption, :deterministic_key),
|
344
|
+
key_derivation_salt: app.credentials.dig(:active_record_encryption, :key_derivation_salt),
|
345
|
+
**config.active_record.encryption
|
346
|
+
|
347
|
+
ActiveSupport.on_load(:active_record) do
|
348
|
+
# Support extended queries for deterministic attributes and validations
|
349
|
+
if ActiveRecord::Encryption.config.extend_queries
|
350
|
+
ActiveRecord::Encryption::ExtendedDeterministicQueries.install_support
|
351
|
+
ActiveRecord::Encryption::ExtendedDeterministicUniquenessValidator.install_support
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
ActiveSupport.on_load(:active_record_fixture_set) do
|
356
|
+
# Encrypt active record fixtures
|
357
|
+
if ActiveRecord::Encryption.config.encrypt_fixtures
|
358
|
+
ActiveRecord::Fixture.prepend ActiveRecord::Encryption::EncryptedFixtures
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
# Filtered params
|
363
|
+
ActiveSupport.on_load(:action_controller) do
|
364
|
+
if ActiveRecord::Encryption.config.add_to_filter_parameters
|
365
|
+
ActiveRecord::Encryption.install_auto_filtered_parameters(app)
|
366
|
+
end
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
initializer "active_record.query_log_tags_config" do |app|
|
371
|
+
config.after_initialize do
|
372
|
+
if app.config.active_record.query_log_tags_enabled
|
373
|
+
ActiveRecord.query_transformers << ActiveRecord::QueryLogs
|
374
|
+
ActiveRecord::QueryLogs.taggings.merge!(
|
375
|
+
application: Rails.application.class.name.split("::").first,
|
376
|
+
pid: -> { Process.pid },
|
377
|
+
socket: -> { ActiveRecord::Base.connection_db_config.socket },
|
378
|
+
db_host: -> { ActiveRecord::Base.connection_db_config.host },
|
379
|
+
database: -> { ActiveRecord::Base.connection_db_config.database }
|
380
|
+
)
|
381
|
+
|
382
|
+
if app.config.active_record.query_log_tags.present?
|
383
|
+
ActiveRecord::QueryLogs.tags = app.config.active_record.query_log_tags
|
384
|
+
end
|
385
|
+
|
386
|
+
if app.config.active_record.cache_query_log_tags
|
387
|
+
ActiveRecord::QueryLogs.cache_query_log_tags = true
|
388
|
+
end
|
389
|
+
end
|
390
|
+
end
|
391
|
+
end
|
282
392
|
end
|
283
393
|
end
|
@@ -86,19 +86,30 @@ db_namespace = namespace :db do
|
|
86
86
|
|
87
87
|
desc "Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)."
|
88
88
|
task migrate: :load_config do
|
89
|
-
|
90
|
-
|
91
|
-
|
89
|
+
db_configs = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env)
|
90
|
+
|
91
|
+
if db_configs.size == 1
|
92
92
|
ActiveRecord::Tasks::DatabaseTasks.migrate
|
93
|
+
else
|
94
|
+
original_db_config = ActiveRecord::Base.connection_db_config
|
95
|
+
mapped_versions = ActiveRecord::Tasks::DatabaseTasks.db_configs_with_versions(db_configs)
|
96
|
+
|
97
|
+
mapped_versions.sort.each do |version, db_configs|
|
98
|
+
db_configs.each do |db_config|
|
99
|
+
ActiveRecord::Base.establish_connection(db_config)
|
100
|
+
ActiveRecord::Tasks::DatabaseTasks.migrate(version)
|
101
|
+
end
|
102
|
+
end
|
93
103
|
end
|
104
|
+
|
94
105
|
db_namespace["_dump"].invoke
|
95
106
|
ensure
|
96
|
-
ActiveRecord::Base.establish_connection(original_db_config)
|
107
|
+
ActiveRecord::Base.establish_connection(original_db_config) if original_db_config
|
97
108
|
end
|
98
109
|
|
99
|
-
# IMPORTANT: This task won't dump the schema if ActiveRecord
|
110
|
+
# IMPORTANT: This task won't dump the schema if ActiveRecord.dump_schema_after_migration is set to false
|
100
111
|
task :_dump do
|
101
|
-
if ActiveRecord
|
112
|
+
if ActiveRecord.dump_schema_after_migration
|
102
113
|
db_namespace["schema:dump"].invoke
|
103
114
|
end
|
104
115
|
# Allow this task to be called as many times as required. An example is the
|
@@ -108,11 +119,15 @@ db_namespace = namespace :db do
|
|
108
119
|
|
109
120
|
namespace :_dump do
|
110
121
|
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
|
111
|
-
# IMPORTANT: This task won't dump the schema if ActiveRecord
|
122
|
+
# IMPORTANT: This task won't dump the schema if ActiveRecord.dump_schema_after_migration is set to false
|
112
123
|
task name do
|
113
|
-
|
124
|
+
db_config = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env, name: name)
|
125
|
+
|
126
|
+
if ActiveRecord.dump_schema_after_migration && db_config.schema_dump
|
127
|
+
ActiveRecord::Base.establish_connection(db_config)
|
114
128
|
db_namespace["schema:dump:#{name}"].invoke
|
115
129
|
end
|
130
|
+
|
116
131
|
# Allow this task to be called as many times as required. An example is the
|
117
132
|
# migrate:redo task, which calls other two internally that depend on this one.
|
118
133
|
db_namespace["_dump:#{name}"].reenable
|
@@ -275,6 +290,7 @@ db_namespace = namespace :db do
|
|
275
290
|
desc "Rolls the schema back to the previous version (specify steps w/ STEP=n)."
|
276
291
|
task rollback: :load_config do
|
277
292
|
ActiveRecord::Tasks::DatabaseTasks.raise_for_multi_db(command: "db:rollback")
|
293
|
+
raise "VERSION is not supported - To rollback a specific version, use db:migrate:down" if ENV["VERSION"]
|
278
294
|
|
279
295
|
step = ENV["STEP"] ? ENV["STEP"].to_i : 1
|
280
296
|
|
@@ -290,7 +306,16 @@ db_namespace = namespace :db do
|
|
290
306
|
db_namespace["_dump"].invoke
|
291
307
|
end
|
292
308
|
|
293
|
-
|
309
|
+
namespace :reset do
|
310
|
+
task all: ["db:drop", "db:setup"]
|
311
|
+
|
312
|
+
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
|
313
|
+
desc "Drops and recreates the #{name} database from its schema for the current environment and loads the seeds."
|
314
|
+
task name => ["db:drop:#{name}", "db:setup:#{name}"]
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
desc "Drops and recreates all databases from their schema for the current environment and loads the seeds."
|
294
319
|
task reset: [ "db:drop", "db:setup" ]
|
295
320
|
|
296
321
|
# desc "Retrieves the charset for the current environment's database"
|
@@ -307,7 +332,7 @@ db_namespace = namespace :db do
|
|
307
332
|
|
308
333
|
desc "Retrieves the current schema version number"
|
309
334
|
task version: :load_config do
|
310
|
-
puts "Current version: #{ActiveRecord::Base.connection.
|
335
|
+
puts "Current version: #{ActiveRecord::Base.connection.schema_version}"
|
311
336
|
end
|
312
337
|
|
313
338
|
# desc "Raises an error if there are pending migrations"
|
@@ -349,41 +374,21 @@ db_namespace = namespace :db do
|
|
349
374
|
end
|
350
375
|
end
|
351
376
|
|
352
|
-
|
377
|
+
namespace :setup do
|
378
|
+
task all: ["db:create", :environment, "db:schema:load", :seed]
|
379
|
+
|
380
|
+
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
|
381
|
+
desc "Creates the #{name} database, loads the schema, and initializes with the seed data (use db:reset:#{name} to also drop the database first)"
|
382
|
+
task name => ["db:create:#{name}", :environment, "db:schema:load:#{name}", "db:seed"]
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
desc "Creates all databases, loads all schemas, and initializes with the seed data (use db:reset to also drop all databases first)"
|
353
387
|
task setup: ["db:create", :environment, "db:schema:load", :seed]
|
354
388
|
|
355
389
|
desc "Runs setup if database does not exist, or runs migrations if it does"
|
356
390
|
task prepare: :load_config do
|
357
|
-
|
358
|
-
|
359
|
-
ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
|
360
|
-
ActiveRecord::Base.establish_connection(db_config)
|
361
|
-
|
362
|
-
# Skipped when no database
|
363
|
-
ActiveRecord::Tasks::DatabaseTasks.migrate
|
364
|
-
|
365
|
-
if ActiveRecord::Base.dump_schema_after_migration
|
366
|
-
ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, ActiveRecord::Base.schema_format)
|
367
|
-
end
|
368
|
-
rescue ActiveRecord::NoDatabaseError
|
369
|
-
config_name = db_config.name
|
370
|
-
ActiveRecord::Tasks::DatabaseTasks.create_current(db_config.env_name, config_name)
|
371
|
-
|
372
|
-
if File.exist?(ActiveRecord::Tasks::DatabaseTasks.dump_filename(config_name))
|
373
|
-
ActiveRecord::Tasks::DatabaseTasks.load_schema(
|
374
|
-
db_config,
|
375
|
-
ActiveRecord::Base.schema_format,
|
376
|
-
nil
|
377
|
-
)
|
378
|
-
else
|
379
|
-
ActiveRecord::Tasks::DatabaseTasks.migrate
|
380
|
-
end
|
381
|
-
|
382
|
-
seed = true
|
383
|
-
end
|
384
|
-
|
385
|
-
ActiveRecord::Base.establish_connection
|
386
|
-
ActiveRecord::Tasks::DatabaseTasks.load_seed if seed
|
391
|
+
ActiveRecord::Tasks::DatabaseTasks.prepare_all
|
387
392
|
end
|
388
393
|
|
389
394
|
desc "Loads the seed data from db/seeds.rb"
|
@@ -450,8 +455,10 @@ db_namespace = namespace :db do
|
|
450
455
|
desc "Creates a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`)"
|
451
456
|
task dump: :load_config do
|
452
457
|
ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
|
453
|
-
|
454
|
-
|
458
|
+
if db_config.schema_dump
|
459
|
+
ActiveRecord::Base.establish_connection(db_config)
|
460
|
+
ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config)
|
461
|
+
end
|
455
462
|
end
|
456
463
|
|
457
464
|
db_namespace["schema:dump"].reenable
|
@@ -459,15 +466,7 @@ db_namespace = namespace :db do
|
|
459
466
|
|
460
467
|
desc "Loads a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`) into the database"
|
461
468
|
task load: [:load_config, :check_protected_environments] do
|
462
|
-
ActiveRecord::Tasks::DatabaseTasks.load_schema_current(ActiveRecord
|
463
|
-
end
|
464
|
-
|
465
|
-
task load_if_ruby: ["db:create", :environment] do
|
466
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
467
|
-
Using `bin/rails db:schema:load_if_ruby` is deprecated and will be removed in Rails 6.2.
|
468
|
-
Configure the format using `config.active_record.schema_format = :ruby` to use `schema.rb` and run `bin/rails db:schema:load` instead.
|
469
|
-
MSG
|
470
|
-
db_namespace["schema:load"].invoke if ActiveRecord::Base.schema_format == :ruby
|
469
|
+
ActiveRecord::Tasks::DatabaseTasks.load_schema_current(ActiveRecord.schema_format, ENV["SCHEMA"])
|
471
470
|
end
|
472
471
|
|
473
472
|
namespace :dump do
|
@@ -486,8 +485,11 @@ db_namespace = namespace :db do
|
|
486
485
|
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
|
487
486
|
desc "Loads a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`) into the #{name} database"
|
488
487
|
task name => :load_config do
|
488
|
+
original_db_config = ActiveRecord::Base.connection_db_config
|
489
489
|
db_config = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env, name: name)
|
490
|
-
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config
|
490
|
+
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config)
|
491
|
+
ensure
|
492
|
+
ActiveRecord::Base.establish_connection(original_db_config) if original_db_config
|
491
493
|
end
|
492
494
|
end
|
493
495
|
end
|
@@ -523,60 +525,17 @@ db_namespace = namespace :db do
|
|
523
525
|
end
|
524
526
|
end
|
525
527
|
|
526
|
-
namespace :
|
527
|
-
desc "
|
528
|
-
task
|
529
|
-
|
530
|
-
|
531
|
-
Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:dump` instead.
|
532
|
-
MSG
|
533
|
-
|
534
|
-
db_namespace["schema:dump"].invoke
|
535
|
-
db_namespace["structure:dump"].reenable
|
536
|
-
end
|
528
|
+
namespace :encryption do
|
529
|
+
desc "Generate a set of keys for configuring Active Record encryption in a given environment"
|
530
|
+
task :init do
|
531
|
+
puts <<~MSG
|
532
|
+
Add this entry to the credentials of the target environment:#{' '}
|
537
533
|
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:load` instead.
|
534
|
+
active_record_encryption:
|
535
|
+
primary_key: #{SecureRandom.alphanumeric(32)}
|
536
|
+
deterministic_key: #{SecureRandom.alphanumeric(32)}
|
537
|
+
key_derivation_salt: #{SecureRandom.alphanumeric(32)}
|
543
538
|
MSG
|
544
|
-
db_namespace["schema:load"].invoke
|
545
|
-
end
|
546
|
-
|
547
|
-
task load_if_sql: ["db:create", :environment] do
|
548
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
549
|
-
Using `bin/rails db:structure:load_if_sql` is deprecated and will be removed in Rails 6.2.
|
550
|
-
Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:load` instead.
|
551
|
-
MSG
|
552
|
-
db_namespace["schema:load"].invoke if ActiveRecord::Base.schema_format == :sql
|
553
|
-
end
|
554
|
-
|
555
|
-
namespace :dump do
|
556
|
-
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
|
557
|
-
desc "Dumps the #{name} database structure to db/structure.sql. Specify another file with SCHEMA=db/my_structure.sql"
|
558
|
-
task name => :load_config do
|
559
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
560
|
-
Using `bin/rails db:structure:dump:#{name}` is deprecated and will be removed in Rails 6.2.
|
561
|
-
Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:dump:#{name}` instead.
|
562
|
-
MSG
|
563
|
-
db_namespace["schema:dump:#{name}"].invoke
|
564
|
-
db_namespace["structure:dump:#{name}"].reenable
|
565
|
-
end
|
566
|
-
end
|
567
|
-
end
|
568
|
-
|
569
|
-
namespace :load do
|
570
|
-
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
|
571
|
-
desc "Recreates the #{name} database from the structure.sql file"
|
572
|
-
task name => :load_config do
|
573
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
574
|
-
Using `bin/rails db:structure:load:#{name}` is deprecated and will be removed in Rails 6.2.
|
575
|
-
Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:load:#{name}` instead.
|
576
|
-
MSG
|
577
|
-
db_namespace["schema:load:#{name}"].invoke
|
578
|
-
end
|
579
|
-
end
|
580
539
|
end
|
581
540
|
end
|
582
541
|
|
@@ -591,8 +550,7 @@ db_namespace = namespace :db do
|
|
591
550
|
should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
|
592
551
|
ActiveRecord::Schema.verbose = false
|
593
552
|
ActiveRecord::Base.configurations.configs_for(env_name: "test").each do |db_config|
|
594
|
-
|
595
|
-
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ActiveRecord::Base.schema_format, filename)
|
553
|
+
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config)
|
596
554
|
end
|
597
555
|
ensure
|
598
556
|
if should_reconnect
|
@@ -600,15 +558,6 @@ db_namespace = namespace :db do
|
|
600
558
|
end
|
601
559
|
end
|
602
560
|
|
603
|
-
# desc "Recreate the test database from an existent structure.sql file"
|
604
|
-
task load_structure: %w(db:test:purge) do
|
605
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
606
|
-
Using `bin/rails db:test:load_structure` is deprecated and will be removed in Rails 6.2.
|
607
|
-
Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:test:load_schema` instead.
|
608
|
-
MSG
|
609
|
-
db_namespace["test:load_schema"].invoke
|
610
|
-
end
|
611
|
-
|
612
561
|
# desc "Empty the test database"
|
613
562
|
task purge: %w(load_config check_protected_environments) do
|
614
563
|
ActiveRecord::Base.configurations.configs_for(env_name: "test").each do |db_config|
|
@@ -636,9 +585,8 @@ db_namespace = namespace :db do
|
|
636
585
|
task name => "db:test:purge:#{name}" do
|
637
586
|
should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
|
638
587
|
ActiveRecord::Schema.verbose = false
|
639
|
-
filename = ActiveRecord::Tasks::DatabaseTasks.dump_filename(name)
|
640
588
|
db_config = ActiveRecord::Base.configurations.configs_for(env_name: "test", name: name)
|
641
|
-
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config
|
589
|
+
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config)
|
642
590
|
ensure
|
643
591
|
if should_reconnect
|
644
592
|
ActiveRecord::Base.establish_connection(ActiveRecord::Tasks::DatabaseTasks.env.to_sym)
|
@@ -646,17 +594,6 @@ db_namespace = namespace :db do
|
|
646
594
|
end
|
647
595
|
end
|
648
596
|
|
649
|
-
# desc "Recreate the #{name} test database from an existent structure.sql file"
|
650
|
-
namespace :load_structure do
|
651
|
-
task name => "db:test:purge:#{name}" do
|
652
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
653
|
-
Using `bin/rails db:test:load_structure:#{name}` is deprecated and will be removed in Rails 6.2.
|
654
|
-
Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:test:load_structure:#{name}` instead.
|
655
|
-
MSG
|
656
|
-
db_namespace["test:load_schema:#{name}"].invoke
|
657
|
-
end
|
658
|
-
end
|
659
|
-
|
660
597
|
# desc "Empty the #{name} test database"
|
661
598
|
namespace :purge do
|
662
599
|
task name => %w(load_config check_protected_environments) do
|
@@ -11,6 +11,17 @@ module ActiveRecord
|
|
11
11
|
module ClassMethods
|
12
12
|
# Attributes listed as readonly will be used to create a new record but update operations will
|
13
13
|
# ignore these fields.
|
14
|
+
#
|
15
|
+
# You can assign a new value to a readonly attribute, but it will be ignored when the record is updated.
|
16
|
+
#
|
17
|
+
# ==== Examples
|
18
|
+
#
|
19
|
+
# class Post < ActiveRecord::Base
|
20
|
+
# attr_readonly :title
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# post = Post.create!(title: "Introducing Ruby on Rails!")
|
24
|
+
# post.update(title: "a different title") # change to title will be ignored
|
14
25
|
def attr_readonly(*attributes)
|
15
26
|
self._attr_readonly = Set.new(attributes.map(&:to_s)) + (_attr_readonly || [])
|
16
27
|
end
|