activerecord 6.1.7 → 7.2.0
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 +520 -1385
- data/MIT-LICENSE +1 -1
- data/README.rdoc +31 -31
- data/examples/performance.rb +2 -2
- data/lib/active_record/aggregations.rb +17 -14
- data/lib/active_record/association_relation.rb +2 -12
- data/lib/active_record/associations/alias_tracker.rb +25 -19
- data/lib/active_record/associations/association.rb +60 -21
- data/lib/active_record/associations/association_scope.rb +17 -12
- data/lib/active_record/associations/belongs_to_association.rb +37 -11
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -4
- data/lib/active_record/associations/builder/association.rb +11 -5
- data/lib/active_record/associations/builder/belongs_to.rb +41 -14
- data/lib/active_record/associations/builder/collection_association.rb +10 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -7
- data/lib/active_record/associations/builder/has_many.rb +4 -4
- data/lib/active_record/associations/builder/has_one.rb +4 -4
- data/lib/active_record/associations/builder/singular_association.rb +6 -2
- data/lib/active_record/associations/collection_association.rb +46 -36
- data/lib/active_record/associations/collection_proxy.rb +44 -16
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/errors.rb +265 -0
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +29 -19
- data/lib/active_record/associations/has_many_through_association.rb +12 -7
- data/lib/active_record/associations/has_one_association.rb +20 -10
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +27 -25
- data/lib/active_record/associations/join_dependency.rb +23 -15
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +212 -53
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +153 -0
- data/lib/active_record/associations/preloader/through_association.rb +50 -16
- data/lib/active_record/associations/preloader.rb +50 -121
- data/lib/active_record/associations/singular_association.rb +15 -3
- data/lib/active_record/associations/through_association.rb +25 -14
- data/lib/active_record/associations.rb +404 -509
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +2 -14
- data/lib/active_record/attribute_methods/before_type_cast.rb +24 -2
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +73 -22
- data/lib/active_record/attribute_methods/primary_key.rb +47 -27
- data/lib/active_record/attribute_methods/query.rb +31 -19
- data/lib/active_record/attribute_methods/read.rb +14 -11
- data/lib/active_record/attribute_methods/serialization.rb +174 -37
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +11 -9
- data/lib/active_record/attribute_methods/write.rb +12 -15
- data/lib/active_record/attribute_methods.rb +164 -52
- data/lib/active_record/attributes.rb +51 -49
- data/lib/active_record/autosave_association.rb +74 -57
- data/lib/active_record/base.rb +27 -5
- data/lib/active_record/callbacks.rb +18 -34
- 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 -46
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +284 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +79 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +327 -612
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +199 -60
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +201 -64
- data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -131
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +21 -20
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +186 -31
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +377 -142
- data/lib/active_record/connection_adapters/abstract/transaction.rb +361 -76
- data/lib/active_record/connection_adapters/abstract_adapter.rb +624 -163
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +345 -166
- data/lib/active_record/connection_adapters/column.rb +13 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +29 -130
- data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -55
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +45 -14
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +107 -68
- data/lib/active_record/connection_adapters/pool_config.rb +26 -16
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +30 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +114 -54
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
- 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/interval.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +12 -3
- 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 +30 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +137 -104
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +92 -2
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +173 -3
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +401 -77
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +518 -251
- data/lib/active_record/connection_adapters/schema_cache.rb +326 -102
- data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +78 -55
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +68 -54
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +20 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +66 -22
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +372 -130
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +229 -0
- data/lib/active_record/connection_adapters.rb +130 -6
- data/lib/active_record/connection_handling.rb +132 -146
- data/lib/active_record/core.rb +276 -251
- data/lib/active_record/counter_cache.rb +68 -34
- data/lib/active_record/database_configurations/connection_url_resolver.rb +9 -3
- data/lib/active_record/database_configurations/database_config.rb +34 -10
- data/lib/active_record/database_configurations/hash_config.rb +107 -31
- data/lib/active_record/database_configurations/url_config.rb +38 -13
- data/lib/active_record/database_configurations.rb +96 -60
- data/lib/active_record/delegated_type.rb +90 -20
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +4 -2
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +3 -3
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +68 -0
- data/lib/active_record/encryption/configurable.rb +60 -0
- data/lib/active_record/encryption/context.rb +42 -0
- data/lib/active_record/encryption/contexts.rb +76 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +230 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +175 -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 +170 -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 +157 -0
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
- data/lib/active_record/encryption/key.rb +28 -0
- data/lib/active_record/encryption/key_generator.rb +53 -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_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +96 -0
- data/lib/active_record/encryption/null_encryptor.rb +25 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +28 -0
- data/lib/active_record/encryption/scheme.rb +100 -0
- data/lib/active_record/encryption.rb +56 -0
- data/lib/active_record/enum.rb +163 -63
- data/lib/active_record/errors.rb +210 -27
- data/lib/active_record/explain.rb +21 -12
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +15 -1
- 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 +70 -14
- data/lib/active_record/fixture_set/table_rows.rb +4 -4
- data/lib/active_record/fixtures.rb +179 -112
- data/lib/active_record/future_result.rb +178 -0
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +85 -31
- data/lib/active_record/insert_all.rb +148 -32
- data/lib/active_record/integration.rb +14 -10
- data/lib/active_record/internal_metadata.rb +123 -23
- data/lib/active_record/legacy_yaml_adapter.rb +2 -39
- data/lib/active_record/locking/optimistic.rb +43 -27
- data/lib/active_record/locking/pessimistic.rb +15 -6
- data/lib/active_record/log_subscriber.rb +41 -29
- 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 +10 -10
- data/lib/active_record/middleware/database_selector.rb +23 -13
- data/lib/active_record/middleware/shard_selector.rb +62 -0
- data/lib/active_record/migration/command_recorder.rb +113 -16
- data/lib/active_record/migration/compatibility.rb +235 -46
- data/lib/active_record/migration/default_strategy.rb +22 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +374 -177
- data/lib/active_record/model_schema.rb +143 -159
- data/lib/active_record/nested_attributes.rb +48 -21
- data/lib/active_record/no_touching.rb +3 -3
- data/lib/active_record/normalization.rb +163 -0
- data/lib/active_record/persistence.rb +282 -283
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +19 -25
- data/lib/active_record/query_logs.rb +189 -0
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +44 -9
- data/lib/active_record/railtie.rb +234 -71
- data/lib/active_record/railties/controller_runtime.rb +25 -11
- data/lib/active_record/railties/databases.rake +189 -256
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +41 -3
- data/lib/active_record/reflection.rb +325 -103
- data/lib/active_record/relation/batches/batch_enumerator.rb +38 -9
- data/lib/active_record/relation/batches.rb +198 -63
- data/lib/active_record/relation/calculations.rb +300 -111
- data/lib/active_record/relation/delegation.rb +33 -22
- data/lib/active_record/relation/finder_methods.rb +123 -52
- data/lib/active_record/relation/merger.rb +26 -19
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +38 -4
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -7
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +29 -22
- data/lib/active_record/relation/query_attribute.rb +30 -12
- data/lib/active_record/relation/query_methods.rb +842 -150
- data/lib/active_record/relation/record_fetch_warning.rb +10 -9
- data/lib/active_record/relation/spawn_methods.rb +7 -6
- data/lib/active_record/relation/where_clause.rb +15 -36
- data/lib/active_record/relation.rb +736 -145
- data/lib/active_record/result.rb +67 -54
- data/lib/active_record/runtime_registry.rb +71 -13
- data/lib/active_record/sanitization.rb +84 -34
- data/lib/active_record/schema.rb +39 -23
- data/lib/active_record/schema_dumper.rb +90 -31
- data/lib/active_record/schema_migration.rb +74 -23
- data/lib/active_record/scoping/default.rb +72 -15
- data/lib/active_record/scoping/named.rb +5 -13
- data/lib/active_record/scoping.rb +65 -34
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/serialization.rb +6 -1
- data/lib/active_record/signed_id.rb +30 -9
- data/lib/active_record/statement_cache.rb +7 -7
- data/lib/active_record/store.rb +10 -10
- data/lib/active_record/suppressor.rb +13 -15
- data/lib/active_record/table_metadata.rb +7 -3
- data/lib/active_record/tasks/database_tasks.rb +277 -149
- data/lib/active_record/tasks/mysql_database_tasks.rb +16 -7
- data/lib/active_record/tasks/postgresql_database_tasks.rb +35 -26
- data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -7
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +173 -155
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +32 -19
- data/lib/active_record/token_for.rb +123 -0
- data/lib/active_record/touch_later.rb +12 -7
- data/lib/active_record/transaction.rb +132 -0
- data/lib/active_record/transactions.rb +118 -41
- data/lib/active_record/translation.rb +3 -5
- data/lib/active_record/type/adapter_specific_registry.rb +32 -14
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +9 -7
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/type/type_map.rb +17 -20
- data/lib/active_record/type.rb +1 -2
- data/lib/active_record/type_caster/connection.rb +4 -4
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +13 -7
- 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 +64 -15
- data/lib/active_record/validations.rb +12 -5
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +444 -32
- data/lib/arel/alias_predication.rb +1 -1
- data/lib/arel/attributes/attribute.rb +0 -8
- data/lib/arel/collectors/bind.rb +2 -0
- data/lib/arel/collectors/composite.rb +7 -0
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +1 -1
- data/lib/arel/crud.rb +28 -22
- data/lib/arel/delete_manager.rb +18 -4
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +2 -3
- data/lib/arel/nodes/binary.rb +6 -7
- data/lib/arel/nodes/bound_sql_literal.rb +65 -0
- data/lib/arel/nodes/casted.rb +1 -1
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/delete_statement.rb +12 -13
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/function.rb +1 -0
- data/lib/arel/nodes/homogeneous_in.rb +1 -9
- data/lib/arel/nodes/insert_statement.rb +2 -2
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/{and.rb → nary.rb} +9 -2
- data/lib/arel/nodes/node.rb +115 -5
- data/lib/arel/nodes/select_core.rb +2 -2
- data/lib/arel/nodes/select_statement.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +13 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes/update_statement.rb +8 -3
- data/lib/arel/nodes.rb +7 -2
- data/lib/arel/predications.rb +14 -4
- data/lib/arel/select_manager.rb +11 -5
- data/lib/arel/table.rb +9 -6
- data/lib/arel/tree_manager.rb +8 -15
- data/lib/arel/update_manager.rb +20 -5
- data/lib/arel/visitors/dot.rb +81 -90
- data/lib/arel/visitors/mysql.rb +23 -5
- data/lib/arel/visitors/postgresql.rb +1 -22
- data/lib/arel/visitors/to_sql.rb +170 -36
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +23 -4
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
- 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
- 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
- data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
- data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
- metadata +100 -14
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -67
data/lib/active_record/core.rb
CHANGED
@@ -1,42 +1,50 @@
|
|
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
|
##
|
15
16
|
# :singleton-method:
|
16
17
|
#
|
17
|
-
# Accepts a logger conforming to the interface of Log4r
|
18
|
-
# passed on to any new database
|
19
|
-
#
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
#
|
26
|
-
|
27
|
-
|
18
|
+
# Accepts a logger conforming to the interface of Log4r or the default
|
19
|
+
# Ruby +Logger+ class, which is then passed on to any new database
|
20
|
+
# connections made. You can retrieve this logger by calling +logger+ on
|
21
|
+
# either an Active Record model class or an Active Record model instance.
|
22
|
+
class_attribute :logger, instance_writer: false
|
23
|
+
|
24
|
+
class_attribute :_destroy_association_async_job, instance_accessor: false, default: "ActiveRecord::DestroyAssociationAsyncJob"
|
25
|
+
|
26
|
+
# The job class used to destroy associations in the background.
|
27
|
+
def self.destroy_association_async_job
|
28
|
+
if _destroy_association_async_job.is_a?(String)
|
29
|
+
self._destroy_association_async_job = _destroy_association_async_job.constantize
|
30
|
+
end
|
31
|
+
_destroy_association_async_job
|
32
|
+
rescue NameError => error
|
33
|
+
raise NameError, "Unable to load destroy_association_async_job: #{error.message}"
|
34
|
+
end
|
28
35
|
|
29
|
-
|
30
|
-
|
31
|
-
#
|
32
|
-
# Specifies the names of the queues used by background jobs.
|
33
|
-
mattr_accessor :queues, instance_accessor: false, default: {}
|
36
|
+
singleton_class.alias_method :destroy_association_async_job=, :_destroy_association_async_job=
|
37
|
+
delegate :destroy_association_async_job, to: :class
|
34
38
|
|
35
39
|
##
|
36
40
|
# :singleton-method:
|
37
41
|
#
|
38
|
-
# Specifies the
|
39
|
-
|
42
|
+
# Specifies the maximum number of records that will be destroyed in a
|
43
|
+
# single background job by the <tt>dependent: :destroy_async</tt>
|
44
|
+
# association option. When +nil+ (default), all dependent records will be
|
45
|
+
# destroyed in a single background job. If specified, the records to be
|
46
|
+
# destroyed will be split into multiple background jobs.
|
47
|
+
class_attribute :destroy_association_async_batch_size, instance_writer: false, instance_predicate: false, default: nil
|
40
48
|
|
41
49
|
##
|
42
50
|
# Contains the database configuration - as is typically stored in config/database.yml -
|
@@ -46,106 +54,45 @@ module ActiveRecord
|
|
46
54
|
#
|
47
55
|
# development:
|
48
56
|
# adapter: sqlite3
|
49
|
-
# database:
|
57
|
+
# database: storage/development.sqlite3
|
50
58
|
#
|
51
59
|
# production:
|
52
60
|
# adapter: sqlite3
|
53
|
-
# database:
|
61
|
+
# database: storage/production.sqlite3
|
54
62
|
#
|
55
63
|
# ...would result in ActiveRecord::Base.configurations to look like this:
|
56
64
|
#
|
57
65
|
# #<ActiveRecord::DatabaseConfigurations:0x00007fd1acbdf800 @configurations=[
|
58
66
|
# #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10 @env_name="development",
|
59
|
-
# @name="primary", @config={adapter: "sqlite3", database: "
|
67
|
+
# @name="primary", @config={adapter: "sqlite3", database: "storage/development.sqlite3"}>,
|
60
68
|
# #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbdea90 @env_name="production",
|
61
|
-
# @name="primary", @config={adapter: "sqlite3", database: "
|
69
|
+
# @name="primary", @config={adapter: "sqlite3", database: "storage/production.sqlite3"}>
|
62
70
|
# ]>
|
63
71
|
def self.configurations=(config)
|
64
72
|
@@configurations = ActiveRecord::DatabaseConfigurations.new(config)
|
65
73
|
end
|
66
74
|
self.configurations = {}
|
67
75
|
|
68
|
-
# Returns fully resolved ActiveRecord::DatabaseConfigurations object
|
76
|
+
# Returns a fully resolved ActiveRecord::DatabaseConfigurations object.
|
69
77
|
def self.configurations
|
70
78
|
@@configurations
|
71
79
|
end
|
72
80
|
|
73
81
|
##
|
74
82
|
# :singleton-method:
|
75
|
-
#
|
76
|
-
#
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
# :singleton-method:
|
81
|
-
# Specifies the format to use when dumping the database schema with Rails'
|
82
|
-
# Rakefile. If :sql, the schema is dumped as (potentially database-
|
83
|
-
# specific) SQL statements. If :ruby, the schema is dumped as an
|
84
|
-
# ActiveRecord::Schema file which can be loaded into any database that
|
85
|
-
# supports migrations. Use :ruby if you want to have different database
|
86
|
-
# adapters for, e.g., your development and test environments.
|
87
|
-
mattr_accessor :schema_format, instance_writer: false, default: :ruby
|
88
|
-
|
89
|
-
##
|
90
|
-
# :singleton-method:
|
91
|
-
# Specifies if an error should be raised if the query has an order being
|
92
|
-
# ignored when doing batch queries. Useful in applications where the
|
93
|
-
# scope being ignored is error-worthy, rather than a warning.
|
94
|
-
mattr_accessor :error_on_ignored_order, instance_writer: false, default: false
|
95
|
-
|
96
|
-
##
|
97
|
-
# :singleton-method:
|
98
|
-
# Specify whether or not to use timestamps for migration versions
|
99
|
-
mattr_accessor :timestamped_migrations, instance_writer: false, default: true
|
100
|
-
|
101
|
-
##
|
102
|
-
# :singleton-method:
|
103
|
-
# Specify whether schema dump should happen at the end of the
|
104
|
-
# db:migrate rails command. This is true by default, which is useful for the
|
105
|
-
# development environment. This should ideally be false in the production
|
106
|
-
# environment where dumping schema is rarely needed.
|
107
|
-
mattr_accessor :dump_schema_after_migration, instance_writer: false, default: true
|
108
|
-
|
109
|
-
##
|
110
|
-
# :singleton-method:
|
111
|
-
# Specifies which database schemas to dump when calling db:schema:dump.
|
112
|
-
# If the value is :schema_search_path (the default), any schemas listed in
|
113
|
-
# schema_search_path are dumped. Use :all to dump all schemas regardless
|
114
|
-
# of schema_search_path, or a string of comma separated schemas for a
|
115
|
-
# custom list.
|
116
|
-
mattr_accessor :dump_schemas, instance_writer: false, default: :schema_search_path
|
117
|
-
|
118
|
-
##
|
119
|
-
# :singleton-method:
|
120
|
-
# Specify a threshold for the size of query result sets. If the number of
|
121
|
-
# records in the set exceeds the threshold, a warning is logged. This can
|
122
|
-
# be used to identify queries which load thousands of records and
|
123
|
-
# potentially cause memory bloat.
|
124
|
-
mattr_accessor :warn_on_records_fetched_greater_than, instance_writer: false
|
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
|
-
|
132
|
-
mattr_accessor :maintain_test_schema, instance_accessor: false
|
83
|
+
# Force enumeration of all columns in SELECT statements.
|
84
|
+
# e.g. <tt>SELECT first_name, last_name FROM ...</tt> instead of <tt>SELECT * FROM ...</tt>
|
85
|
+
# This avoids +PreparedStatementCacheExpired+ errors when a column is added
|
86
|
+
# to the database while the app is running.
|
87
|
+
class_attribute :enumerate_columns_in_select_statements, instance_accessor: false, default: false
|
133
88
|
|
134
89
|
class_attribute :belongs_to_required_by_default, instance_accessor: false
|
135
90
|
|
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
91
|
class_attribute :strict_loading_by_default, instance_accessor: false, default: false
|
143
92
|
|
144
|
-
|
93
|
+
class_attribute :has_many_inversing, instance_accessor: false, default: false
|
145
94
|
|
146
|
-
|
147
|
-
|
148
|
-
mattr_accessor :has_many_inversing, instance_accessor: false, default: false
|
95
|
+
class_attribute :run_commit_callbacks_on_first_saved_instances_in_transaction, instance_accessor: false, default: true
|
149
96
|
|
150
97
|
class_attribute :default_connection_handler, instance_writer: false
|
151
98
|
|
@@ -153,40 +100,38 @@ module ActiveRecord
|
|
153
100
|
|
154
101
|
class_attribute :default_shard, instance_writer: false
|
155
102
|
|
156
|
-
|
103
|
+
class_attribute :shard_selector, instance_accessor: false, default: nil
|
157
104
|
|
158
|
-
#
|
159
|
-
|
160
|
-
mattr_accessor :use_yaml_unsafe_load, instance_writer: false, default: false
|
105
|
+
# Specifies the attributes that will be included in the output of the #inspect method
|
106
|
+
class_attribute :attributes_for_inspect, instance_accessor: false, default: [:id]
|
161
107
|
|
162
|
-
|
163
|
-
|
164
|
-
|
108
|
+
def self.application_record_class? # :nodoc:
|
109
|
+
if ActiveRecord.application_record_class
|
110
|
+
self == ActiveRecord.application_record_class
|
111
|
+
else
|
112
|
+
if defined?(ApplicationRecord) && self == ApplicationRecord
|
113
|
+
true
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
165
117
|
|
166
118
|
self.filter_attributes = []
|
167
119
|
|
168
120
|
def self.connection_handler
|
169
|
-
|
121
|
+
ActiveSupport::IsolatedExecutionState[:active_record_connection_handler] || default_connection_handler
|
170
122
|
end
|
171
123
|
|
172
124
|
def self.connection_handler=(handler)
|
173
|
-
|
125
|
+
ActiveSupport::IsolatedExecutionState[:active_record_connection_handler] = handler
|
174
126
|
end
|
175
127
|
|
176
|
-
def self.
|
177
|
-
|
178
|
-
raise NotImplementedError, "The new connection handling does not support accessing multiple connection handlers."
|
179
|
-
end
|
180
|
-
|
181
|
-
@@connection_handlers ||= {}
|
128
|
+
def self.asynchronous_queries_session # :nodoc:
|
129
|
+
asynchronous_queries_tracker.current_session
|
182
130
|
end
|
183
131
|
|
184
|
-
def self.
|
185
|
-
|
186
|
-
|
187
|
-
end
|
188
|
-
|
189
|
-
@@connection_handlers = handlers
|
132
|
+
def self.asynchronous_queries_tracker # :nodoc:
|
133
|
+
ActiveSupport::IsolatedExecutionState[:active_record_asynchronous_queries_tracker] ||= \
|
134
|
+
AsynchronousQueriesTracker.new
|
190
135
|
end
|
191
136
|
|
192
137
|
# Returns the symbol representing the current connected role.
|
@@ -199,16 +144,12 @@ module ActiveRecord
|
|
199
144
|
# ActiveRecord::Base.current_role #=> :reading
|
200
145
|
# end
|
201
146
|
def self.current_role
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
connected_to_stack.reverse_each do |hash|
|
206
|
-
return hash[:role] if hash[:role] && hash[:klasses].include?(Base)
|
207
|
-
return hash[:role] if hash[:role] && hash[:klasses].include?(connection_classes)
|
208
|
-
end
|
209
|
-
|
210
|
-
default_role
|
147
|
+
connected_to_stack.reverse_each do |hash|
|
148
|
+
return hash[:role] if hash[:role] && hash[:klasses].include?(Base)
|
149
|
+
return hash[:role] if hash[:role] && hash[:klasses].include?(connection_class_for_self)
|
211
150
|
end
|
151
|
+
|
152
|
+
default_role
|
212
153
|
end
|
213
154
|
|
214
155
|
# Returns the symbol representing the current connected shard.
|
@@ -223,7 +164,7 @@ module ActiveRecord
|
|
223
164
|
def self.current_shard
|
224
165
|
connected_to_stack.reverse_each do |hash|
|
225
166
|
return hash[:shard] if hash[:shard] && hash[:klasses].include?(Base)
|
226
|
-
return hash[:shard] if hash[:shard] && hash[:klasses].include?(
|
167
|
+
return hash[:shard] if hash[:shard] && hash[:klasses].include?(connection_class_for_self)
|
227
168
|
end
|
228
169
|
|
229
170
|
default_shard
|
@@ -240,24 +181,20 @@ module ActiveRecord
|
|
240
181
|
# ActiveRecord::Base.current_preventing_writes #=> false
|
241
182
|
# end
|
242
183
|
def self.current_preventing_writes
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
connected_to_stack.reverse_each do |hash|
|
247
|
-
return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(Base)
|
248
|
-
return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(connection_classes)
|
249
|
-
end
|
250
|
-
|
251
|
-
false
|
184
|
+
connected_to_stack.reverse_each do |hash|
|
185
|
+
return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(Base)
|
186
|
+
return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(connection_class_for_self)
|
252
187
|
end
|
188
|
+
|
189
|
+
false
|
253
190
|
end
|
254
191
|
|
255
192
|
def self.connected_to_stack # :nodoc:
|
256
|
-
if connected_to_stack =
|
193
|
+
if connected_to_stack = ActiveSupport::IsolatedExecutionState[:active_record_connected_to_stack]
|
257
194
|
connected_to_stack
|
258
195
|
else
|
259
196
|
connected_to_stack = Concurrent::Array.new
|
260
|
-
|
197
|
+
ActiveSupport::IsolatedExecutionState[:active_record_connected_to_stack] = connected_to_stack
|
261
198
|
connected_to_stack
|
262
199
|
end
|
263
200
|
end
|
@@ -266,7 +203,7 @@ module ActiveRecord
|
|
266
203
|
@connection_class = b
|
267
204
|
end
|
268
205
|
|
269
|
-
def self.connection_class # :nodoc
|
206
|
+
def self.connection_class # :nodoc:
|
270
207
|
@connection_class ||= false
|
271
208
|
end
|
272
209
|
|
@@ -274,7 +211,7 @@ module ActiveRecord
|
|
274
211
|
self.connection_class
|
275
212
|
end
|
276
213
|
|
277
|
-
def self.
|
214
|
+
def self.connection_class_for_self # :nodoc:
|
278
215
|
klass = self
|
279
216
|
|
280
217
|
until klass == Base
|
@@ -285,22 +222,14 @@ module ActiveRecord
|
|
285
222
|
klass
|
286
223
|
end
|
287
224
|
|
288
|
-
def self.allow_unsafe_raw_sql # :nodoc:
|
289
|
-
ActiveSupport::Deprecation.warn("ActiveRecord::Base.allow_unsafe_raw_sql is deprecated and will be removed in Rails 7.0")
|
290
|
-
end
|
291
|
-
|
292
|
-
def self.allow_unsafe_raw_sql=(value) # :nodoc:
|
293
|
-
ActiveSupport::Deprecation.warn("ActiveRecord::Base.allow_unsafe_raw_sql= is deprecated and will be removed in Rails 7.0")
|
294
|
-
end
|
295
|
-
|
296
225
|
self.default_connection_handler = ConnectionAdapters::ConnectionHandler.new
|
297
|
-
self.default_role = writing_role
|
226
|
+
self.default_role = ActiveRecord.writing_role
|
298
227
|
self.default_shard = :default
|
299
228
|
|
300
229
|
def self.strict_loading_violation!(owner:, reflection:) # :nodoc:
|
301
|
-
case action_on_strict_loading_violation
|
230
|
+
case ActiveRecord.action_on_strict_loading_violation
|
302
231
|
when :raise
|
303
|
-
message =
|
232
|
+
message = reflection.strict_loading_violation_message(owner)
|
304
233
|
raise ActiveRecord::StrictLoadingViolationError.new(message)
|
305
234
|
when :log
|
306
235
|
name = "strict_loading_violation.active_record"
|
@@ -314,19 +243,6 @@ module ActiveRecord
|
|
314
243
|
@find_by_statement_cache = { true => Concurrent::Map.new, false => Concurrent::Map.new }
|
315
244
|
end
|
316
245
|
|
317
|
-
def inherited(child_class) # :nodoc:
|
318
|
-
# initialize cache at class definition for thread safety
|
319
|
-
child_class.initialize_find_by_cache
|
320
|
-
unless child_class.base_class?
|
321
|
-
klass = self
|
322
|
-
until klass.base_class?
|
323
|
-
klass.initialize_find_by_cache
|
324
|
-
klass = klass.superclass
|
325
|
-
end
|
326
|
-
end
|
327
|
-
super
|
328
|
-
end
|
329
|
-
|
330
246
|
def find(*ids) # :nodoc:
|
331
247
|
# We don't have cache keys for this stuff yet
|
332
248
|
return super unless ids.length == 1
|
@@ -336,14 +252,8 @@ module ActiveRecord
|
|
336
252
|
|
337
253
|
return super if StatementCache.unsupported_value?(id)
|
338
254
|
|
339
|
-
|
340
|
-
|
341
|
-
statement = cached_find_by_statement(key) { |params|
|
342
|
-
where(key => params.bind).limit(1)
|
343
|
-
}
|
344
|
-
|
345
|
-
statement.execute([id], connection).first ||
|
346
|
-
raise(RecordNotFound.new("Couldn't find #{name} with '#{key}'=#{id}", name, key, id))
|
255
|
+
cached_find_by([primary_key], [id]) ||
|
256
|
+
raise(RecordNotFound.new("Couldn't find #{name} with '#{primary_key}'=#{id}", name, primary_key, id))
|
347
257
|
end
|
348
258
|
|
349
259
|
def find_by(*args) # :nodoc:
|
@@ -365,31 +275,36 @@ module ActiveRecord
|
|
365
275
|
elsif reflection.belongs_to? && !reflection.polymorphic?
|
366
276
|
key = reflection.join_foreign_key
|
367
277
|
pkey = reflection.join_primary_key
|
368
|
-
|
278
|
+
|
279
|
+
if pkey.is_a?(Array)
|
280
|
+
if pkey.all? { |attribute| value.respond_to?(attribute) }
|
281
|
+
value = pkey.map do |attribute|
|
282
|
+
if attribute == "id"
|
283
|
+
value.id_value
|
284
|
+
else
|
285
|
+
value.public_send(attribute)
|
286
|
+
end
|
287
|
+
end
|
288
|
+
composite_primary_key = true
|
289
|
+
end
|
290
|
+
else
|
291
|
+
value = value.public_send(pkey) if value.respond_to?(pkey)
|
292
|
+
end
|
369
293
|
end
|
370
294
|
|
371
|
-
if !
|
295
|
+
if !composite_primary_key &&
|
296
|
+
(!columns_hash.key?(key) || StatementCache.unsupported_value?(value))
|
372
297
|
return super
|
373
298
|
end
|
374
299
|
|
375
300
|
h[key] = value
|
376
301
|
end
|
377
302
|
|
378
|
-
keys
|
379
|
-
statement = cached_find_by_statement(keys) { |params|
|
380
|
-
wheres = keys.index_with { params.bind }
|
381
|
-
where(wheres).limit(1)
|
382
|
-
}
|
383
|
-
|
384
|
-
begin
|
385
|
-
statement.execute(hash.values, connection).first
|
386
|
-
rescue TypeError
|
387
|
-
raise ActiveRecord::StatementInvalid
|
388
|
-
end
|
303
|
+
cached_find_by(hash.keys, hash.values)
|
389
304
|
end
|
390
305
|
|
391
306
|
def find_by!(*args) # :nodoc:
|
392
|
-
find_by(*args) ||
|
307
|
+
find_by(*args) || where(*args).raise_record_not_found_exception!
|
393
308
|
end
|
394
309
|
|
395
310
|
def initialize_generated_modules # :nodoc:
|
@@ -408,10 +323,10 @@ module ActiveRecord
|
|
408
323
|
|
409
324
|
# Returns columns which shouldn't be exposed while calling +#inspect+.
|
410
325
|
def filter_attributes
|
411
|
-
if
|
412
|
-
@filter_attributes
|
413
|
-
else
|
326
|
+
if @filter_attributes.nil?
|
414
327
|
superclass.filter_attributes
|
328
|
+
else
|
329
|
+
@filter_attributes
|
415
330
|
end
|
416
331
|
end
|
417
332
|
|
@@ -422,13 +337,13 @@ module ActiveRecord
|
|
422
337
|
end
|
423
338
|
|
424
339
|
def inspection_filter # :nodoc:
|
425
|
-
if
|
340
|
+
if @filter_attributes.nil?
|
341
|
+
superclass.inspection_filter
|
342
|
+
else
|
426
343
|
@inspection_filter ||= begin
|
427
344
|
mask = InspectionMask.new(ActiveSupport::ParameterFilter::FILTERED)
|
428
345
|
ActiveSupport::ParameterFilter.new(@filter_attributes, mask: mask)
|
429
346
|
end
|
430
|
-
else
|
431
|
-
superclass.inspection_filter
|
432
347
|
end
|
433
348
|
end
|
434
349
|
|
@@ -439,7 +354,7 @@ module ActiveRecord
|
|
439
354
|
elsif abstract_class?
|
440
355
|
"#{super}(abstract)"
|
441
356
|
elsif !connected?
|
442
|
-
"#{super} (call '#{super}.
|
357
|
+
"#{super} (call '#{super}.lease_connection' to establish a connection)"
|
443
358
|
elsif table_exists?
|
444
359
|
attr_list = attribute_types.map { |name, type| "#{name}: #{type.type}" } * ", "
|
445
360
|
"#{super}(#{attr_list})"
|
@@ -448,25 +363,11 @@ module ActiveRecord
|
|
448
363
|
end
|
449
364
|
end
|
450
365
|
|
451
|
-
#
|
452
|
-
def ===(object) # :nodoc:
|
453
|
-
object.is_a?(self)
|
454
|
-
end
|
455
|
-
|
456
|
-
# Returns an instance of <tt>Arel::Table</tt> loaded with the current table name.
|
457
|
-
#
|
458
|
-
# class Post < ActiveRecord::Base
|
459
|
-
# scope :published_and_commented, -> { published.and(arel_table[:comments_count].gt(0)) }
|
460
|
-
# end
|
366
|
+
# Returns an instance of +Arel::Table+ loaded with the current table name.
|
461
367
|
def arel_table # :nodoc:
|
462
368
|
@arel_table ||= Arel::Table.new(table_name, klass: self)
|
463
369
|
end
|
464
370
|
|
465
|
-
def arel_attribute(name, table = arel_table) # :nodoc:
|
466
|
-
table[name]
|
467
|
-
end
|
468
|
-
deprecate :arel_attribute
|
469
|
-
|
470
371
|
def predicate_builder # :nodoc:
|
471
372
|
@predicate_builder ||= PredicateBuilder.new(table_metadata)
|
472
373
|
end
|
@@ -475,16 +376,34 @@ module ActiveRecord
|
|
475
376
|
TypeCaster::Map.new(self)
|
476
377
|
end
|
477
378
|
|
478
|
-
def
|
479
|
-
false
|
480
|
-
end
|
481
|
-
|
482
|
-
def cached_find_by_statement(key, &block) # :nodoc:
|
379
|
+
def cached_find_by_statement(connection, key, &block) # :nodoc:
|
483
380
|
cache = @find_by_statement_cache[connection.prepared_statements]
|
484
381
|
cache.compute_if_absent(key) { StatementCache.create(connection, &block) }
|
485
382
|
end
|
486
383
|
|
487
384
|
private
|
385
|
+
def inherited(subclass)
|
386
|
+
super
|
387
|
+
|
388
|
+
# initialize cache at class definition for thread safety
|
389
|
+
subclass.initialize_find_by_cache
|
390
|
+
unless subclass.base_class?
|
391
|
+
klass = self
|
392
|
+
until klass.base_class?
|
393
|
+
klass.initialize_find_by_cache
|
394
|
+
klass = klass.superclass
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
subclass.class_eval do
|
399
|
+
@arel_table = nil
|
400
|
+
@predicate_builder = nil
|
401
|
+
@inspection_filter = nil
|
402
|
+
@filter_attributes ||= nil
|
403
|
+
@generated_association_methods ||= nil
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
488
407
|
def relation
|
489
408
|
relation = Relation.create(self)
|
490
409
|
|
@@ -498,6 +417,27 @@ module ActiveRecord
|
|
498
417
|
def table_metadata
|
499
418
|
TableMetadata.new(self, arel_table)
|
500
419
|
end
|
420
|
+
|
421
|
+
def cached_find_by(keys, values)
|
422
|
+
with_connection do |connection|
|
423
|
+
statement = cached_find_by_statement(connection, keys) { |params|
|
424
|
+
wheres = keys.index_with do |key|
|
425
|
+
if key.is_a?(Array)
|
426
|
+
[key.map { params.bind }]
|
427
|
+
else
|
428
|
+
params.bind
|
429
|
+
end
|
430
|
+
end
|
431
|
+
where(wheres).limit(1)
|
432
|
+
}
|
433
|
+
|
434
|
+
begin
|
435
|
+
statement.execute(values.flatten, connection, allow_retry: true).first
|
436
|
+
rescue TypeError
|
437
|
+
raise ActiveRecord::StatementInvalid
|
438
|
+
end
|
439
|
+
end
|
440
|
+
end
|
501
441
|
end
|
502
442
|
|
503
443
|
# New objects can be instantiated as either empty (pass no construction parameter) or pre-set with
|
@@ -505,7 +445,7 @@ module ActiveRecord
|
|
505
445
|
# In both instances, valid attribute keys are determined by the column names of the associated table --
|
506
446
|
# hence you can't have attributes that aren't part of the table columns.
|
507
447
|
#
|
508
|
-
# ==== Example
|
448
|
+
# ==== Example
|
509
449
|
# # Instantiates a single new object
|
510
450
|
# User.new(first_name: 'Jamie')
|
511
451
|
def initialize(attributes = nil)
|
@@ -515,7 +455,7 @@ module ActiveRecord
|
|
515
455
|
init_internals
|
516
456
|
initialize_internals_callback
|
517
457
|
|
518
|
-
|
458
|
+
super
|
519
459
|
|
520
460
|
yield self if block_given?
|
521
461
|
_run_initialize_callbacks
|
@@ -536,7 +476,7 @@ module ActiveRecord
|
|
536
476
|
# post.init_with(coder)
|
537
477
|
# post.title # => 'hello world'
|
538
478
|
def init_with(coder, &block)
|
539
|
-
coder = LegacyYamlAdapter.convert(
|
479
|
+
coder = LegacyYamlAdapter.convert(coder)
|
540
480
|
attributes = self.class.yaml_encoder.decode(coder)
|
541
481
|
init_with_attributes(attributes, coder["new_record"], &block)
|
542
482
|
end
|
@@ -583,12 +523,17 @@ module ActiveRecord
|
|
583
523
|
# only, not its associations. The extent of a "deep" copy is application
|
584
524
|
# specific and is therefore left to the application to implement according
|
585
525
|
# to its need.
|
586
|
-
# The dup method does not preserve the timestamps (created|updated)_(at|on)
|
526
|
+
# The dup method does not preserve the timestamps (created|updated)_(at|on)
|
527
|
+
# and locking column.
|
587
528
|
|
588
529
|
##
|
589
530
|
def initialize_dup(other) # :nodoc:
|
590
531
|
@attributes = @attributes.deep_dup
|
591
|
-
|
532
|
+
if self.class.composite_primary_key?
|
533
|
+
@primary_key.each { |key| @attributes.reset(key) }
|
534
|
+
else
|
535
|
+
@attributes.reset(@primary_key)
|
536
|
+
end
|
592
537
|
|
593
538
|
_run_initialize_callbacks
|
594
539
|
|
@@ -618,6 +563,35 @@ module ActiveRecord
|
|
618
563
|
coder["active_record_yaml_version"] = 2
|
619
564
|
end
|
620
565
|
|
566
|
+
##
|
567
|
+
# :method: slice
|
568
|
+
#
|
569
|
+
# :call-seq: slice(*methods)
|
570
|
+
#
|
571
|
+
# Returns a hash of the given methods with their names as keys and returned
|
572
|
+
# values as values.
|
573
|
+
#
|
574
|
+
# topic = Topic.new(title: "Budget", author_name: "Jason")
|
575
|
+
# topic.slice(:title, :author_name)
|
576
|
+
# => { "title" => "Budget", "author_name" => "Jason" }
|
577
|
+
#
|
578
|
+
#--
|
579
|
+
# Implemented by ActiveModel::Access#slice.
|
580
|
+
|
581
|
+
##
|
582
|
+
# :method: values_at
|
583
|
+
#
|
584
|
+
# :call-seq: values_at(*methods)
|
585
|
+
#
|
586
|
+
# Returns an array of the values returned by the given methods.
|
587
|
+
#
|
588
|
+
# topic = Topic.new(title: "Budget", author_name: "Jason")
|
589
|
+
# topic.values_at(:title, :author_name)
|
590
|
+
# => ["Budget", "Jason"]
|
591
|
+
#
|
592
|
+
#--
|
593
|
+
# Implemented by ActiveModel::Access#values_at.
|
594
|
+
|
621
595
|
# Returns true if +comparison_object+ is the same exact object, or +comparison_object+
|
622
596
|
# is of the same type and +self+ has an ID and it is equal to +comparison_object.id+.
|
623
597
|
#
|
@@ -630,7 +604,7 @@ module ActiveRecord
|
|
630
604
|
def ==(comparison_object)
|
631
605
|
super ||
|
632
606
|
comparison_object.instance_of?(self.class) &&
|
633
|
-
|
607
|
+
primary_key_values_present? &&
|
634
608
|
comparison_object.id == id
|
635
609
|
end
|
636
610
|
alias :eql? :==
|
@@ -638,7 +612,9 @@ module ActiveRecord
|
|
638
612
|
# Delegates to id in order to allow two records of the same type and id to work with something like:
|
639
613
|
# [ Person.find(1), Person.find(2), Person.find(3) ] & [ Person.find(1), Person.find(4) ] # => [ Person.find(1) ]
|
640
614
|
def hash
|
641
|
-
|
615
|
+
id = self.id
|
616
|
+
|
617
|
+
if primary_key_values_present?
|
642
618
|
self.class.hash ^ id.hash
|
643
619
|
else
|
644
620
|
super
|
@@ -689,14 +665,57 @@ module ActiveRecord
|
|
689
665
|
# if the record tries to lazily load an association.
|
690
666
|
#
|
691
667
|
# user = User.first
|
692
|
-
# user.strict_loading!
|
668
|
+
# user.strict_loading! # => true
|
669
|
+
# user.address.city
|
670
|
+
# => ActiveRecord::StrictLoadingViolationError
|
693
671
|
# user.comments.to_a
|
694
672
|
# => ActiveRecord::StrictLoadingViolationError
|
695
|
-
|
696
|
-
|
673
|
+
#
|
674
|
+
# ==== Parameters
|
675
|
+
#
|
676
|
+
# * +value+ - Boolean specifying whether to enable or disable strict loading.
|
677
|
+
# * <tt>:mode</tt> - Symbol specifying strict loading mode. Defaults to :all. Using
|
678
|
+
# :n_plus_one_only mode will only raise an error if an association that
|
679
|
+
# will lead to an n plus one query is lazily loaded.
|
680
|
+
#
|
681
|
+
# ==== Examples
|
682
|
+
#
|
683
|
+
# user = User.first
|
684
|
+
# user.strict_loading!(false) # => false
|
685
|
+
# user.address.city # => "Tatooine"
|
686
|
+
# user.comments.to_a # => [#<Comment:0x00...]
|
687
|
+
#
|
688
|
+
# user.strict_loading!(mode: :n_plus_one_only)
|
689
|
+
# user.address.city # => "Tatooine"
|
690
|
+
# user.comments.to_a # => [#<Comment:0x00...]
|
691
|
+
# user.comments.first.ratings.to_a
|
692
|
+
# => ActiveRecord::StrictLoadingViolationError
|
693
|
+
def strict_loading!(value = true, mode: :all)
|
694
|
+
unless [:all, :n_plus_one_only].include?(mode)
|
695
|
+
raise ArgumentError, "The :mode option must be one of [:all, :n_plus_one_only] but #{mode.inspect} was provided."
|
696
|
+
end
|
697
|
+
|
698
|
+
@strict_loading_mode = mode
|
699
|
+
@strict_loading = value
|
700
|
+
end
|
701
|
+
|
702
|
+
attr_reader :strict_loading_mode
|
703
|
+
|
704
|
+
# Returns +true+ if the record uses strict_loading with +:n_plus_one_only+ mode enabled.
|
705
|
+
def strict_loading_n_plus_one_only?
|
706
|
+
@strict_loading_mode == :n_plus_one_only
|
707
|
+
end
|
708
|
+
|
709
|
+
# Returns +true+ if the record uses strict_loading with +:all+ mode enabled.
|
710
|
+
def strict_loading_all?
|
711
|
+
@strict_loading_mode == :all
|
697
712
|
end
|
698
713
|
|
699
714
|
# Marks this record as read only.
|
715
|
+
#
|
716
|
+
# customer = Customer.first
|
717
|
+
# customer.readonly!
|
718
|
+
# customer.save # Raises an ActiveRecord::ReadOnlyRecord
|
700
719
|
def readonly!
|
701
720
|
@readonly = true
|
702
721
|
end
|
@@ -705,21 +724,14 @@ module ActiveRecord
|
|
705
724
|
self.class.connection_handler
|
706
725
|
end
|
707
726
|
|
708
|
-
# Returns the
|
727
|
+
# Returns the attributes specified by <tt>.attributes_for_inspect</tt> as a nicely formatted string.
|
709
728
|
def inspect
|
710
|
-
|
711
|
-
|
712
|
-
inspection = if defined?(@attributes) && @attributes
|
713
|
-
self.class.attribute_names.collect do |name|
|
714
|
-
if _has_attribute?(name)
|
715
|
-
"#{name}: #{attribute_for_inspect(name)}"
|
716
|
-
end
|
717
|
-
end.compact.join(", ")
|
718
|
-
else
|
719
|
-
"not initialized"
|
720
|
-
end
|
729
|
+
inspect_with_attributes(attributes_for_inspect)
|
730
|
+
end
|
721
731
|
|
722
|
-
|
732
|
+
# Returns the full contents of the record as a nicely formatted string.
|
733
|
+
def full_inspect
|
734
|
+
inspect_with_attributes(attribute_names)
|
723
735
|
end
|
724
736
|
|
725
737
|
# Takes a PP and prettily prints this record to it, allowing you to get a nice result from <tt>pp record</tt>
|
@@ -727,17 +739,17 @@ module ActiveRecord
|
|
727
739
|
def pretty_print(pp)
|
728
740
|
return super if custom_inspect_method_defined?
|
729
741
|
pp.object_address_group(self) do
|
730
|
-
if
|
731
|
-
attr_names =
|
742
|
+
if @attributes
|
743
|
+
attr_names = attributes_for_inspect.select { |name| _has_attribute?(name.to_s) }
|
732
744
|
pp.seplist(attr_names, proc { pp.text "," }) do |attr_name|
|
745
|
+
attr_name = attr_name.to_s
|
733
746
|
pp.breakable " "
|
734
747
|
pp.group(1) do
|
735
748
|
pp.text attr_name
|
736
749
|
pp.text ":"
|
737
750
|
pp.breakable
|
738
|
-
value =
|
739
|
-
|
740
|
-
pp.pp value
|
751
|
+
value = attribute_for_inspect(attr_name)
|
752
|
+
pp.text value
|
741
753
|
end
|
742
754
|
end
|
743
755
|
else
|
@@ -747,16 +759,6 @@ module ActiveRecord
|
|
747
759
|
end
|
748
760
|
end
|
749
761
|
|
750
|
-
# Returns a hash of the given methods with their names as keys and returned values as values.
|
751
|
-
def slice(*methods)
|
752
|
-
methods.flatten.index_with { |method| public_send(method) }.with_indifferent_access
|
753
|
-
end
|
754
|
-
|
755
|
-
# Returns an array of the values returned by the given methods.
|
756
|
-
def values_at(*methods)
|
757
|
-
methods.flatten.map! { |method| public_send(method) }
|
758
|
-
end
|
759
|
-
|
760
762
|
private
|
761
763
|
# +Array#flatten+ will call +#to_ary+ (recursively) on each of the elements of
|
762
764
|
# the array, and then rescues from the possible +NoMethodError+. If those elements are
|
@@ -771,16 +773,20 @@ module ActiveRecord
|
|
771
773
|
end
|
772
774
|
|
773
775
|
def init_internals
|
774
|
-
@primary_key = self.class.primary_key
|
775
776
|
@readonly = false
|
776
777
|
@previously_new_record = false
|
777
778
|
@destroyed = false
|
778
779
|
@marked_for_destruction = false
|
779
780
|
@destroyed_by_association = nil
|
780
781
|
@_start_transaction_state = nil
|
781
|
-
@strict_loading = self.class.strict_loading_by_default
|
782
782
|
|
783
|
-
self.class
|
783
|
+
klass = self.class
|
784
|
+
|
785
|
+
@primary_key = klass.primary_key
|
786
|
+
@strict_loading = klass.strict_loading_by_default
|
787
|
+
@strict_loading_mode = :all
|
788
|
+
|
789
|
+
klass.define_attribute_methods
|
784
790
|
end
|
785
791
|
|
786
792
|
def initialize_internals_callback
|
@@ -800,5 +806,24 @@ module ActiveRecord
|
|
800
806
|
def inspection_filter
|
801
807
|
self.class.inspection_filter
|
802
808
|
end
|
809
|
+
|
810
|
+
def inspect_with_attributes(attributes_to_list)
|
811
|
+
inspection = if @attributes
|
812
|
+
attributes_to_list.filter_map do |name|
|
813
|
+
name = name.to_s
|
814
|
+
if _has_attribute?(name)
|
815
|
+
"#{name}: #{attribute_for_inspect(name)}"
|
816
|
+
end
|
817
|
+
end.join(", ")
|
818
|
+
else
|
819
|
+
"not initialized"
|
820
|
+
end
|
821
|
+
|
822
|
+
"#<#{self.class} #{inspection}>"
|
823
|
+
end
|
824
|
+
|
825
|
+
def attributes_for_inspect
|
826
|
+
self.class.attributes_for_inspect == :all ? attribute_names : self.class.attributes_for_inspect
|
827
|
+
end
|
803
828
|
end
|
804
829
|
end
|