activerecord 6.0.6.1 → 6.1.7.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1146 -788
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -2
- data/lib/active_record/aggregations.rb +5 -5
- data/lib/active_record/association_relation.rb +30 -12
- data/lib/active_record/associations/alias_tracker.rb +19 -15
- data/lib/active_record/associations/association.rb +49 -26
- data/lib/active_record/associations/association_scope.rb +18 -20
- data/lib/active_record/associations/belongs_to_association.rb +23 -10
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -3
- data/lib/active_record/associations/builder/association.rb +32 -5
- data/lib/active_record/associations/builder/belongs_to.rb +10 -7
- data/lib/active_record/associations/builder/collection_association.rb +5 -4
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +0 -1
- data/lib/active_record/associations/builder/has_many.rb +6 -2
- data/lib/active_record/associations/builder/has_one.rb +11 -14
- data/lib/active_record/associations/builder/singular_association.rb +1 -1
- data/lib/active_record/associations/collection_association.rb +32 -18
- data/lib/active_record/associations/collection_proxy.rb +12 -5
- data/lib/active_record/associations/foreign_association.rb +13 -0
- data/lib/active_record/associations/has_many_association.rb +24 -2
- data/lib/active_record/associations/has_many_through_association.rb +10 -4
- data/lib/active_record/associations/has_one_association.rb +15 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +37 -21
- data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
- data/lib/active_record/associations/join_dependency.rb +63 -49
- data/lib/active_record/associations/preloader/association.rb +14 -8
- data/lib/active_record/associations/preloader/through_association.rb +1 -1
- data/lib/active_record/associations/preloader.rb +5 -3
- data/lib/active_record/associations/singular_association.rb +1 -1
- data/lib/active_record/associations.rb +118 -11
- data/lib/active_record/attribute_assignment.rb +10 -8
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -9
- data/lib/active_record/attribute_methods/dirty.rb +1 -11
- data/lib/active_record/attribute_methods/primary_key.rb +6 -2
- data/lib/active_record/attribute_methods/query.rb +3 -6
- data/lib/active_record/attribute_methods/read.rb +8 -11
- data/lib/active_record/attribute_methods/serialization.rb +11 -5
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -13
- data/lib/active_record/attribute_methods/write.rb +12 -20
- data/lib/active_record/attribute_methods.rb +64 -54
- data/lib/active_record/attributes.rb +33 -8
- data/lib/active_record/autosave_association.rb +47 -30
- data/lib/active_record/base.rb +2 -14
- data/lib/active_record/callbacks.rb +152 -22
- data/lib/active_record/coders/yaml_column.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +185 -134
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +66 -23
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +3 -8
- data/lib/active_record/connection_adapters/abstract/quoting.rb +34 -34
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -116
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +114 -26
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +228 -83
- data/lib/active_record/connection_adapters/abstract/transaction.rb +92 -33
- data/lib/active_record/connection_adapters/abstract_adapter.rb +52 -76
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +123 -87
- data/lib/active_record/connection_adapters/column.rb +15 -1
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +24 -24
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/quoting.rb +18 -3
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +32 -6
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +5 -2
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +7 -4
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -12
- data/lib/active_record/connection_adapters/pool_config.rb +73 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +24 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +14 -53
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -1
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +30 -4
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +61 -29
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +75 -64
- data/lib/active_record/connection_adapters/schema_cache.rb +130 -15
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +32 -5
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +36 -3
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +48 -50
- data/lib/active_record/connection_adapters.rb +52 -0
- data/lib/active_record/connection_handling.rb +218 -71
- data/lib/active_record/core.rb +264 -63
- data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -0
- data/lib/active_record/database_configurations/database_config.rb +52 -9
- data/lib/active_record/database_configurations/hash_config.rb +54 -8
- data/lib/active_record/database_configurations/url_config.rb +15 -40
- data/lib/active_record/database_configurations.rb +125 -85
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/enum.rb +69 -34
- data/lib/active_record/errors.rb +47 -12
- data/lib/active_record/explain.rb +9 -4
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +10 -17
- data/lib/active_record/fixture_set/model_metadata.rb +1 -2
- data/lib/active_record/fixture_set/render_context.rb +1 -1
- data/lib/active_record/fixture_set/table_row.rb +2 -2
- data/lib/active_record/fixtures.rb +58 -9
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +40 -18
- data/lib/active_record/insert_all.rb +38 -5
- data/lib/active_record/integration.rb +3 -5
- data/lib/active_record/internal_metadata.rb +18 -7
- data/lib/active_record/legacy_yaml_adapter.rb +7 -3
- data/lib/active_record/locking/optimistic.rb +24 -17
- data/lib/active_record/locking/pessimistic.rb +6 -2
- data/lib/active_record/log_subscriber.rb +27 -8
- data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +5 -0
- data/lib/active_record/middleware/database_selector.rb +4 -1
- data/lib/active_record/migration/command_recorder.rb +47 -27
- data/lib/active_record/migration/compatibility.rb +72 -18
- data/lib/active_record/migration.rb +114 -84
- data/lib/active_record/model_schema.rb +89 -14
- data/lib/active_record/nested_attributes.rb +2 -3
- data/lib/active_record/no_touching.rb +1 -1
- data/lib/active_record/persistence.rb +50 -45
- data/lib/active_record/query_cache.rb +15 -5
- data/lib/active_record/querying.rb +11 -6
- data/lib/active_record/railtie.rb +64 -44
- data/lib/active_record/railties/console_sandbox.rb +2 -4
- data/lib/active_record/railties/databases.rake +279 -101
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +60 -44
- data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
- data/lib/active_record/relation/batches.rb +38 -31
- data/lib/active_record/relation/calculations.rb +104 -43
- data/lib/active_record/relation/finder_methods.rb +44 -14
- data/lib/active_record/relation/from_clause.rb +1 -1
- data/lib/active_record/relation/merger.rb +20 -23
- data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +4 -5
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -6
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +61 -38
- data/lib/active_record/relation/query_methods.rb +322 -196
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +8 -7
- data/lib/active_record/relation/where_clause.rb +111 -61
- data/lib/active_record/relation.rb +100 -81
- data/lib/active_record/result.rb +41 -33
- data/lib/active_record/runtime_registry.rb +2 -2
- data/lib/active_record/sanitization.rb +6 -17
- data/lib/active_record/schema_dumper.rb +34 -4
- data/lib/active_record/schema_migration.rb +2 -8
- data/lib/active_record/scoping/default.rb +1 -3
- data/lib/active_record/scoping/named.rb +1 -17
- data/lib/active_record/secure_token.rb +16 -8
- data/lib/active_record/serialization.rb +5 -3
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +20 -4
- data/lib/active_record/store.rb +8 -3
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +42 -51
- data/lib/active_record/tasks/database_tasks.rb +140 -113
- data/lib/active_record/tasks/mysql_database_tasks.rb +34 -35
- data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -26
- data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -9
- data/lib/active_record/test_databases.rb +5 -4
- data/lib/active_record/test_fixtures.rb +79 -31
- data/lib/active_record/timestamp.rb +4 -6
- data/lib/active_record/touch_later.rb +21 -21
- data/lib/active_record/transactions.rb +19 -66
- data/lib/active_record/type/serialized.rb +6 -2
- data/lib/active_record/type.rb +8 -1
- data/lib/active_record/type_caster/connection.rb +0 -1
- data/lib/active_record/type_caster/map.rb +8 -5
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +24 -4
- data/lib/active_record/validations.rb +1 -0
- data/lib/active_record.rb +7 -14
- data/lib/arel/attributes/attribute.rb +4 -0
- data/lib/arel/collectors/bind.rb +5 -0
- data/lib/arel/collectors/composite.rb +8 -0
- data/lib/arel/collectors/sql_string.rb +7 -0
- data/lib/arel/collectors/substitute_binds.rb +7 -0
- data/lib/arel/nodes/binary.rb +82 -8
- data/lib/arel/nodes/bind_param.rb +8 -0
- data/lib/arel/nodes/casted.rb +21 -9
- data/lib/arel/nodes/equality.rb +6 -9
- data/lib/arel/nodes/grouping.rb +3 -0
- data/lib/arel/nodes/homogeneous_in.rb +76 -0
- data/lib/arel/nodes/in.rb +8 -1
- data/lib/arel/nodes/infix_operation.rb +13 -1
- data/lib/arel/nodes/join_source.rb +1 -1
- data/lib/arel/nodes/node.rb +7 -6
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/sql_literal.rb +3 -0
- data/lib/arel/nodes/table_alias.rb +7 -3
- data/lib/arel/nodes/unary.rb +0 -1
- data/lib/arel/nodes.rb +3 -1
- data/lib/arel/predications.rb +12 -18
- data/lib/arel/select_manager.rb +1 -2
- data/lib/arel/table.rb +13 -5
- data/lib/arel/visitors/dot.rb +14 -2
- data/lib/arel/visitors/mysql.rb +11 -1
- data/lib/arel/visitors/postgresql.rb +15 -4
- data/lib/arel/visitors/to_sql.rb +89 -78
- data/lib/arel/visitors.rb +0 -7
- data/lib/arel.rb +5 -13
- data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +3 -3
- data/lib/rails/generators/active_record/migration.rb +6 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- metadata +24 -25
- data/lib/active_record/advisory_lock_base.rb +0 -18
- data/lib/active_record/attribute_decorators.rb +0 -88
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -296
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
- data/lib/active_record/relation/where_clause_factory.rb +0 -33
- data/lib/arel/attributes.rb +0 -22
- data/lib/arel/visitors/depth_first.rb +0 -203
- data/lib/arel/visitors/ibm_db.rb +0 -34
- data/lib/arel/visitors/informix.rb +0 -62
- data/lib/arel/visitors/mssql.rb +0 -156
- data/lib/arel/visitors/oracle.rb +0 -158
- data/lib/arel/visitors/oracle12.rb +0 -65
- data/lib/arel/visitors/where_sql.rb +0 -22
data/lib/active_record/core.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/core_ext/enumerable"
|
3
4
|
require "active_support/core_ext/hash/indifferent_access"
|
4
5
|
require "active_support/core_ext/string/filters"
|
5
6
|
require "active_support/parameter_filter"
|
@@ -25,6 +26,18 @@ module ActiveRecord
|
|
25
26
|
# their relevant queries. Defaults to false.
|
26
27
|
mattr_accessor :verbose_query_logs, instance_writer: false, default: false
|
27
28
|
|
29
|
+
##
|
30
|
+
# :singleton-method:
|
31
|
+
#
|
32
|
+
# Specifies the names of the queues used by background jobs.
|
33
|
+
mattr_accessor :queues, instance_accessor: false, default: {}
|
34
|
+
|
35
|
+
##
|
36
|
+
# :singleton-method:
|
37
|
+
#
|
38
|
+
# Specifies the job used to destroy associations in the background
|
39
|
+
class_attribute :destroy_association_async_job, instance_writer: false, instance_predicate: false, default: false
|
40
|
+
|
28
41
|
##
|
29
42
|
# Contains the database configuration - as is typically stored in config/database.yml -
|
30
43
|
# as an ActiveRecord::DatabaseConfigurations object.
|
@@ -43,9 +56,9 @@ module ActiveRecord
|
|
43
56
|
#
|
44
57
|
# #<ActiveRecord::DatabaseConfigurations:0x00007fd1acbdf800 @configurations=[
|
45
58
|
# #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10 @env_name="development",
|
46
|
-
# @
|
59
|
+
# @name="primary", @config={adapter: "sqlite3", database: "db/development.sqlite3"}>,
|
47
60
|
# #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbdea90 @env_name="production",
|
48
|
-
# @
|
61
|
+
# @name="primary", @config={adapter: "sqlite3", database: "db/production.sqlite3"}>
|
49
62
|
# ]>
|
50
63
|
def self.configurations=(config)
|
51
64
|
@@configurations = ActiveRecord::DatabaseConfigurations.new(config)
|
@@ -80,14 +93,6 @@ module ActiveRecord
|
|
80
93
|
# scope being ignored is error-worthy, rather than a warning.
|
81
94
|
mattr_accessor :error_on_ignored_order, instance_writer: false, default: false
|
82
95
|
|
83
|
-
# :singleton-method:
|
84
|
-
# Specify the behavior for unsafe raw query methods. Values are as follows
|
85
|
-
# deprecated - Warnings are logged when unsafe raw SQL is passed to
|
86
|
-
# query methods.
|
87
|
-
# disabled - Unsafe raw SQL passed to query methods results in
|
88
|
-
# UnknownAttributeReference exception.
|
89
|
-
mattr_accessor :allow_unsafe_raw_sql, instance_writer: false, default: :deprecated
|
90
|
-
|
91
96
|
##
|
92
97
|
# :singleton-method:
|
93
98
|
# Specify whether or not to use timestamps for migration versions
|
@@ -103,7 +108,7 @@ module ActiveRecord
|
|
103
108
|
|
104
109
|
##
|
105
110
|
# :singleton-method:
|
106
|
-
# Specifies which database schemas to dump when calling db:
|
111
|
+
# Specifies which database schemas to dump when calling db:schema:dump.
|
107
112
|
# If the value is :schema_search_path (the default), any schemas listed in
|
108
113
|
# schema_search_path are dumped. Use :all to dump all schemas regardless
|
109
114
|
# of schema_search_path, or a string of comma separated schemas for a
|
@@ -118,18 +123,38 @@ module ActiveRecord
|
|
118
123
|
# potentially cause memory bloat.
|
119
124
|
mattr_accessor :warn_on_records_fetched_greater_than, instance_writer: false
|
120
125
|
|
126
|
+
##
|
127
|
+
# :singleton-method:
|
128
|
+
# Show a warning when Rails couldn't parse your database.yml
|
129
|
+
# for multiple databases.
|
130
|
+
mattr_accessor :suppress_multiple_database_warning, instance_writer: false, default: false
|
131
|
+
|
121
132
|
mattr_accessor :maintain_test_schema, instance_accessor: false
|
122
133
|
|
123
|
-
|
134
|
+
class_attribute :belongs_to_required_by_default, instance_accessor: false
|
124
135
|
|
125
|
-
|
136
|
+
##
|
137
|
+
# :singleton-method:
|
138
|
+
# Set the application to log or raise when an association violates strict loading.
|
139
|
+
# Defaults to :raise.
|
140
|
+
mattr_accessor :action_on_strict_loading_violation, instance_accessor: false, default: :raise
|
141
|
+
|
142
|
+
class_attribute :strict_loading_by_default, instance_accessor: false, default: false
|
126
143
|
|
127
144
|
mattr_accessor :writing_role, instance_accessor: false, default: :writing
|
128
145
|
|
129
146
|
mattr_accessor :reading_role, instance_accessor: false, default: :reading
|
130
147
|
|
131
|
-
|
132
|
-
|
148
|
+
mattr_accessor :has_many_inversing, instance_accessor: false, default: false
|
149
|
+
|
150
|
+
class_attribute :default_connection_handler, instance_writer: false
|
151
|
+
|
152
|
+
class_attribute :default_role, instance_writer: false
|
153
|
+
|
154
|
+
class_attribute :default_shard, instance_writer: false
|
155
|
+
|
156
|
+
mattr_accessor :legacy_connection_handling, instance_writer: false, default: true
|
157
|
+
|
133
158
|
# Application configurable boolean that instructs the YAML Coder to use
|
134
159
|
# an unsafe load if set to true.
|
135
160
|
mattr_accessor :use_yaml_unsafe_load, instance_writer: false, default: false
|
@@ -138,19 +163,157 @@ module ActiveRecord
|
|
138
163
|
# to Psych safe_load in the YAML Coder
|
139
164
|
mattr_accessor :yaml_column_permitted_classes, instance_writer: false, default: [Symbol]
|
140
165
|
|
141
|
-
|
166
|
+
##
|
167
|
+
# :singleton-method:
|
168
|
+
# Application configurable boolean that denotes whether or not to raise
|
169
|
+
# an exception when the PostgreSQLAdapter is provided with an integer that is
|
170
|
+
# wider than signed 64bit representation
|
171
|
+
mattr_accessor :raise_int_wider_than_64bit, instance_writer: false, default: true
|
142
172
|
|
143
173
|
self.filter_attributes = []
|
144
174
|
|
145
175
|
def self.connection_handler
|
146
|
-
Thread.current.thread_variable_get(
|
176
|
+
Thread.current.thread_variable_get(:ar_connection_handler) || default_connection_handler
|
147
177
|
end
|
148
178
|
|
149
179
|
def self.connection_handler=(handler)
|
150
|
-
Thread.current.thread_variable_set(
|
180
|
+
Thread.current.thread_variable_set(:ar_connection_handler, handler)
|
181
|
+
end
|
182
|
+
|
183
|
+
def self.connection_handlers
|
184
|
+
unless legacy_connection_handling
|
185
|
+
raise NotImplementedError, "The new connection handling does not support accessing multiple connection handlers."
|
186
|
+
end
|
187
|
+
|
188
|
+
@@connection_handlers ||= {}
|
189
|
+
end
|
190
|
+
|
191
|
+
def self.connection_handlers=(handlers)
|
192
|
+
unless legacy_connection_handling
|
193
|
+
raise NotImplementedError, "The new connection handling does not setting support multiple connection handlers."
|
194
|
+
end
|
195
|
+
|
196
|
+
@@connection_handlers = handlers
|
197
|
+
end
|
198
|
+
|
199
|
+
# Returns the symbol representing the current connected role.
|
200
|
+
#
|
201
|
+
# ActiveRecord::Base.connected_to(role: :writing) do
|
202
|
+
# ActiveRecord::Base.current_role #=> :writing
|
203
|
+
# end
|
204
|
+
#
|
205
|
+
# ActiveRecord::Base.connected_to(role: :reading) do
|
206
|
+
# ActiveRecord::Base.current_role #=> :reading
|
207
|
+
# end
|
208
|
+
def self.current_role
|
209
|
+
if ActiveRecord::Base.legacy_connection_handling
|
210
|
+
connection_handlers.key(connection_handler) || default_role
|
211
|
+
else
|
212
|
+
connected_to_stack.reverse_each do |hash|
|
213
|
+
return hash[:role] if hash[:role] && hash[:klasses].include?(Base)
|
214
|
+
return hash[:role] if hash[:role] && hash[:klasses].include?(connection_classes)
|
215
|
+
end
|
216
|
+
|
217
|
+
default_role
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
# Returns the symbol representing the current connected shard.
|
222
|
+
#
|
223
|
+
# ActiveRecord::Base.connected_to(role: :reading) do
|
224
|
+
# ActiveRecord::Base.current_shard #=> :default
|
225
|
+
# end
|
226
|
+
#
|
227
|
+
# ActiveRecord::Base.connected_to(role: :writing, shard: :one) do
|
228
|
+
# ActiveRecord::Base.current_shard #=> :one
|
229
|
+
# end
|
230
|
+
def self.current_shard
|
231
|
+
connected_to_stack.reverse_each do |hash|
|
232
|
+
return hash[:shard] if hash[:shard] && hash[:klasses].include?(Base)
|
233
|
+
return hash[:shard] if hash[:shard] && hash[:klasses].include?(connection_classes)
|
234
|
+
end
|
235
|
+
|
236
|
+
default_shard
|
237
|
+
end
|
238
|
+
|
239
|
+
# Returns the symbol representing the current setting for
|
240
|
+
# preventing writes.
|
241
|
+
#
|
242
|
+
# ActiveRecord::Base.connected_to(role: :reading) do
|
243
|
+
# ActiveRecord::Base.current_preventing_writes #=> true
|
244
|
+
# end
|
245
|
+
#
|
246
|
+
# ActiveRecord::Base.connected_to(role: :writing) do
|
247
|
+
# ActiveRecord::Base.current_preventing_writes #=> false
|
248
|
+
# end
|
249
|
+
def self.current_preventing_writes
|
250
|
+
if legacy_connection_handling
|
251
|
+
connection_handler.prevent_writes
|
252
|
+
else
|
253
|
+
connected_to_stack.reverse_each do |hash|
|
254
|
+
return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(Base)
|
255
|
+
return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(connection_classes)
|
256
|
+
end
|
257
|
+
|
258
|
+
false
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
def self.connected_to_stack # :nodoc:
|
263
|
+
if connected_to_stack = Thread.current.thread_variable_get(:ar_connected_to_stack)
|
264
|
+
connected_to_stack
|
265
|
+
else
|
266
|
+
connected_to_stack = Concurrent::Array.new
|
267
|
+
Thread.current.thread_variable_set(:ar_connected_to_stack, connected_to_stack)
|
268
|
+
connected_to_stack
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
def self.connection_class=(b) # :nodoc:
|
273
|
+
@connection_class = b
|
274
|
+
end
|
275
|
+
|
276
|
+
def self.connection_class # :nodoc
|
277
|
+
@connection_class ||= false
|
278
|
+
end
|
279
|
+
|
280
|
+
def self.connection_class? # :nodoc:
|
281
|
+
self.connection_class
|
282
|
+
end
|
283
|
+
|
284
|
+
def self.connection_classes # :nodoc:
|
285
|
+
klass = self
|
286
|
+
|
287
|
+
until klass == Base
|
288
|
+
break if klass.connection_class?
|
289
|
+
klass = klass.superclass
|
290
|
+
end
|
291
|
+
|
292
|
+
klass
|
293
|
+
end
|
294
|
+
|
295
|
+
def self.allow_unsafe_raw_sql # :nodoc:
|
296
|
+
ActiveSupport::Deprecation.warn("ActiveRecord::Base.allow_unsafe_raw_sql is deprecated and will be removed in Rails 7.0")
|
297
|
+
end
|
298
|
+
|
299
|
+
def self.allow_unsafe_raw_sql=(value) # :nodoc:
|
300
|
+
ActiveSupport::Deprecation.warn("ActiveRecord::Base.allow_unsafe_raw_sql= is deprecated and will be removed in Rails 7.0")
|
151
301
|
end
|
152
302
|
|
153
303
|
self.default_connection_handler = ConnectionAdapters::ConnectionHandler.new
|
304
|
+
self.default_role = writing_role
|
305
|
+
self.default_shard = :default
|
306
|
+
|
307
|
+
def self.strict_loading_violation!(owner:, reflection:) # :nodoc:
|
308
|
+
case action_on_strict_loading_violation
|
309
|
+
when :raise
|
310
|
+
message = "`#{owner}` is marked for strict_loading. The `#{reflection.klass}` association named `:#{reflection.name}` cannot be lazily loaded."
|
311
|
+
raise ActiveRecord::StrictLoadingViolationError.new(message)
|
312
|
+
when :log
|
313
|
+
name = "strict_loading_violation.active_record"
|
314
|
+
ActiveSupport::Notifications.instrument(name, owner: owner, reflection: reflection)
|
315
|
+
end
|
316
|
+
end
|
154
317
|
end
|
155
318
|
|
156
319
|
module ClassMethods
|
@@ -161,16 +324,20 @@ module ActiveRecord
|
|
161
324
|
def inherited(child_class) # :nodoc:
|
162
325
|
# initialize cache at class definition for thread safety
|
163
326
|
child_class.initialize_find_by_cache
|
327
|
+
unless child_class.base_class?
|
328
|
+
klass = self
|
329
|
+
until klass.base_class?
|
330
|
+
klass.initialize_find_by_cache
|
331
|
+
klass = klass.superclass
|
332
|
+
end
|
333
|
+
end
|
164
334
|
super
|
165
335
|
end
|
166
336
|
|
167
337
|
def find(*ids) # :nodoc:
|
168
338
|
# We don't have cache keys for this stuff yet
|
169
339
|
return super unless ids.length == 1
|
170
|
-
return super if block_given? ||
|
171
|
-
primary_key.nil? ||
|
172
|
-
scope_attributes? ||
|
173
|
-
columns_hash.key?(inheritance_column) && !base_class?
|
340
|
+
return super if block_given? || primary_key.nil? || scope_attributes?
|
174
341
|
|
175
342
|
id = ids.first
|
176
343
|
|
@@ -182,36 +349,47 @@ module ActiveRecord
|
|
182
349
|
where(key => params.bind).limit(1)
|
183
350
|
}
|
184
351
|
|
185
|
-
|
186
|
-
|
187
|
-
raise RecordNotFound.new("Couldn't find #{name} with '#{key}'=#{id}", name, key, id)
|
188
|
-
end
|
189
|
-
record
|
352
|
+
statement.execute([id], connection).first ||
|
353
|
+
raise(RecordNotFound.new("Couldn't find #{name} with '#{key}'=#{id}", name, key, id))
|
190
354
|
end
|
191
355
|
|
192
356
|
def find_by(*args) # :nodoc:
|
193
|
-
return super if scope_attributes?
|
194
|
-
columns_hash.key?(inheritance_column) && !base_class?
|
357
|
+
return super if scope_attributes?
|
195
358
|
|
196
359
|
hash = args.first
|
360
|
+
return super unless Hash === hash
|
197
361
|
|
198
|
-
|
199
|
-
|
200
|
-
|
362
|
+
hash = hash.each_with_object({}) do |(key, value), h|
|
363
|
+
key = key.to_s
|
364
|
+
key = attribute_aliases[key] || key
|
201
365
|
|
202
|
-
|
203
|
-
return super unless hash.keys.all? { |k| columns_hash.has_key?(k.to_s) }
|
366
|
+
return super if reflect_on_aggregation(key)
|
204
367
|
|
205
|
-
|
368
|
+
reflection = _reflect_on_association(key)
|
369
|
+
|
370
|
+
if !reflection
|
371
|
+
value = value.id if value.respond_to?(:id)
|
372
|
+
elsif reflection.belongs_to? && !reflection.polymorphic?
|
373
|
+
key = reflection.join_foreign_key
|
374
|
+
pkey = reflection.join_primary_key
|
375
|
+
value = value.public_send(pkey) if value.respond_to?(pkey)
|
376
|
+
end
|
377
|
+
|
378
|
+
if !columns_hash.key?(key) || StatementCache.unsupported_value?(value)
|
379
|
+
return super
|
380
|
+
end
|
206
381
|
|
382
|
+
h[key] = value
|
383
|
+
end
|
384
|
+
|
385
|
+
keys = hash.keys
|
207
386
|
statement = cached_find_by_statement(keys) { |params|
|
208
|
-
wheres = keys.
|
209
|
-
o[param] = params.bind
|
210
|
-
}
|
387
|
+
wheres = keys.index_with { params.bind }
|
211
388
|
where(wheres).limit(1)
|
212
389
|
}
|
390
|
+
|
213
391
|
begin
|
214
|
-
statement.execute(hash.values, connection)
|
392
|
+
statement.execute(hash.values, connection).first
|
215
393
|
rescue TypeError
|
216
394
|
raise ActiveRecord::StatementInvalid
|
217
395
|
end
|
@@ -245,7 +423,21 @@ module ActiveRecord
|
|
245
423
|
end
|
246
424
|
|
247
425
|
# Specifies columns which shouldn't be exposed while calling +#inspect+.
|
248
|
-
|
426
|
+
def filter_attributes=(filter_attributes)
|
427
|
+
@inspection_filter = nil
|
428
|
+
@filter_attributes = filter_attributes
|
429
|
+
end
|
430
|
+
|
431
|
+
def inspection_filter # :nodoc:
|
432
|
+
if defined?(@filter_attributes)
|
433
|
+
@inspection_filter ||= begin
|
434
|
+
mask = InspectionMask.new(ActiveSupport::ParameterFilter::FILTERED)
|
435
|
+
ActiveSupport::ParameterFilter.new(@filter_attributes, mask: mask)
|
436
|
+
end
|
437
|
+
else
|
438
|
+
superclass.inspection_filter
|
439
|
+
end
|
440
|
+
end
|
249
441
|
|
250
442
|
# Returns a string like 'Post(id:integer, title:string, body:text)'
|
251
443
|
def inspect # :nodoc:
|
@@ -274,14 +466,13 @@ module ActiveRecord
|
|
274
466
|
# scope :published_and_commented, -> { published.and(arel_table[:comments_count].gt(0)) }
|
275
467
|
# end
|
276
468
|
def arel_table # :nodoc:
|
277
|
-
@arel_table ||= Arel::Table.new(table_name,
|
469
|
+
@arel_table ||= Arel::Table.new(table_name, klass: self)
|
278
470
|
end
|
279
471
|
|
280
472
|
def arel_attribute(name, table = arel_table) # :nodoc:
|
281
|
-
name = name.to_s
|
282
|
-
name = attribute_aliases[name] || name
|
283
473
|
table[name]
|
284
474
|
end
|
475
|
+
deprecate :arel_attribute
|
285
476
|
|
286
477
|
def predicate_builder # :nodoc:
|
287
478
|
@predicate_builder ||= PredicateBuilder.new(table_metadata)
|
@@ -409,9 +600,9 @@ module ActiveRecord
|
|
409
600
|
_run_initialize_callbacks
|
410
601
|
|
411
602
|
@new_record = true
|
603
|
+
@previously_new_record = false
|
412
604
|
@destroyed = false
|
413
605
|
@_start_transaction_state = nil
|
414
|
-
@transaction_state = nil
|
415
606
|
|
416
607
|
super
|
417
608
|
end
|
@@ -471,7 +662,6 @@ module ActiveRecord
|
|
471
662
|
|
472
663
|
# Returns +true+ if the attributes hash has been frozen.
|
473
664
|
def frozen?
|
474
|
-
sync_with_transaction_state if @transaction_state&.finalized?
|
475
665
|
@attributes.frozen?
|
476
666
|
end
|
477
667
|
|
@@ -492,12 +682,27 @@ module ActiveRecord
|
|
492
682
|
false
|
493
683
|
end
|
494
684
|
|
495
|
-
# Returns +true+ if the record is read only.
|
496
|
-
# attributes will be marked as read only since they cannot be saved.
|
685
|
+
# Returns +true+ if the record is read only.
|
497
686
|
def readonly?
|
498
687
|
@readonly
|
499
688
|
end
|
500
689
|
|
690
|
+
# Returns +true+ if the record is in strict_loading mode.
|
691
|
+
def strict_loading?
|
692
|
+
@strict_loading
|
693
|
+
end
|
694
|
+
|
695
|
+
# Sets the record to strict_loading mode. This will raise an error
|
696
|
+
# if the record tries to lazily load an association.
|
697
|
+
#
|
698
|
+
# user = User.first
|
699
|
+
# user.strict_loading!
|
700
|
+
# user.comments.to_a
|
701
|
+
# => ActiveRecord::StrictLoadingViolationError
|
702
|
+
def strict_loading!
|
703
|
+
@strict_loading = true
|
704
|
+
end
|
705
|
+
|
501
706
|
# Marks this record as read only.
|
502
707
|
def readonly!
|
503
708
|
@readonly = true
|
@@ -513,15 +718,8 @@ module ActiveRecord
|
|
513
718
|
# allocated but not initialized.
|
514
719
|
inspection = if defined?(@attributes) && @attributes
|
515
720
|
self.class.attribute_names.collect do |name|
|
516
|
-
if
|
517
|
-
|
518
|
-
value = if attr.nil?
|
519
|
-
attr.inspect
|
520
|
-
else
|
521
|
-
attr = format_for_inspect(attr)
|
522
|
-
inspection_filter.filter_param(name, attr)
|
523
|
-
end
|
524
|
-
"#{name}: #{value}"
|
721
|
+
if _has_attribute?(name)
|
722
|
+
"#{name}: #{attribute_for_inspect(name)}"
|
525
723
|
end
|
526
724
|
end.compact.join(", ")
|
527
725
|
else
|
@@ -537,7 +735,7 @@ module ActiveRecord
|
|
537
735
|
return super if custom_inspect_method_defined?
|
538
736
|
pp.object_address_group(self) do
|
539
737
|
if defined?(@attributes) && @attributes
|
540
|
-
attr_names = self.class.attribute_names.select { |name|
|
738
|
+
attr_names = self.class.attribute_names.select { |name| _has_attribute?(name) }
|
541
739
|
pp.seplist(attr_names, proc { pp.text "," }) do |attr_name|
|
542
740
|
pp.breakable " "
|
543
741
|
pp.group(1) do
|
@@ -558,7 +756,12 @@ module ActiveRecord
|
|
558
756
|
|
559
757
|
# Returns a hash of the given methods with their names as keys and returned values as values.
|
560
758
|
def slice(*methods)
|
561
|
-
|
759
|
+
methods.flatten.index_with { |method| public_send(method) }.with_indifferent_access
|
760
|
+
end
|
761
|
+
|
762
|
+
# Returns an array of the values returned by the given methods.
|
763
|
+
def values_at(*methods)
|
764
|
+
methods.flatten.map! { |method| public_send(method) }
|
562
765
|
end
|
563
766
|
|
564
767
|
private
|
@@ -577,11 +780,12 @@ module ActiveRecord
|
|
577
780
|
def init_internals
|
578
781
|
@primary_key = self.class.primary_key
|
579
782
|
@readonly = false
|
783
|
+
@previously_new_record = false
|
580
784
|
@destroyed = false
|
581
785
|
@marked_for_destruction = false
|
582
786
|
@destroyed_by_association = nil
|
583
787
|
@_start_transaction_state = nil
|
584
|
-
@
|
788
|
+
@strict_loading = self.class.strict_loading_by_default
|
585
789
|
|
586
790
|
self.class.define_attribute_methods
|
587
791
|
end
|
@@ -601,10 +805,7 @@ module ActiveRecord
|
|
601
805
|
private_constant :InspectionMask
|
602
806
|
|
603
807
|
def inspection_filter
|
604
|
-
|
605
|
-
mask = InspectionMask.new(ActiveSupport::ParameterFilter::FILTERED)
|
606
|
-
ActiveSupport::ParameterFilter.new(self.class.filter_attributes, mask: mask)
|
607
|
-
end
|
808
|
+
self.class.inspection_filter
|
608
809
|
end
|
609
810
|
end
|
610
811
|
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "uri"
|
4
|
+
require "active_support/core_ext/enumerable"
|
5
|
+
|
6
|
+
module ActiveRecord
|
7
|
+
class DatabaseConfigurations
|
8
|
+
# Expands a connection string into a hash.
|
9
|
+
class ConnectionUrlResolver # :nodoc:
|
10
|
+
# == Example
|
11
|
+
#
|
12
|
+
# url = "postgresql://foo:bar@localhost:9000/foo_test?pool=5&timeout=3000"
|
13
|
+
# ConnectionUrlResolver.new(url).to_hash
|
14
|
+
# # => {
|
15
|
+
# adapter: "postgresql",
|
16
|
+
# host: "localhost",
|
17
|
+
# port: 9000,
|
18
|
+
# database: "foo_test",
|
19
|
+
# username: "foo",
|
20
|
+
# password: "bar",
|
21
|
+
# pool: "5",
|
22
|
+
# timeout: "3000"
|
23
|
+
# }
|
24
|
+
def initialize(url)
|
25
|
+
raise "Database URL cannot be empty" if url.blank?
|
26
|
+
@uri = uri_parser.parse(url)
|
27
|
+
@adapter = @uri.scheme && @uri.scheme.tr("-", "_")
|
28
|
+
@adapter = "postgresql" if @adapter == "postgres"
|
29
|
+
|
30
|
+
if @uri.opaque
|
31
|
+
@uri.opaque, @query = @uri.opaque.split("?", 2)
|
32
|
+
else
|
33
|
+
@query = @uri.query
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Converts the given URL to a full connection hash.
|
38
|
+
def to_hash
|
39
|
+
config = raw_config.compact_blank
|
40
|
+
config.map { |key, value| config[key] = uri_parser.unescape(value) if value.is_a? String }
|
41
|
+
config
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
attr_reader :uri
|
46
|
+
|
47
|
+
def uri_parser
|
48
|
+
@uri_parser ||= URI::Parser.new
|
49
|
+
end
|
50
|
+
|
51
|
+
# Converts the query parameters of the URI into a hash.
|
52
|
+
#
|
53
|
+
# "localhost?pool=5&reaping_frequency=2"
|
54
|
+
# # => { pool: "5", reaping_frequency: "2" }
|
55
|
+
#
|
56
|
+
# returns empty hash if no query present.
|
57
|
+
#
|
58
|
+
# "localhost"
|
59
|
+
# # => {}
|
60
|
+
def query_hash
|
61
|
+
Hash[(@query || "").split("&").map { |pair| pair.split("=", 2) }].symbolize_keys
|
62
|
+
end
|
63
|
+
|
64
|
+
def raw_config
|
65
|
+
if uri.opaque
|
66
|
+
query_hash.merge(
|
67
|
+
adapter: @adapter,
|
68
|
+
database: uri.opaque
|
69
|
+
)
|
70
|
+
else
|
71
|
+
query_hash.merge(
|
72
|
+
adapter: @adapter,
|
73
|
+
username: uri.user,
|
74
|
+
password: uri.password,
|
75
|
+
port: uri.port,
|
76
|
+
database: database_from_path,
|
77
|
+
host: uri.hostname
|
78
|
+
)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# Returns name of the database.
|
83
|
+
def database_from_path
|
84
|
+
if @adapter == "sqlite3"
|
85
|
+
# 'sqlite3:/foo' is absolute, because that makes sense. The
|
86
|
+
# corresponding relative version, 'sqlite3:foo', is handled
|
87
|
+
# elsewhere, as an "opaque".
|
88
|
+
|
89
|
+
uri.path
|
90
|
+
else
|
91
|
+
# Only SQLite uses a filename as the "database" name; for
|
92
|
+
# anything else, a leading slash would be silly.
|
93
|
+
|
94
|
+
uri.path.delete_prefix("/")
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -6,32 +6,75 @@ module ActiveRecord
|
|
6
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
|
-
attr_reader :env_name, :
|
9
|
+
attr_reader :env_name, :name
|
10
10
|
|
11
|
-
|
11
|
+
attr_accessor :owner_name
|
12
|
+
|
13
|
+
def initialize(env_name, name)
|
12
14
|
@env_name = env_name
|
13
|
-
@
|
15
|
+
@name = name
|
14
16
|
end
|
15
17
|
|
16
|
-
def
|
18
|
+
def spec_name
|
19
|
+
@name
|
20
|
+
end
|
21
|
+
deprecate spec_name: "please use name instead"
|
22
|
+
|
23
|
+
def config
|
17
24
|
raise NotImplementedError
|
18
25
|
end
|
19
26
|
|
20
|
-
def
|
27
|
+
def adapter_method
|
28
|
+
"#{adapter}_connection"
|
29
|
+
end
|
30
|
+
|
31
|
+
def host
|
32
|
+
raise NotImplementedError
|
33
|
+
end
|
34
|
+
|
35
|
+
def database
|
21
36
|
raise NotImplementedError
|
22
37
|
end
|
23
38
|
|
24
|
-
def
|
25
|
-
|
39
|
+
def _database=(database)
|
40
|
+
raise NotImplementedError
|
41
|
+
end
|
42
|
+
|
43
|
+
def adapter
|
44
|
+
raise NotImplementedError
|
26
45
|
end
|
27
46
|
|
28
|
-
def
|
29
|
-
|
47
|
+
def pool
|
48
|
+
raise NotImplementedError
|
49
|
+
end
|
50
|
+
|
51
|
+
def checkout_timeout
|
52
|
+
raise NotImplementedError
|
53
|
+
end
|
54
|
+
|
55
|
+
def reaping_frequency
|
56
|
+
raise NotImplementedError
|
57
|
+
end
|
58
|
+
|
59
|
+
def idle_timeout
|
60
|
+
raise NotImplementedError
|
61
|
+
end
|
62
|
+
|
63
|
+
def replica?
|
64
|
+
raise NotImplementedError
|
65
|
+
end
|
66
|
+
|
67
|
+
def migrations_paths
|
68
|
+
raise NotImplementedError
|
30
69
|
end
|
31
70
|
|
32
71
|
def for_current_env?
|
33
72
|
env_name == ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
|
34
73
|
end
|
74
|
+
|
75
|
+
def schema_cache_path
|
76
|
+
raise NotImplementedError
|
77
|
+
end
|
35
78
|
end
|
36
79
|
end
|
37
80
|
end
|