activerecord 6.1.7.10 → 7.0.0.alpha1
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 +726 -1404
- 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 +31 -9
- 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 +1 -1
- 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 +14 -23
- 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 +161 -47
- data/lib/active_record/associations/preloader/batch.rb +51 -0
- data/lib/active_record/associations/preloader/branch.rb +147 -0
- data/lib/active_record/associations/preloader/through_association.rb +37 -11
- data/lib/active_record/associations/preloader.rb +46 -110
- data/lib/active_record/associations/singular_association.rb +8 -2
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +76 -81
- data/lib/active_record/asynchronous_queries_tracker.rb +57 -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 +41 -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 +6 -9
- data/lib/active_record/attributes.rb +24 -35
- data/lib/active_record/autosave_association.rb +3 -18
- data/lib/active_record/base.rb +19 -1
- data/lib/active_record/callbacks.rb +2 -2
- data/lib/active_record/coders/yaml_column.rb +2 -14
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +312 -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 +31 -558
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +45 -21
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +24 -12
- data/lib/active_record/connection_adapters/abstract/quoting.rb +12 -14
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -17
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +30 -13
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +60 -16
- data/lib/active_record/connection_adapters/abstract/transaction.rb +3 -3
- data/lib/active_record/connection_adapters/abstract_adapter.rb +112 -66
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +96 -81
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +33 -23
- data/lib/active_record/connection_adapters/mysql/quoting.rb +16 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +1 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -6
- data/lib/active_record/connection_adapters/pool_config.rb +1 -3
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +19 -14
- 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 +6 -32
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +32 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +5 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +12 -12
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +159 -102
- data/lib/active_record/connection_adapters/schema_cache.rb +36 -37
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +23 -19
- 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 +20 -38
- data/lib/active_record/core.rb +111 -125
- data/lib/active_record/database_configurations/connection_url_resolver.rb +0 -1
- data/lib/active_record/database_configurations/database_config.rb +12 -0
- data/lib/active_record/database_configurations/hash_config.rb +27 -1
- data/lib/active_record/database_configurations/url_config.rb +2 -2
- data/lib/active_record/database_configurations.rb +17 -9
- data/lib/active_record/delegated_type.rb +33 -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 +29 -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 +80 -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 +41 -41
- data/lib/active_record/errors.rb +66 -3
- data/lib/active_record/fixture_set/file.rb +15 -1
- data/lib/active_record/fixture_set/table_row.rb +40 -5
- data/lib/active_record/fixture_set/table_rows.rb +4 -4
- data/lib/active_record/fixtures.rb +16 -11
- 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 +34 -5
- data/lib/active_record/integration.rb +1 -1
- data/lib/active_record/internal_metadata.rb +1 -5
- data/lib/active_record/locking/optimistic.rb +10 -9
- data/lib/active_record/log_subscriber.rb +6 -2
- 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/migration/command_recorder.rb +4 -4
- data/lib/active_record/migration/compatibility.rb +89 -10
- 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 -31
- data/lib/active_record/nested_attributes.rb +3 -3
- data/lib/active_record/no_touching.rb +2 -2
- data/lib/active_record/null_relation.rb +2 -6
- data/lib/active_record/persistence.rb +134 -45
- data/lib/active_record/query_cache.rb +2 -2
- data/lib/active_record/query_logs.rb +203 -0
- data/lib/active_record/querying.rb +15 -5
- data/lib/active_record/railtie.rb +117 -17
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +72 -48
- data/lib/active_record/readonly_attributes.rb +11 -0
- data/lib/active_record/reflection.rb +45 -44
- 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 +39 -26
- data/lib/active_record/relation/delegation.rb +6 -6
- data/lib/active_record/relation/finder_methods.rb +31 -22
- 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 +230 -49
- data/lib/active_record/relation/record_fetch_warning.rb +2 -2
- data/lib/active_record/relation/spawn_methods.rb +2 -2
- data/lib/active_record/relation/where_clause.rb +8 -4
- data/lib/active_record/relation.rb +166 -77
- data/lib/active_record/result.rb +17 -2
- data/lib/active_record/runtime_registry.rb +2 -4
- data/lib/active_record/sanitization.rb +11 -7
- data/lib/active_record/schema_dumper.rb +3 -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 +40 -22
- data/lib/active_record/serialization.rb +1 -1
- data/lib/active_record/signed_id.rb +1 -1
- data/lib/active_record/store.rb +1 -6
- data/lib/active_record/tasks/database_tasks.rb +106 -22
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/postgresql_database_tasks.rb +14 -11
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +9 -13
- 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.rb +170 -2
- data/lib/arel/attributes/attribute.rb +0 -8
- data/lib/arel/crud.rb +18 -22
- data/lib/arel/delete_manager.rb +2 -4
- data/lib/arel/insert_manager.rb +2 -3
- data/lib/arel/nodes/casted.rb +1 -1
- data/lib/arel/nodes/delete_statement.rb +8 -13
- 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 +3 -2
- data/lib/arel/predications.rb +1 -1
- 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 +2 -4
- data/lib/arel/visitors/dot.rb +80 -90
- data/lib/arel/visitors/mysql.rb +6 -1
- data/lib/arel/visitors/postgresql.rb +0 -10
- data/lib/arel/visitors/to_sql.rb +43 -2
- data/lib/arel.rb +1 -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 +52 -14
@@ -2,6 +2,15 @@
|
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
module Scoping
|
5
|
+
class DefaultScope # :nodoc:
|
6
|
+
attr_reader :scope, :all_queries
|
7
|
+
|
8
|
+
def initialize(scope, all_queries = nil)
|
9
|
+
@scope = scope
|
10
|
+
@all_queries = all_queries
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
5
14
|
module Default
|
6
15
|
extend ActiveSupport::Concern
|
7
16
|
|
@@ -30,8 +39,8 @@ module ActiveRecord
|
|
30
39
|
# Post.unscoped {
|
31
40
|
# Post.limit(10) # Fires "SELECT * FROM posts LIMIT 10"
|
32
41
|
# }
|
33
|
-
def unscoped
|
34
|
-
block_given? ? relation.scoping
|
42
|
+
def unscoped(&block)
|
43
|
+
block_given? ? relation.scoping(&block) : relation
|
35
44
|
end
|
36
45
|
|
37
46
|
# Are there attributes associated with this scope?
|
@@ -39,10 +48,21 @@ module ActiveRecord
|
|
39
48
|
super || default_scopes.any? || respond_to?(:default_scope)
|
40
49
|
end
|
41
50
|
|
42
|
-
def before_remove_const
|
51
|
+
def before_remove_const # :nodoc:
|
43
52
|
self.current_scope = nil
|
44
53
|
end
|
45
54
|
|
55
|
+
# Checks if the model has any default scopes. If all_queries
|
56
|
+
# is set to true, the method will check if there are any
|
57
|
+
# default_scopes for the model where +all_queries+ is true.
|
58
|
+
def default_scopes?(all_queries: false)
|
59
|
+
if all_queries
|
60
|
+
self.default_scopes.any?(&:all_queries)
|
61
|
+
else
|
62
|
+
self.default_scopes.any?
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
46
66
|
private
|
47
67
|
# Use this macro in your model to set a default scope for all operations on
|
48
68
|
# the model.
|
@@ -54,11 +74,26 @@ module ActiveRecord
|
|
54
74
|
# Article.all # => SELECT * FROM articles WHERE published = true
|
55
75
|
#
|
56
76
|
# The #default_scope is also applied while creating/building a record.
|
57
|
-
# It is not applied while updating a record.
|
77
|
+
# It is not applied while updating or deleting a record.
|
58
78
|
#
|
59
79
|
# Article.new.published # => true
|
60
80
|
# Article.create.published # => true
|
61
81
|
#
|
82
|
+
# To apply a #default_scope when updating or deleting a record, add
|
83
|
+
# <tt>all_queries: true</tt>:
|
84
|
+
#
|
85
|
+
# class Article < ActiveRecord::Base
|
86
|
+
# default_scope { where(blog_id: 1) }, all_queries: true
|
87
|
+
# end
|
88
|
+
#
|
89
|
+
# Applying a default scope to all queries will ensure that records
|
90
|
+
# are always queried by the additional conditions. Note that only
|
91
|
+
# where clauses apply, as it does not make sense to add order to
|
92
|
+
# queries that return a single object by primary key.
|
93
|
+
#
|
94
|
+
# Article.find(1).destroy
|
95
|
+
# => DELETE ... FROM `articles` where ID = 1 AND blog_id = 1;
|
96
|
+
#
|
62
97
|
# (You can also pass any object which responds to +call+ to the
|
63
98
|
# +default_scope+ macro, and it will be called when building the
|
64
99
|
# default scope.)
|
@@ -85,7 +120,7 @@ module ActiveRecord
|
|
85
120
|
# # Should return a scope, you can call 'super' here etc.
|
86
121
|
# end
|
87
122
|
# end
|
88
|
-
def default_scope(scope = nil, &block) # :doc:
|
123
|
+
def default_scope(scope = nil, all_queries: nil, &block) # :doc:
|
89
124
|
scope = block if block_given?
|
90
125
|
|
91
126
|
if scope.is_a?(Relation) || !scope.respond_to?(:call)
|
@@ -96,10 +131,12 @@ module ActiveRecord
|
|
96
131
|
"self.default_scope.)"
|
97
132
|
end
|
98
133
|
|
99
|
-
|
134
|
+
default_scope = DefaultScope.new(scope, all_queries)
|
135
|
+
|
136
|
+
self.default_scopes += [default_scope]
|
100
137
|
end
|
101
138
|
|
102
|
-
def build_default_scope(relation = relation())
|
139
|
+
def build_default_scope(relation = relation(), all_queries: nil)
|
103
140
|
return if abstract_class?
|
104
141
|
|
105
142
|
if default_scope_override.nil?
|
@@ -113,20 +150,32 @@ module ActiveRecord
|
|
113
150
|
end
|
114
151
|
elsif default_scopes.any?
|
115
152
|
evaluate_default_scope do
|
116
|
-
default_scopes.inject(relation) do |default_scope,
|
117
|
-
|
118
|
-
|
153
|
+
default_scopes.inject(relation) do |default_scope, scope_obj|
|
154
|
+
if execute_scope?(all_queries, scope_obj)
|
155
|
+
scope = scope_obj.scope.respond_to?(:to_proc) ? scope_obj.scope : scope_obj.scope.method(:call)
|
156
|
+
|
157
|
+
default_scope.instance_exec(&scope) || default_scope
|
158
|
+
end
|
119
159
|
end
|
120
160
|
end
|
121
161
|
end
|
122
162
|
end
|
123
163
|
|
164
|
+
# If all_queries is nil, only execute on select and insert queries.
|
165
|
+
#
|
166
|
+
# If all_queries is true, check if the default_scope object has
|
167
|
+
# all_queries set, then execute on all queries; select, insert, update
|
168
|
+
# and delete.
|
169
|
+
def execute_scope?(all_queries, default_scope_obj)
|
170
|
+
all_queries.nil? || all_queries && default_scope_obj.all_queries
|
171
|
+
end
|
172
|
+
|
124
173
|
def ignore_default_scope?
|
125
|
-
ScopeRegistry.
|
174
|
+
ScopeRegistry.ignore_default_scope(base_class)
|
126
175
|
end
|
127
176
|
|
128
177
|
def ignore_default_scope=(ignore)
|
129
|
-
ScopeRegistry.
|
178
|
+
ScopeRegistry.set_ignore_default_scope(base_class, ignore)
|
130
179
|
end
|
131
180
|
|
132
181
|
# The ignore_default_scope flag is used to prevent an infinite recursion
|
@@ -42,8 +42,8 @@ module ActiveRecord
|
|
42
42
|
end
|
43
43
|
|
44
44
|
# Returns a scope for the model with default scopes.
|
45
|
-
def default_scoped(scope = relation)
|
46
|
-
build_default_scope(scope) || scope
|
45
|
+
def default_scoped(scope = relation, all_queries: nil)
|
46
|
+
build_default_scope(scope, all_queries: all_queries) || scope
|
47
47
|
end
|
48
48
|
|
49
49
|
def default_extensions # :nodoc:
|
@@ -168,7 +168,6 @@ module ActiveRecord
|
|
168
168
|
"an instance method with the same name."
|
169
169
|
end
|
170
170
|
|
171
|
-
valid_scope_name?(name)
|
172
171
|
extension = Module.new(&block) if block
|
173
172
|
|
174
173
|
if body.respond_to?(:to_proc)
|
@@ -184,7 +183,7 @@ module ActiveRecord
|
|
184
183
|
scope
|
185
184
|
end
|
186
185
|
end
|
187
|
-
singleton_class.send(:ruby2_keywords, name)
|
186
|
+
singleton_class.send(:ruby2_keywords, name)
|
188
187
|
|
189
188
|
generate_relation_method(name)
|
190
189
|
end
|
@@ -193,13 +192,6 @@ module ActiveRecord
|
|
193
192
|
def singleton_method_added(name)
|
194
193
|
generate_relation_method(name) if Kernel.respond_to?(name) && !ActiveRecord::Relation.method_defined?(name)
|
195
194
|
end
|
196
|
-
|
197
|
-
def valid_scope_name?(name)
|
198
|
-
if respond_to?(name, true) && logger
|
199
|
-
logger.warn "Creating scope :#{name}. " \
|
200
|
-
"Overwriting existing method #{self.name}.#{name}."
|
201
|
-
end
|
202
|
-
end
|
203
195
|
end
|
204
196
|
end
|
205
197
|
end
|
@@ -24,11 +24,23 @@ module ActiveRecord
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def current_scope(skip_inherited_scope = false)
|
27
|
-
ScopeRegistry.
|
27
|
+
ScopeRegistry.current_scope(self, skip_inherited_scope)
|
28
28
|
end
|
29
29
|
|
30
30
|
def current_scope=(scope)
|
31
|
-
ScopeRegistry.
|
31
|
+
ScopeRegistry.set_current_scope(self, scope)
|
32
|
+
end
|
33
|
+
|
34
|
+
def global_current_scope(skip_inherited_scope = false)
|
35
|
+
ScopeRegistry.global_current_scope(self, skip_inherited_scope)
|
36
|
+
end
|
37
|
+
|
38
|
+
def global_current_scope=(scope)
|
39
|
+
ScopeRegistry.set_global_current_scope(self, scope)
|
40
|
+
end
|
41
|
+
|
42
|
+
def scope_registry
|
43
|
+
ScopeRegistry.instance
|
32
44
|
end
|
33
45
|
end
|
34
46
|
|
@@ -69,37 +81,43 @@ module ActiveRecord
|
|
69
81
|
class ScopeRegistry # :nodoc:
|
70
82
|
extend ActiveSupport::PerThreadRegistry
|
71
83
|
|
72
|
-
VALID_SCOPE_TYPES = [:current_scope, :ignore_default_scope]
|
84
|
+
VALID_SCOPE_TYPES = [:current_scope, :ignore_default_scope, :global_current_scope]
|
73
85
|
|
74
86
|
def initialize
|
75
|
-
@
|
87
|
+
@current_scope = {}
|
88
|
+
@ignore_default_scope = {}
|
89
|
+
@global_current_scope = {}
|
76
90
|
end
|
77
91
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
klass = model
|
83
|
-
base = model.base_class
|
84
|
-
while klass <= base
|
85
|
-
value = @registry[scope_type][klass.name]
|
86
|
-
return value if value
|
87
|
-
klass = klass.superclass
|
92
|
+
VALID_SCOPE_TYPES.each do |type|
|
93
|
+
class_eval <<-eorb, __FILE__, __LINE__
|
94
|
+
def #{type}(model, skip_inherited_scope = false)
|
95
|
+
value_for(@#{type}, model, skip_inherited_scope)
|
88
96
|
end
|
89
|
-
end
|
90
97
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
98
|
+
def set_#{type}(model, value)
|
99
|
+
set_value_for(@#{type}, model, value)
|
100
|
+
end
|
101
|
+
eorb
|
95
102
|
end
|
96
103
|
|
97
104
|
private
|
98
|
-
|
99
|
-
|
100
|
-
|
105
|
+
# Obtains the value for a given +scope_type+ and +model+.
|
106
|
+
def value_for(scope_type, model, skip_inherited_scope = false)
|
107
|
+
return scope_type[model.name] if skip_inherited_scope
|
108
|
+
klass = model
|
109
|
+
base = model.base_class
|
110
|
+
while klass <= base
|
111
|
+
value = scope_type[klass.name]
|
112
|
+
return value if value
|
113
|
+
klass = klass.superclass
|
101
114
|
end
|
102
115
|
end
|
116
|
+
|
117
|
+
# Sets the +value+ for a given +scope_type+ and +model+.
|
118
|
+
def set_value_for(scope_type, model, value)
|
119
|
+
scope_type[model.name] = value
|
120
|
+
end
|
103
121
|
end
|
104
122
|
end
|
105
123
|
end
|
@@ -10,7 +10,7 @@ module ActiveRecord
|
|
10
10
|
# :singleton-method:
|
11
11
|
# Set the secret used for the signed id verifier instance when using Active Record outside of Rails.
|
12
12
|
# Within Rails, this is automatically set using the Rails application key generator.
|
13
|
-
|
13
|
+
class_attribute :signed_id_verifier_secret, instance_writer: false
|
14
14
|
end
|
15
15
|
|
16
16
|
module ClassMethods
|
data/lib/active_record/store.rb
CHANGED
@@ -268,7 +268,7 @@ module ActiveRecord
|
|
268
268
|
end
|
269
269
|
|
270
270
|
def dump(obj)
|
271
|
-
@coder.dump
|
271
|
+
@coder.dump self.class.as_indifferent_hash(obj)
|
272
272
|
end
|
273
273
|
|
274
274
|
def load(yaml)
|
@@ -285,11 +285,6 @@ module ActiveRecord
|
|
285
285
|
ActiveSupport::HashWithIndifferentAccess.new
|
286
286
|
end
|
287
287
|
end
|
288
|
-
|
289
|
-
private
|
290
|
-
def as_regular_hash(obj)
|
291
|
-
obj.respond_to?(:to_hash) ? obj.to_hash : {}
|
292
|
-
end
|
293
288
|
end
|
294
289
|
end
|
295
290
|
end
|
@@ -39,11 +39,18 @@ module ActiveRecord
|
|
39
39
|
##
|
40
40
|
# :singleton-method:
|
41
41
|
# Extra flags passed to database CLI tool (mysqldump/pg_dump) when calling db:schema:dump
|
42
|
+
# It can be used as a string/array (the typical case) or a hash (when you use multiple adapters)
|
43
|
+
# Example:
|
44
|
+
# ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = {
|
45
|
+
# mysql2: ['--no-defaults', '--skip-add-drop-table'],
|
46
|
+
# postgres: '--no-tablespaces'
|
47
|
+
# }
|
42
48
|
mattr_accessor :structure_dump_flags, instance_accessor: false
|
43
49
|
|
44
50
|
##
|
45
51
|
# :singleton-method:
|
46
52
|
# Extra flags passed to database CLI tool when calling db:schema:load
|
53
|
+
# It can be used as a string/array (the typical case) or a hash (when you use multiple adapters)
|
47
54
|
mattr_accessor :structure_load_flags, instance_accessor: false
|
48
55
|
|
49
56
|
extend self
|
@@ -123,7 +130,7 @@ module ActiveRecord
|
|
123
130
|
env_name = options[:env] || env
|
124
131
|
name = options[:spec] || "primary"
|
125
132
|
|
126
|
-
@current_config ||=
|
133
|
+
@current_config ||= configs_for(env_name: env_name, name: name)&.configuration_hash
|
127
134
|
end
|
128
135
|
end
|
129
136
|
deprecate :current_config
|
@@ -154,7 +161,7 @@ module ActiveRecord
|
|
154
161
|
begin
|
155
162
|
Rails.application.config.load_database_yaml
|
156
163
|
rescue
|
157
|
-
unless ActiveRecord
|
164
|
+
unless ActiveRecord.suppress_multiple_database_warning
|
158
165
|
$stderr.puts "Rails couldn't infer whether you are using multiple databases from your database.yml and can't generate the tasks for the non-primary databases. If you'd like to use this feature, please simplify your ERB."
|
159
166
|
end
|
160
167
|
|
@@ -171,12 +178,14 @@ module ActiveRecord
|
|
171
178
|
return if database_configs.count == 1
|
172
179
|
|
173
180
|
database_configs.each do |db_config|
|
181
|
+
next unless db_config.database_tasks?
|
182
|
+
|
174
183
|
yield db_config.name
|
175
184
|
end
|
176
185
|
end
|
177
186
|
|
178
187
|
def raise_for_multi_db(environment = env, command:)
|
179
|
-
db_configs =
|
188
|
+
db_configs = configs_for(env_name: environment)
|
180
189
|
|
181
190
|
if db_configs.count > 1
|
182
191
|
dbs_list = []
|
@@ -194,6 +203,39 @@ module ActiveRecord
|
|
194
203
|
ActiveRecord::Base.establish_connection(environment.to_sym)
|
195
204
|
end
|
196
205
|
|
206
|
+
def prepare_all
|
207
|
+
seed = false
|
208
|
+
|
209
|
+
configs_for(env_name: env).each do |db_config|
|
210
|
+
ActiveRecord::Base.establish_connection(db_config)
|
211
|
+
|
212
|
+
# Skipped when no database
|
213
|
+
migrate
|
214
|
+
|
215
|
+
if ActiveRecord.dump_schema_after_migration
|
216
|
+
dump_schema(db_config, ActiveRecord.schema_format)
|
217
|
+
end
|
218
|
+
rescue ActiveRecord::NoDatabaseError
|
219
|
+
config_name = db_config.name
|
220
|
+
create_current(db_config.env_name, config_name)
|
221
|
+
|
222
|
+
if File.exist?(dump_filename(config_name))
|
223
|
+
load_schema(
|
224
|
+
db_config,
|
225
|
+
ActiveRecord.schema_format,
|
226
|
+
nil
|
227
|
+
)
|
228
|
+
else
|
229
|
+
migrate
|
230
|
+
end
|
231
|
+
|
232
|
+
seed = true
|
233
|
+
end
|
234
|
+
|
235
|
+
ActiveRecord::Base.establish_connection
|
236
|
+
load_seed if seed
|
237
|
+
end
|
238
|
+
|
197
239
|
def drop(configuration, *arguments)
|
198
240
|
db_config = resolve_configuration(configuration)
|
199
241
|
database_adapter_for(db_config, *arguments).drop
|
@@ -223,19 +265,21 @@ module ActiveRecord
|
|
223
265
|
private :truncate_tables
|
224
266
|
|
225
267
|
def truncate_all(environment = env)
|
226
|
-
|
268
|
+
configs_for(env_name: environment).each do |db_config|
|
227
269
|
truncate_tables(db_config)
|
228
270
|
end
|
229
271
|
end
|
230
272
|
|
231
|
-
def migrate
|
273
|
+
def migrate(version = nil)
|
232
274
|
check_target_version
|
233
275
|
|
234
276
|
scope = ENV["SCOPE"]
|
235
277
|
verbose_was, Migration.verbose = Migration.verbose, verbose?
|
236
278
|
|
237
|
-
Base.connection.migration_context.migrate(target_version) do |migration|
|
279
|
+
Base.connection.migration_context.migrate(target_version || version) do |migration|
|
238
280
|
scope.blank? || scope == migration.scope
|
281
|
+
end.tap do |migrations_ran|
|
282
|
+
Migration.write("No migrations ran. (using #{scope} scope)") if scope.present? && migrations_ran.empty?
|
239
283
|
end
|
240
284
|
|
241
285
|
ActiveRecord::Base.clear_cache!
|
@@ -243,6 +287,23 @@ module ActiveRecord
|
|
243
287
|
Migration.verbose = verbose_was
|
244
288
|
end
|
245
289
|
|
290
|
+
def db_configs_with_versions(db_configs) # :nodoc:
|
291
|
+
db_configs_with_versions = Hash.new { |h, k| h[k] = [] }
|
292
|
+
|
293
|
+
db_configs.each do |db_config|
|
294
|
+
ActiveRecord::Base.establish_connection(db_config)
|
295
|
+
versions_to_run = ActiveRecord::Base.connection.migration_context.pending_migration_versions
|
296
|
+
target_version = ActiveRecord::Tasks::DatabaseTasks.target_version
|
297
|
+
|
298
|
+
versions_to_run.each do |version|
|
299
|
+
next if target_version && target_version != version
|
300
|
+
db_configs_with_versions[version] << db_config
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
db_configs_with_versions
|
305
|
+
end
|
306
|
+
|
246
307
|
def migrate_status
|
247
308
|
unless ActiveRecord::Base.connection.schema_migration.table_exists?
|
248
309
|
Kernel.abort "Schema migrations table does not exist yet."
|
@@ -269,7 +330,7 @@ module ActiveRecord
|
|
269
330
|
end
|
270
331
|
|
271
332
|
def charset_current(env_name = env, db_name = name)
|
272
|
-
db_config =
|
333
|
+
db_config = configs_for(env_name: env_name, name: db_name)
|
273
334
|
charset(db_config)
|
274
335
|
end
|
275
336
|
|
@@ -279,7 +340,7 @@ module ActiveRecord
|
|
279
340
|
end
|
280
341
|
|
281
342
|
def collation_current(env_name = env, db_name = name)
|
282
|
-
db_config =
|
343
|
+
db_config = configs_for(env_name: env_name, name: db_name)
|
283
344
|
collation(db_config)
|
284
345
|
end
|
285
346
|
|
@@ -305,16 +366,18 @@ module ActiveRecord
|
|
305
366
|
def structure_dump(configuration, *arguments)
|
306
367
|
db_config = resolve_configuration(configuration)
|
307
368
|
filename = arguments.delete_at(0)
|
308
|
-
|
369
|
+
flags = structure_dump_flags_for(db_config.adapter)
|
370
|
+
database_adapter_for(db_config, *arguments).structure_dump(filename, flags)
|
309
371
|
end
|
310
372
|
|
311
373
|
def structure_load(configuration, *arguments)
|
312
374
|
db_config = resolve_configuration(configuration)
|
313
375
|
filename = arguments.delete_at(0)
|
314
|
-
|
376
|
+
flags = structure_load_flags_for(db_config.adapter)
|
377
|
+
database_adapter_for(db_config, *arguments).structure_load(filename, flags)
|
315
378
|
end
|
316
379
|
|
317
|
-
def load_schema(db_config, format = ActiveRecord
|
380
|
+
def load_schema(db_config, format = ActiveRecord.schema_format, file = nil) # :nodoc:
|
318
381
|
file ||= dump_filename(db_config.name, format)
|
319
382
|
|
320
383
|
verbose_was, Migration.verbose = Migration.verbose, verbose? && ENV["VERBOSE"]
|
@@ -336,7 +399,7 @@ module ActiveRecord
|
|
336
399
|
Migration.verbose = verbose_was
|
337
400
|
end
|
338
401
|
|
339
|
-
def schema_up_to_date?(configuration, format = ActiveRecord
|
402
|
+
def schema_up_to_date?(configuration, format = ActiveRecord.schema_format, file = nil, environment = nil, name = nil)
|
340
403
|
db_config = resolve_configuration(configuration)
|
341
404
|
|
342
405
|
if environment || name
|
@@ -357,7 +420,7 @@ module ActiveRecord
|
|
357
420
|
ActiveRecord::InternalMetadata[:schema_sha1] == schema_sha1(file)
|
358
421
|
end
|
359
422
|
|
360
|
-
def reconstruct_from_schema(db_config, format = ActiveRecord
|
423
|
+
def reconstruct_from_schema(db_config, format = ActiveRecord.schema_format, file = nil) # :nodoc:
|
361
424
|
file ||= dump_filename(db_config.name, format)
|
362
425
|
|
363
426
|
check_schema_file(file)
|
@@ -375,7 +438,7 @@ module ActiveRecord
|
|
375
438
|
load_schema(db_config, format, file)
|
376
439
|
end
|
377
440
|
|
378
|
-
def dump_schema(db_config, format = ActiveRecord
|
441
|
+
def dump_schema(db_config, format = ActiveRecord.schema_format) # :nodoc:
|
379
442
|
require "active_record/schema_dumper"
|
380
443
|
filename = dump_filename(db_config.name, format)
|
381
444
|
connection = ActiveRecord::Base.connection
|
@@ -397,11 +460,12 @@ module ActiveRecord
|
|
397
460
|
end
|
398
461
|
end
|
399
462
|
|
400
|
-
def schema_file(format = ActiveRecord
|
463
|
+
def schema_file(format = ActiveRecord.schema_format)
|
401
464
|
File.join(db_dir, schema_file_type(format))
|
402
465
|
end
|
466
|
+
deprecate :schema_file
|
403
467
|
|
404
|
-
def schema_file_type(format = ActiveRecord
|
468
|
+
def schema_file_type(format = ActiveRecord.schema_format)
|
405
469
|
case format
|
406
470
|
when :ruby
|
407
471
|
"schema.rb"
|
@@ -410,7 +474,7 @@ module ActiveRecord
|
|
410
474
|
end
|
411
475
|
end
|
412
476
|
|
413
|
-
def dump_filename(db_config_name, format = ActiveRecord
|
477
|
+
def dump_filename(db_config_name, format = ActiveRecord.schema_format)
|
414
478
|
filename = if ActiveRecord::Base.configurations.primary?(db_config_name)
|
415
479
|
schema_file_type(format)
|
416
480
|
else
|
@@ -430,7 +494,7 @@ module ActiveRecord
|
|
430
494
|
schema_cache_path || ENV["SCHEMA_CACHE"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
|
431
495
|
end
|
432
496
|
|
433
|
-
def load_schema_current(format = ActiveRecord
|
497
|
+
def load_schema_current(format = ActiveRecord.schema_format, file = nil, environment = env)
|
434
498
|
each_current_configuration(environment) do |db_config|
|
435
499
|
load_schema(db_config, format, file)
|
436
500
|
end
|
@@ -468,6 +532,10 @@ module ActiveRecord
|
|
468
532
|
end
|
469
533
|
|
470
534
|
private
|
535
|
+
def configs_for(**options)
|
536
|
+
Base.configurations.configs_for(**options)
|
537
|
+
end
|
538
|
+
|
471
539
|
def resolve_configuration(configuration)
|
472
540
|
Base.configurations.resolve(configuration)
|
473
541
|
end
|
@@ -488,7 +556,7 @@ module ActiveRecord
|
|
488
556
|
end
|
489
557
|
|
490
558
|
def class_for_adapter(adapter)
|
491
|
-
_key, task = @tasks.
|
559
|
+
_key, task = @tasks.reverse_each.detect { |pattern, _task| adapter[pattern] }
|
492
560
|
unless task
|
493
561
|
raise DatabaseNotSupported, "Rake tasks not supported by '#{adapter}' adapter"
|
494
562
|
end
|
@@ -500,7 +568,7 @@ module ActiveRecord
|
|
500
568
|
environments << "test" if environment == "development" && !ENV["SKIP_TEST_DATABASE"] && !ENV["DATABASE_URL"]
|
501
569
|
|
502
570
|
environments.each do |env|
|
503
|
-
|
571
|
+
configs_for(env_name: env).each do |db_config|
|
504
572
|
next if name && name != db_config.name
|
505
573
|
|
506
574
|
yield db_config
|
@@ -509,7 +577,7 @@ module ActiveRecord
|
|
509
577
|
end
|
510
578
|
|
511
579
|
def each_local_configuration
|
512
|
-
|
580
|
+
configs_for.each do |db_config|
|
513
581
|
next unless db_config.database
|
514
582
|
|
515
583
|
if local_database?(db_config)
|
@@ -526,7 +594,23 @@ module ActiveRecord
|
|
526
594
|
end
|
527
595
|
|
528
596
|
def schema_sha1(file)
|
529
|
-
Digest::SHA1.hexdigest(File.read(file))
|
597
|
+
OpenSSL::Digest::SHA1.hexdigest(File.read(file))
|
598
|
+
end
|
599
|
+
|
600
|
+
def structure_dump_flags_for(adapter)
|
601
|
+
if structure_dump_flags.is_a?(Hash)
|
602
|
+
structure_dump_flags[adapter.to_sym]
|
603
|
+
else
|
604
|
+
structure_dump_flags
|
605
|
+
end
|
606
|
+
end
|
607
|
+
|
608
|
+
def structure_load_flags_for(adapter)
|
609
|
+
if structure_load_flags.is_a?(Hash)
|
610
|
+
structure_load_flags[adapter.to_sym]
|
611
|
+
else
|
612
|
+
structure_load_flags
|
613
|
+
end
|
530
614
|
end
|
531
615
|
end
|
532
616
|
end
|
@@ -94,7 +94,7 @@ module ActiveRecord
|
|
94
94
|
sslcapath: "--ssl-capath",
|
95
95
|
sslcipher: "--ssl-cipher",
|
96
96
|
sslkey: "--ssl-key"
|
97
|
-
}.
|
97
|
+
}.filter_map { |opt, arg| "#{arg}=#{configuration_hash[opt]}" if configuration_hash[opt] }
|
98
98
|
|
99
99
|
args
|
100
100
|
end
|
@@ -47,16 +47,14 @@ module ActiveRecord
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def structure_dump(filename, extra_flags)
|
50
|
-
set_psql_env
|
51
|
-
|
52
50
|
search_path = \
|
53
|
-
case ActiveRecord
|
51
|
+
case ActiveRecord.dump_schemas
|
54
52
|
when :schema_search_path
|
55
53
|
configuration_hash[:schema_search_path]
|
56
54
|
when :all
|
57
55
|
nil
|
58
56
|
when String
|
59
|
-
ActiveRecord
|
57
|
+
ActiveRecord.dump_schemas
|
60
58
|
end
|
61
59
|
|
62
60
|
args = ["--schema-only", "--no-privileges", "--no-owner", "--file", filename]
|
@@ -79,7 +77,6 @@ module ActiveRecord
|
|
79
77
|
end
|
80
78
|
|
81
79
|
def structure_load(filename, extra_flags)
|
82
|
-
set_psql_env
|
83
80
|
args = ["--set", ON_ERROR_STOP_1, "--quiet", "--no-psqlrc", "--file", filename]
|
84
81
|
args.concat(Array(extra_flags)) if extra_flags
|
85
82
|
args << db_config.database
|
@@ -100,15 +97,21 @@ module ActiveRecord
|
|
100
97
|
)
|
101
98
|
end
|
102
99
|
|
103
|
-
def
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
100
|
+
def psql_env
|
101
|
+
{}.tap do |env|
|
102
|
+
env["PGHOST"] = db_config.host if db_config.host
|
103
|
+
env["PGPORT"] = configuration_hash[:port].to_s if configuration_hash[:port]
|
104
|
+
env["PGPASSWORD"] = configuration_hash[:password].to_s if configuration_hash[:password]
|
105
|
+
env["PGUSER"] = configuration_hash[:username].to_s if configuration_hash[:username]
|
106
|
+
env["PGSSLMODE"] = configuration_hash[:sslmode].to_s if configuration_hash[:sslmode]
|
107
|
+
env["PGSSLCERT"] = configuration_hash[:sslcert].to_s if configuration_hash[:sslcert]
|
108
|
+
env["PGSSLKEY"] = configuration_hash[:sslkey].to_s if configuration_hash[:sslkey]
|
109
|
+
env["PGSSLROOTCERT"] = configuration_hash[:sslrootcert].to_s if configuration_hash[:sslrootcert]
|
110
|
+
end
|
108
111
|
end
|
109
112
|
|
110
113
|
def run_cmd(cmd, args, action)
|
111
|
-
fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args)
|
114
|
+
fail run_cmd_error(cmd, args, action) unless Kernel.system(psql_env, cmd, *args)
|
112
115
|
end
|
113
116
|
|
114
117
|
def run_cmd_error(cmd, args, action)
|