activerecord 7.0.8.7 → 7.1.0.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1339 -1572
- data/MIT-LICENSE +1 -1
- data/README.rdoc +15 -16
- data/lib/active_record/aggregations.rb +16 -13
- data/lib/active_record/association_relation.rb +1 -1
- data/lib/active_record/associations/association.rb +18 -3
- data/lib/active_record/associations/association_scope.rb +16 -9
- data/lib/active_record/associations/belongs_to_association.rb +14 -6
- data/lib/active_record/associations/builder/association.rb +3 -3
- data/lib/active_record/associations/builder/belongs_to.rb +21 -8
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
- data/lib/active_record/associations/builder/singular_association.rb +4 -0
- data/lib/active_record/associations/collection_association.rb +17 -9
- data/lib/active_record/associations/collection_proxy.rb +16 -11
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +20 -13
- data/lib/active_record/associations/has_many_through_association.rb +10 -6
- data/lib/active_record/associations/has_one_association.rb +10 -3
- data/lib/active_record/associations/join_dependency.rb +10 -8
- data/lib/active_record/associations/preloader/association.rb +27 -6
- data/lib/active_record/associations/preloader.rb +12 -9
- data/lib/active_record/associations/singular_association.rb +1 -1
- data/lib/active_record/associations/through_association.rb +22 -11
- data/lib/active_record/associations.rb +193 -97
- data/lib/active_record/attribute_assignment.rb +0 -2
- data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
- data/lib/active_record/attribute_methods/dirty.rb +40 -26
- data/lib/active_record/attribute_methods/primary_key.rb +76 -24
- data/lib/active_record/attribute_methods/query.rb +28 -16
- data/lib/active_record/attribute_methods/read.rb +18 -5
- data/lib/active_record/attribute_methods/serialization.rb +150 -31
- data/lib/active_record/attribute_methods/write.rb +3 -3
- data/lib/active_record/attribute_methods.rb +105 -21
- data/lib/active_record/attributes.rb +3 -3
- data/lib/active_record/autosave_association.rb +55 -9
- data/lib/active_record/base.rb +7 -2
- data/lib/active_record/callbacks.rb +10 -24
- data/lib/active_record/coders/column_serializer.rb +61 -0
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +70 -42
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +163 -88
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +3 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +63 -43
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +109 -32
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +60 -22
- data/lib/active_record/connection_adapters/abstract/quoting.rb +41 -6
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +18 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +137 -11
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +289 -122
- data/lib/active_record/connection_adapters/abstract/transaction.rb +280 -58
- data/lib/active_record/connection_adapters/abstract_adapter.rb +502 -91
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +200 -108
- data/lib/active_record/connection_adapters/column.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +22 -143
- data/lib/active_record/connection_adapters/mysql/quoting.rb +16 -12
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +6 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +17 -12
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +148 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +98 -53
- data/lib/active_record/connection_adapters/pool_config.rb +14 -5
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +76 -29
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +11 -2
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +9 -6
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +3 -9
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +131 -2
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +42 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +351 -54
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +336 -168
- data/lib/active_record/connection_adapters/schema_cache.rb +287 -59
- data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +42 -36
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +4 -3
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +1 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +26 -7
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +162 -77
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +98 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +254 -0
- data/lib/active_record/connection_adapters.rb +3 -1
- data/lib/active_record/connection_handling.rb +71 -94
- data/lib/active_record/core.rb +128 -138
- data/lib/active_record/counter_cache.rb +46 -25
- data/lib/active_record/database_configurations/database_config.rb +9 -3
- data/lib/active_record/database_configurations/hash_config.rb +22 -12
- data/lib/active_record/database_configurations/url_config.rb +17 -11
- data/lib/active_record/database_configurations.rb +86 -33
- data/lib/active_record/delegated_type.rb +8 -3
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +2 -0
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +4 -1
- data/lib/active_record/encryption/config.rb +25 -1
- data/lib/active_record/encryption/configurable.rb +12 -19
- data/lib/active_record/encryption/context.rb +10 -3
- data/lib/active_record/encryption/contexts.rb +5 -1
- data/lib/active_record/encryption/derived_secret_key_provider.rb +8 -2
- data/lib/active_record/encryption/encryptable_record.rb +36 -18
- data/lib/active_record/encryption/encrypted_attribute_type.rb +17 -6
- data/lib/active_record/encryption/extended_deterministic_queries.rb +66 -54
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +2 -2
- data/lib/active_record/encryption/key_generator.rb +12 -1
- data/lib/active_record/encryption/message_serializer.rb +2 -0
- data/lib/active_record/encryption/properties.rb +3 -3
- data/lib/active_record/encryption/scheme.rb +19 -22
- data/lib/active_record/encryption.rb +1 -0
- data/lib/active_record/enum.rb +113 -26
- data/lib/active_record/errors.rb +89 -15
- data/lib/active_record/explain.rb +23 -3
- data/lib/active_record/fixture_set/model_metadata.rb +14 -4
- data/lib/active_record/fixture_set/render_context.rb +2 -0
- data/lib/active_record/fixture_set/table_row.rb +29 -8
- data/lib/active_record/fixtures.rb +119 -71
- data/lib/active_record/future_result.rb +30 -5
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +30 -16
- data/lib/active_record/insert_all.rb +55 -8
- data/lib/active_record/integration.rb +8 -8
- data/lib/active_record/internal_metadata.rb +118 -30
- data/lib/active_record/locking/pessimistic.rb +5 -2
- data/lib/active_record/log_subscriber.rb +29 -12
- data/lib/active_record/marshalling.rb +56 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +4 -0
- data/lib/active_record/middleware/database_selector.rb +5 -7
- data/lib/active_record/middleware/shard_selector.rb +3 -1
- data/lib/active_record/migration/command_recorder.rb +100 -4
- data/lib/active_record/migration/compatibility.rb +131 -5
- data/lib/active_record/migration/default_strategy.rb +23 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration.rb +213 -109
- data/lib/active_record/model_schema.rb +47 -27
- data/lib/active_record/nested_attributes.rb +28 -3
- data/lib/active_record/normalization.rb +158 -0
- data/lib/active_record/persistence.rb +183 -33
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +3 -21
- data/lib/active_record/query_logs.rb +77 -52
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +15 -2
- data/lib/active_record/railtie.rb +107 -45
- data/lib/active_record/railties/controller_runtime.rb +10 -5
- data/lib/active_record/railties/databases.rake +139 -145
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +32 -5
- data/lib/active_record/reflection.rb +169 -45
- data/lib/active_record/relation/batches/batch_enumerator.rb +5 -3
- data/lib/active_record/relation/batches.rb +190 -61
- data/lib/active_record/relation/calculations.rb +152 -63
- data/lib/active_record/relation/delegation.rb +22 -8
- data/lib/active_record/relation/finder_methods.rb +85 -15
- data/lib/active_record/relation/merger.rb +2 -0
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +11 -2
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +26 -14
- data/lib/active_record/relation/query_attribute.rb +2 -1
- data/lib/active_record/relation/query_methods.rb +351 -62
- data/lib/active_record/relation/spawn_methods.rb +18 -1
- data/lib/active_record/relation.rb +76 -35
- data/lib/active_record/result.rb +19 -5
- data/lib/active_record/runtime_registry.rb +10 -1
- data/lib/active_record/sanitization.rb +51 -11
- data/lib/active_record/schema.rb +2 -3
- data/lib/active_record/schema_dumper.rb +41 -7
- data/lib/active_record/schema_migration.rb +68 -33
- data/lib/active_record/scoping/default.rb +15 -5
- data/lib/active_record/scoping/named.rb +2 -2
- data/lib/active_record/scoping.rb +2 -1
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/signed_id.rb +7 -5
- data/lib/active_record/store.rb +8 -8
- data/lib/active_record/suppressor.rb +3 -1
- data/lib/active_record/table_metadata.rb +10 -1
- data/lib/active_record/tasks/database_tasks.rb +127 -105
- data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
- data/lib/active_record/tasks/postgresql_database_tasks.rb +16 -13
- data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -7
- data/lib/active_record/test_fixtures.rb +113 -96
- data/lib/active_record/timestamp.rb +26 -14
- data/lib/active_record/token_for.rb +113 -0
- data/lib/active_record/touch_later.rb +11 -6
- data/lib/active_record/transactions.rb +36 -10
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/numericality.rb +5 -4
- data/lib/active_record/validations/presence.rb +5 -28
- data/lib/active_record/validations/uniqueness.rb +47 -2
- data/lib/active_record/validations.rb +8 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +121 -16
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/nodes/binary.rb +6 -1
- data/lib/arel/nodes/bound_sql_literal.rb +61 -0
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/homogeneous_in.rb +0 -8
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/node.rb +111 -2
- data/lib/arel/nodes/sql_literal.rb +6 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes.rb +4 -0
- data/lib/arel/predications.rb +2 -0
- data/lib/arel/table.rb +9 -5
- data/lib/arel/visitors/mysql.rb +8 -1
- data/lib/arel/visitors/to_sql.rb +81 -17
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +16 -2
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/migration.rb +3 -1
- data/lib/rails/generators/active_record/model/USAGE +113 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
- metadata +52 -17
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -63
data/lib/active_record/core.rb
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_support/core_ext/enumerable"
|
4
|
-
require "active_support/core_ext/
|
5
|
-
require "active_support/core_ext/string/filters"
|
4
|
+
require "active_support/core_ext/module/delegation"
|
6
5
|
require "active_support/parameter_filter"
|
7
6
|
require "concurrent/map"
|
8
7
|
|
9
8
|
module ActiveRecord
|
9
|
+
# = Active Record \Core
|
10
10
|
module Core
|
11
11
|
extend ActiveSupport::Concern
|
12
|
+
include ActiveModel::Access
|
12
13
|
|
13
14
|
included do
|
14
15
|
##
|
@@ -19,11 +20,30 @@ module ActiveRecord
|
|
19
20
|
# retrieved on both a class and instance level by calling +logger+.
|
20
21
|
class_attribute :logger, instance_writer: false
|
21
22
|
|
23
|
+
class_attribute :_destroy_association_async_job, instance_accessor: false, default: "ActiveRecord::DestroyAssociationAsyncJob"
|
24
|
+
|
25
|
+
# The job class used to destroy associations in the background.
|
26
|
+
def self.destroy_association_async_job
|
27
|
+
if _destroy_association_async_job.is_a?(String)
|
28
|
+
self._destroy_association_async_job = _destroy_association_async_job.constantize
|
29
|
+
end
|
30
|
+
_destroy_association_async_job
|
31
|
+
rescue NameError => error
|
32
|
+
raise NameError, "Unable to load destroy_association_async_job: #{error.message}"
|
33
|
+
end
|
34
|
+
|
35
|
+
singleton_class.alias_method :destroy_association_async_job=, :_destroy_association_async_job=
|
36
|
+
delegate :destroy_association_async_job, to: :class
|
37
|
+
|
22
38
|
##
|
23
39
|
# :singleton-method:
|
24
40
|
#
|
25
|
-
# Specifies the
|
26
|
-
|
41
|
+
# Specifies the maximum number of records that will be destroyed in a
|
42
|
+
# single background job by the <tt>dependent: :destroy_async</tt>
|
43
|
+
# association option. When +nil+ (default), all dependent records will be
|
44
|
+
# destroyed in a single background job. If specified, the records to be
|
45
|
+
# destroyed will be split into multiple background jobs.
|
46
|
+
class_attribute :destroy_association_async_batch_size, instance_writer: false, instance_predicate: false, default: nil
|
27
47
|
|
28
48
|
##
|
29
49
|
# Contains the database configuration - as is typically stored in config/database.yml -
|
@@ -33,19 +53,19 @@ module ActiveRecord
|
|
33
53
|
#
|
34
54
|
# development:
|
35
55
|
# adapter: sqlite3
|
36
|
-
# database:
|
56
|
+
# database: storage/development.sqlite3
|
37
57
|
#
|
38
58
|
# production:
|
39
59
|
# adapter: sqlite3
|
40
|
-
# database:
|
60
|
+
# database: storage/production.sqlite3
|
41
61
|
#
|
42
62
|
# ...would result in ActiveRecord::Base.configurations to look like this:
|
43
63
|
#
|
44
64
|
# #<ActiveRecord::DatabaseConfigurations:0x00007fd1acbdf800 @configurations=[
|
45
65
|
# #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10 @env_name="development",
|
46
|
-
# @name="primary", @config={adapter: "sqlite3", database: "
|
66
|
+
# @name="primary", @config={adapter: "sqlite3", database: "storage/development.sqlite3"}>,
|
47
67
|
# #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbdea90 @env_name="production",
|
48
|
-
# @name="primary", @config={adapter: "sqlite3", database: "
|
68
|
+
# @name="primary", @config={adapter: "sqlite3", database: "storage/production.sqlite3"}>
|
49
69
|
# ]>
|
50
70
|
def self.configurations=(config)
|
51
71
|
@@configurations = ActiveRecord::DatabaseConfigurations.new(config)
|
@@ -71,6 +91,8 @@ module ActiveRecord
|
|
71
91
|
|
72
92
|
class_attribute :has_many_inversing, instance_accessor: false, default: false
|
73
93
|
|
94
|
+
class_attribute :run_commit_callbacks_on_first_saved_instances_in_transaction, instance_accessor: false, default: true
|
95
|
+
|
74
96
|
class_attribute :default_connection_handler, instance_writer: false
|
75
97
|
|
76
98
|
class_attribute :default_role, instance_writer: false
|
@@ -99,33 +121,6 @@ module ActiveRecord
|
|
99
121
|
ActiveSupport::IsolatedExecutionState[:active_record_connection_handler] = handler
|
100
122
|
end
|
101
123
|
|
102
|
-
def self.connection_handlers
|
103
|
-
if ActiveRecord.legacy_connection_handling
|
104
|
-
else
|
105
|
-
raise NotImplementedError, "The new connection handling does not support accessing multiple connection handlers."
|
106
|
-
end
|
107
|
-
|
108
|
-
@@connection_handlers ||= {}
|
109
|
-
end
|
110
|
-
|
111
|
-
def self.connection_handlers=(handlers)
|
112
|
-
if ActiveRecord.legacy_connection_handling
|
113
|
-
ActiveSupport::Deprecation.warn(<<~MSG)
|
114
|
-
Using legacy connection handling is deprecated. Please set
|
115
|
-
`legacy_connection_handling` to `false` in your application.
|
116
|
-
|
117
|
-
The new connection handling does not support `connection_handlers`
|
118
|
-
getter and setter.
|
119
|
-
|
120
|
-
Read more about how to migrate at: https://guides.rubyonrails.org/active_record_multiple_databases.html#migrate-to-the-new-connection-handling
|
121
|
-
MSG
|
122
|
-
else
|
123
|
-
raise NotImplementedError, "The new connection handling does not support multiple connection handlers."
|
124
|
-
end
|
125
|
-
|
126
|
-
@@connection_handlers = handlers
|
127
|
-
end
|
128
|
-
|
129
124
|
def self.asynchronous_queries_session # :nodoc:
|
130
125
|
asynchronous_queries_tracker.current_session
|
131
126
|
end
|
@@ -145,16 +140,12 @@ module ActiveRecord
|
|
145
140
|
# ActiveRecord::Base.current_role #=> :reading
|
146
141
|
# end
|
147
142
|
def self.current_role
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
connected_to_stack.reverse_each do |hash|
|
152
|
-
return hash[:role] if hash[:role] && hash[:klasses].include?(Base)
|
153
|
-
return hash[:role] if hash[:role] && hash[:klasses].include?(connection_class_for_self)
|
154
|
-
end
|
155
|
-
|
156
|
-
default_role
|
143
|
+
connected_to_stack.reverse_each do |hash|
|
144
|
+
return hash[:role] if hash[:role] && hash[:klasses].include?(Base)
|
145
|
+
return hash[:role] if hash[:role] && hash[:klasses].include?(connection_class_for_self)
|
157
146
|
end
|
147
|
+
|
148
|
+
default_role
|
158
149
|
end
|
159
150
|
|
160
151
|
# Returns the symbol representing the current connected shard.
|
@@ -186,16 +177,12 @@ module ActiveRecord
|
|
186
177
|
# ActiveRecord::Base.current_preventing_writes #=> false
|
187
178
|
# end
|
188
179
|
def self.current_preventing_writes
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
connected_to_stack.reverse_each do |hash|
|
193
|
-
return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(Base)
|
194
|
-
return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(connection_class_for_self)
|
195
|
-
end
|
196
|
-
|
197
|
-
false
|
180
|
+
connected_to_stack.reverse_each do |hash|
|
181
|
+
return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(Base)
|
182
|
+
return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(connection_class_for_self)
|
198
183
|
end
|
184
|
+
|
185
|
+
false
|
199
186
|
end
|
200
187
|
|
201
188
|
def self.connected_to_stack # :nodoc:
|
@@ -252,19 +239,6 @@ module ActiveRecord
|
|
252
239
|
@find_by_statement_cache = { true => Concurrent::Map.new, false => Concurrent::Map.new }
|
253
240
|
end
|
254
241
|
|
255
|
-
def inherited(child_class) # :nodoc:
|
256
|
-
# initialize cache at class definition for thread safety
|
257
|
-
child_class.initialize_find_by_cache
|
258
|
-
unless child_class.base_class?
|
259
|
-
klass = self
|
260
|
-
until klass.base_class?
|
261
|
-
klass.initialize_find_by_cache
|
262
|
-
klass = klass.superclass
|
263
|
-
end
|
264
|
-
end
|
265
|
-
super
|
266
|
-
end
|
267
|
-
|
268
242
|
def find(*ids) # :nodoc:
|
269
243
|
# We don't have cache keys for this stuff yet
|
270
244
|
return super unless ids.length == 1
|
@@ -274,14 +248,8 @@ module ActiveRecord
|
|
274
248
|
|
275
249
|
return super if StatementCache.unsupported_value?(id)
|
276
250
|
|
277
|
-
|
278
|
-
|
279
|
-
statement = cached_find_by_statement(key) { |params|
|
280
|
-
where(key => params.bind).limit(1)
|
281
|
-
}
|
282
|
-
|
283
|
-
statement.execute([id], connection).first ||
|
284
|
-
raise(RecordNotFound.new("Couldn't find #{name} with '#{key}'=#{id}", name, key, id))
|
251
|
+
cached_find_by([primary_key], [id]) ||
|
252
|
+
raise(RecordNotFound.new("Couldn't find #{name} with '#{primary_key}'=#{id}", name, primary_key, id))
|
285
253
|
end
|
286
254
|
|
287
255
|
def find_by(*args) # :nodoc:
|
@@ -313,48 +281,13 @@ module ActiveRecord
|
|
313
281
|
h[key] = value
|
314
282
|
end
|
315
283
|
|
316
|
-
keys
|
317
|
-
statement = cached_find_by_statement(keys) { |params|
|
318
|
-
wheres = keys.index_with { params.bind }
|
319
|
-
where(wheres).limit(1)
|
320
|
-
}
|
321
|
-
|
322
|
-
begin
|
323
|
-
statement.execute(hash.values, connection).first
|
324
|
-
rescue TypeError
|
325
|
-
raise ActiveRecord::StatementInvalid
|
326
|
-
end
|
284
|
+
cached_find_by(hash.keys, hash.values)
|
327
285
|
end
|
328
286
|
|
329
287
|
def find_by!(*args) # :nodoc:
|
330
288
|
find_by(*args) || where(*args).raise_record_not_found_exception!
|
331
289
|
end
|
332
290
|
|
333
|
-
%w(
|
334
|
-
reading_role writing_role legacy_connection_handling default_timezone index_nested_attribute_errors
|
335
|
-
verbose_query_logs queues warn_on_records_fetched_greater_than maintain_test_schema
|
336
|
-
application_record_class action_on_strict_loading_violation schema_format error_on_ignored_order
|
337
|
-
timestamped_migrations dump_schema_after_migration dump_schemas suppress_multiple_database_warning
|
338
|
-
).each do |attr|
|
339
|
-
module_eval(<<~RUBY, __FILE__, __LINE__ + 1)
|
340
|
-
def #{attr}
|
341
|
-
ActiveSupport::Deprecation.warn(<<~MSG)
|
342
|
-
ActiveRecord::Base.#{attr} is deprecated and will be removed in Rails 7.1.
|
343
|
-
Use `ActiveRecord.#{attr}` instead.
|
344
|
-
MSG
|
345
|
-
ActiveRecord.#{attr}
|
346
|
-
end
|
347
|
-
|
348
|
-
def #{attr}=(value)
|
349
|
-
ActiveSupport::Deprecation.warn(<<~MSG)
|
350
|
-
ActiveRecord::Base.#{attr}= is deprecated and will be removed in Rails 7.1.
|
351
|
-
Use `ActiveRecord.#{attr}=` instead.
|
352
|
-
MSG
|
353
|
-
ActiveRecord.#{attr} = value
|
354
|
-
end
|
355
|
-
RUBY
|
356
|
-
end
|
357
|
-
|
358
291
|
def initialize_generated_modules # :nodoc:
|
359
292
|
generated_association_methods
|
360
293
|
end
|
@@ -371,10 +304,10 @@ module ActiveRecord
|
|
371
304
|
|
372
305
|
# Returns columns which shouldn't be exposed while calling +#inspect+.
|
373
306
|
def filter_attributes
|
374
|
-
if
|
375
|
-
@filter_attributes
|
376
|
-
else
|
307
|
+
if @filter_attributes.nil?
|
377
308
|
superclass.filter_attributes
|
309
|
+
else
|
310
|
+
@filter_attributes
|
378
311
|
end
|
379
312
|
end
|
380
313
|
|
@@ -385,13 +318,13 @@ module ActiveRecord
|
|
385
318
|
end
|
386
319
|
|
387
320
|
def inspection_filter # :nodoc:
|
388
|
-
if
|
321
|
+
if @filter_attributes.nil?
|
322
|
+
superclass.inspection_filter
|
323
|
+
else
|
389
324
|
@inspection_filter ||= begin
|
390
325
|
mask = InspectionMask.new(ActiveSupport::ParameterFilter::FILTERED)
|
391
326
|
ActiveSupport::ParameterFilter.new(@filter_attributes, mask: mask)
|
392
327
|
end
|
393
|
-
else
|
394
|
-
superclass.inspection_filter
|
395
328
|
end
|
396
329
|
end
|
397
330
|
|
@@ -416,7 +349,7 @@ module ActiveRecord
|
|
416
349
|
object.is_a?(self)
|
417
350
|
end
|
418
351
|
|
419
|
-
# Returns an instance of
|
352
|
+
# Returns an instance of +Arel::Table+ loaded with the current table name.
|
420
353
|
def arel_table # :nodoc:
|
421
354
|
@arel_table ||= Arel::Table.new(table_name, klass: self)
|
422
355
|
end
|
@@ -435,6 +368,28 @@ module ActiveRecord
|
|
435
368
|
end
|
436
369
|
|
437
370
|
private
|
371
|
+
def inherited(subclass)
|
372
|
+
super
|
373
|
+
|
374
|
+
# initialize cache at class definition for thread safety
|
375
|
+
subclass.initialize_find_by_cache
|
376
|
+
unless subclass.base_class?
|
377
|
+
klass = self
|
378
|
+
until klass.base_class?
|
379
|
+
klass.initialize_find_by_cache
|
380
|
+
klass = klass.superclass
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
subclass.class_eval do
|
385
|
+
@arel_table = nil
|
386
|
+
@predicate_builder = nil
|
387
|
+
@inspection_filter = nil
|
388
|
+
@filter_attributes = nil
|
389
|
+
@generated_association_methods = nil
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
438
393
|
def relation
|
439
394
|
relation = Relation.create(self)
|
440
395
|
|
@@ -448,6 +403,19 @@ module ActiveRecord
|
|
448
403
|
def table_metadata
|
449
404
|
TableMetadata.new(self, arel_table)
|
450
405
|
end
|
406
|
+
|
407
|
+
def cached_find_by(keys, values)
|
408
|
+
statement = cached_find_by_statement(keys) { |params|
|
409
|
+
wheres = keys.index_with { params.bind }
|
410
|
+
where(wheres).limit(1)
|
411
|
+
}
|
412
|
+
|
413
|
+
begin
|
414
|
+
statement.execute(values, connection).first
|
415
|
+
rescue TypeError
|
416
|
+
raise ActiveRecord::StatementInvalid
|
417
|
+
end
|
418
|
+
end
|
451
419
|
end
|
452
420
|
|
453
421
|
# New objects can be instantiated as either empty (pass no construction parameter) or pre-set with
|
@@ -455,7 +423,7 @@ module ActiveRecord
|
|
455
423
|
# In both instances, valid attribute keys are determined by the column names of the associated table --
|
456
424
|
# hence you can't have attributes that aren't part of the table columns.
|
457
425
|
#
|
458
|
-
# ==== Example
|
426
|
+
# ==== Example
|
459
427
|
# # Instantiates a single new object
|
460
428
|
# User.new(first_name: 'Jamie')
|
461
429
|
def initialize(attributes = nil)
|
@@ -533,12 +501,17 @@ module ActiveRecord
|
|
533
501
|
# only, not its associations. The extent of a "deep" copy is application
|
534
502
|
# specific and is therefore left to the application to implement according
|
535
503
|
# to its need.
|
536
|
-
# The dup method does not preserve the timestamps (created|updated)_(at|on)
|
504
|
+
# The dup method does not preserve the timestamps (created|updated)_(at|on)
|
505
|
+
# and locking column.
|
537
506
|
|
538
507
|
##
|
539
508
|
def initialize_dup(other) # :nodoc:
|
540
509
|
@attributes = @attributes.deep_dup
|
541
|
-
|
510
|
+
if self.class.composite_primary_key?
|
511
|
+
@primary_key.each { |key| @attributes.reset(key) }
|
512
|
+
else
|
513
|
+
@attributes.reset(@primary_key)
|
514
|
+
end
|
542
515
|
|
543
516
|
_run_initialize_callbacks
|
544
517
|
|
@@ -580,7 +553,7 @@ module ActiveRecord
|
|
580
553
|
def ==(comparison_object)
|
581
554
|
super ||
|
582
555
|
comparison_object.instance_of?(self.class) &&
|
583
|
-
|
556
|
+
primary_key_values_present? &&
|
584
557
|
comparison_object.id == id
|
585
558
|
end
|
586
559
|
alias :eql? :==
|
@@ -590,7 +563,7 @@ module ActiveRecord
|
|
590
563
|
def hash
|
591
564
|
id = self.id
|
592
565
|
|
593
|
-
if
|
566
|
+
if primary_key_values_present?
|
594
567
|
self.class.hash ^ id.hash
|
595
568
|
else
|
596
569
|
super
|
@@ -645,22 +618,27 @@ module ActiveRecord
|
|
645
618
|
# user.comments
|
646
619
|
# => ActiveRecord::StrictLoadingViolationError
|
647
620
|
#
|
648
|
-
#
|
621
|
+
# ==== Parameters
|
649
622
|
#
|
650
|
-
# * value - Boolean specifying whether to enable or disable strict loading.
|
651
|
-
# * mode - Symbol specifying strict loading mode. Defaults to :all. Using
|
652
|
-
#
|
653
|
-
#
|
623
|
+
# * +value+ - Boolean specifying whether to enable or disable strict loading.
|
624
|
+
# * <tt>:mode</tt> - Symbol specifying strict loading mode. Defaults to :all. Using
|
625
|
+
# :n_plus_one_only mode will only raise an error if an association that
|
626
|
+
# will lead to an n plus one query is lazily loaded.
|
654
627
|
#
|
655
|
-
#
|
628
|
+
# ==== Examples
|
656
629
|
#
|
657
630
|
# user = User.first
|
658
631
|
# user.strict_loading!(false) # => false
|
659
632
|
# user.comments
|
660
633
|
# => #<ActiveRecord::Associations::CollectionProxy>
|
634
|
+
#
|
635
|
+
# user.strict_loading!(mode: :n_plus_one_only)
|
636
|
+
# user.address.city # => "Tatooine"
|
637
|
+
# user.comments
|
638
|
+
# => ActiveRecord::StrictLoadingViolationError
|
661
639
|
def strict_loading!(value = true, mode: :all)
|
662
640
|
unless [:all, :n_plus_one_only].include?(mode)
|
663
|
-
raise ArgumentError, "The :mode option must be one of [:all, :n_plus_one_only]."
|
641
|
+
raise ArgumentError, "The :mode option must be one of [:all, :n_plus_one_only] but #{mode.inspect} was provided."
|
664
642
|
end
|
665
643
|
|
666
644
|
@strict_loading_mode = mode
|
@@ -688,7 +666,7 @@ module ActiveRecord
|
|
688
666
|
# We check defined?(@attributes) not to issue warnings if the object is
|
689
667
|
# allocated but not initialized.
|
690
668
|
inspection = if defined?(@attributes) && @attributes
|
691
|
-
|
669
|
+
attribute_names.filter_map do |name|
|
692
670
|
if _has_attribute?(name)
|
693
671
|
"#{name}: #{attribute_for_inspect(name)}"
|
694
672
|
end
|
@@ -725,15 +703,26 @@ module ActiveRecord
|
|
725
703
|
end
|
726
704
|
end
|
727
705
|
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
706
|
+
##
|
707
|
+
# :method: values_at
|
708
|
+
#
|
709
|
+
# :call-seq: values_at(*methods)
|
710
|
+
#
|
733
711
|
# Returns an array of the values returned by the given methods.
|
734
|
-
|
735
|
-
|
736
|
-
|
712
|
+
#
|
713
|
+
#--
|
714
|
+
# Implemented by ActiveModel::Access#values_at.
|
715
|
+
|
716
|
+
##
|
717
|
+
# :method: slice
|
718
|
+
#
|
719
|
+
# :call-seq: slice(*methods)
|
720
|
+
#
|
721
|
+
# Returns a hash of the given methods with their names as keys and returned
|
722
|
+
# values as values.
|
723
|
+
#
|
724
|
+
#--
|
725
|
+
# Implemented by ActiveModel::Access#slice.
|
737
726
|
|
738
727
|
private
|
739
728
|
# +Array#flatten+ will call +#to_ary+ (recursively) on each of the elements of
|
@@ -763,6 +752,7 @@ module ActiveRecord
|
|
763
752
|
@strict_loading_mode = :all
|
764
753
|
|
765
754
|
klass.define_attribute_methods
|
755
|
+
klass.generate_alias_attributes
|
766
756
|
end
|
767
757
|
|
768
758
|
def initialize_internals_callback
|
@@ -5,6 +5,10 @@ module ActiveRecord
|
|
5
5
|
module CounterCache
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
|
+
included do
|
9
|
+
class_attribute :_counter_cache_columns, instance_accessor: false, default: []
|
10
|
+
end
|
11
|
+
|
8
12
|
module ClassMethods
|
9
13
|
# Resets one or more counter caches to their correct value using an SQL
|
10
14
|
# count query. This is useful when adding new counter caches, or if the
|
@@ -29,6 +33,7 @@ module ActiveRecord
|
|
29
33
|
def reset_counters(id, *counters, touch: nil)
|
30
34
|
object = find(id)
|
31
35
|
|
36
|
+
updates = {}
|
32
37
|
counters.each do |counter_association|
|
33
38
|
has_many_association = _reflect_on_association(counter_association)
|
34
39
|
unless has_many_association
|
@@ -47,19 +52,21 @@ module ActiveRecord
|
|
47
52
|
reflection = child_class._reflections.values.find { |e| e.belongs_to? && e.foreign_key.to_s == foreign_key && e.options[:counter_cache].present? }
|
48
53
|
counter_name = reflection.counter_cache_column
|
49
54
|
|
50
|
-
|
51
|
-
|
52
|
-
if
|
53
|
-
|
54
|
-
names = Array.wrap(names)
|
55
|
-
options = names.extract_options!
|
56
|
-
touch_updates = touch_attributes_with_time(*names, **options)
|
57
|
-
updates.merge!(touch_updates)
|
58
|
-
end
|
55
|
+
count_was = object.send(counter_name)
|
56
|
+
count = object.send(counter_association).count(:all)
|
57
|
+
updates[counter_name] = count if count != count_was
|
58
|
+
end
|
59
59
|
|
60
|
-
|
60
|
+
if touch
|
61
|
+
names = touch if touch != true
|
62
|
+
names = Array.wrap(names)
|
63
|
+
options = names.extract_options!
|
64
|
+
touch_updates = touch_attributes_with_time(*names, **options)
|
65
|
+
updates.merge!(touch_updates)
|
61
66
|
end
|
62
67
|
|
68
|
+
unscoped.where(primary_key => object.id).update_all(updates) if updates.any?
|
69
|
+
|
63
70
|
true
|
64
71
|
end
|
65
72
|
|
@@ -80,28 +87,28 @@ module ActiveRecord
|
|
80
87
|
#
|
81
88
|
# ==== Examples
|
82
89
|
#
|
83
|
-
# # For the Post with id of 5, decrement the
|
84
|
-
# # increment the
|
85
|
-
# Post.update_counters 5,
|
90
|
+
# # For the Post with id of 5, decrement the comments_count by 1, and
|
91
|
+
# # increment the actions_count by 1
|
92
|
+
# Post.update_counters 5, comments_count: -1, actions_count: 1
|
86
93
|
# # Executes the following SQL:
|
87
94
|
# # UPDATE posts
|
88
|
-
# # SET
|
89
|
-
# #
|
95
|
+
# # SET comments_count = COALESCE(comments_count, 0) - 1,
|
96
|
+
# # actions_count = COALESCE(actions_count, 0) + 1
|
90
97
|
# # WHERE id = 5
|
91
98
|
#
|
92
|
-
# # For the Posts with id of 10 and 15, increment the
|
93
|
-
# Post.update_counters [10, 15],
|
99
|
+
# # For the Posts with id of 10 and 15, increment the comments_count by 1
|
100
|
+
# Post.update_counters [10, 15], comments_count: 1
|
94
101
|
# # Executes the following SQL:
|
95
102
|
# # UPDATE posts
|
96
|
-
# # SET
|
103
|
+
# # SET comments_count = COALESCE(comments_count, 0) + 1
|
97
104
|
# # WHERE id IN (10, 15)
|
98
105
|
#
|
99
|
-
# # For the Posts with id of 10 and 15, increment the
|
106
|
+
# # For the Posts with id of 10 and 15, increment the comments_count by 1
|
100
107
|
# # and update the updated_at value for each counter.
|
101
|
-
# Post.update_counters [10, 15],
|
108
|
+
# Post.update_counters [10, 15], comments_count: 1, touch: true
|
102
109
|
# # Executes the following SQL:
|
103
110
|
# # UPDATE posts
|
104
|
-
# # SET
|
111
|
+
# # SET comments_count = COALESCE(comments_count, 0) + 1,
|
105
112
|
# # `updated_at` = '2016-10-13T09:59:23-05:00'
|
106
113
|
# # WHERE id IN (10, 15)
|
107
114
|
def update_counters(id, counters)
|
@@ -119,6 +126,7 @@ module ActiveRecord
|
|
119
126
|
#
|
120
127
|
# * +counter_name+ - The name of the field that should be incremented.
|
121
128
|
# * +id+ - The id of the object that should be incremented or an array of ids.
|
129
|
+
# * <tt>:by</tt> - The amount by which to increment the value. Defaults to +1+.
|
122
130
|
# * <tt>:touch</tt> - Touch timestamp columns when updating.
|
123
131
|
# Pass +true+ to touch +updated_at+ and/or +updated_on+. Pass a symbol to
|
124
132
|
# touch that column or an array of symbols to touch just those ones.
|
@@ -129,10 +137,14 @@ module ActiveRecord
|
|
129
137
|
# DiscussionBoard.increment_counter(:posts_count, 5)
|
130
138
|
#
|
131
139
|
# # Increment the posts_count column for the record with an id of 5
|
140
|
+
# # by a specific amount.
|
141
|
+
# DiscussionBoard.increment_counter(:posts_count, 5, by: 3)
|
142
|
+
#
|
143
|
+
# # Increment the posts_count column for the record with an id of 5
|
132
144
|
# # and update the updated_at value.
|
133
145
|
# DiscussionBoard.increment_counter(:posts_count, 5, touch: true)
|
134
|
-
def increment_counter(counter_name, id, touch: nil)
|
135
|
-
update_counters(id, counter_name =>
|
146
|
+
def increment_counter(counter_name, id, by: 1, touch: nil)
|
147
|
+
update_counters(id, counter_name => by, touch: touch)
|
136
148
|
end
|
137
149
|
|
138
150
|
# Decrement a numeric field by one, via a direct SQL update.
|
@@ -144,6 +156,7 @@ module ActiveRecord
|
|
144
156
|
#
|
145
157
|
# * +counter_name+ - The name of the field that should be decremented.
|
146
158
|
# * +id+ - The id of the object that should be decremented or an array of ids.
|
159
|
+
# * <tt>:by</tt> - The amount by which to decrement the value. Defaults to +1+.
|
147
160
|
# * <tt>:touch</tt> - Touch timestamp columns when updating.
|
148
161
|
# Pass +true+ to touch +updated_at+ and/or +updated_on+. Pass a symbol to
|
149
162
|
# touch that column or an array of symbols to touch just those ones.
|
@@ -154,10 +167,18 @@ module ActiveRecord
|
|
154
167
|
# DiscussionBoard.decrement_counter(:posts_count, 5)
|
155
168
|
#
|
156
169
|
# # Decrement the posts_count column for the record with an id of 5
|
170
|
+
# by a specific amount.
|
171
|
+
# DiscussionBoard.decrement_counter(:posts_count, 5, by: 3)
|
172
|
+
#
|
173
|
+
# # Decrement the posts_count column for the record with an id of 5
|
157
174
|
# # and update the updated_at value.
|
158
175
|
# DiscussionBoard.decrement_counter(:posts_count, 5, touch: true)
|
159
|
-
def decrement_counter(counter_name, id, touch: nil)
|
160
|
-
update_counters(id, counter_name => -
|
176
|
+
def decrement_counter(counter_name, id, by: 1, touch: nil)
|
177
|
+
update_counters(id, counter_name => -by, touch: touch)
|
178
|
+
end
|
179
|
+
|
180
|
+
def counter_cache_column?(name) # :nodoc:
|
181
|
+
_counter_cache_columns.include?(name)
|
161
182
|
end
|
162
183
|
end
|
163
184
|
|
@@ -3,13 +3,11 @@
|
|
3
3
|
module ActiveRecord
|
4
4
|
class DatabaseConfigurations
|
5
5
|
# ActiveRecord::Base.configurations will return either a HashConfig or
|
6
|
-
# UrlConfig respectively. It will never return a DatabaseConfig object,
|
6
|
+
# UrlConfig respectively. It will never return a +DatabaseConfig+ object,
|
7
7
|
# as this is the parent class for the types of database configuration objects.
|
8
8
|
class DatabaseConfig # :nodoc:
|
9
9
|
attr_reader :env_name, :name
|
10
10
|
|
11
|
-
attr_accessor :owner_name
|
12
|
-
|
13
11
|
def initialize(env_name, name)
|
14
12
|
@env_name = env_name
|
15
13
|
@name = name
|
@@ -19,6 +17,10 @@ module ActiveRecord
|
|
19
17
|
"#{adapter}_connection"
|
20
18
|
end
|
21
19
|
|
20
|
+
def adapter_class_method
|
21
|
+
"#{adapter}_adapter_class"
|
22
|
+
end
|
23
|
+
|
22
24
|
def host
|
23
25
|
raise NotImplementedError
|
24
26
|
end
|
@@ -51,6 +53,10 @@ module ActiveRecord
|
|
51
53
|
raise NotImplementedError
|
52
54
|
end
|
53
55
|
|
56
|
+
def query_cache
|
57
|
+
raise NotImplementedError
|
58
|
+
end
|
59
|
+
|
54
60
|
def checkout_timeout
|
55
61
|
raise NotImplementedError
|
56
62
|
end
|