activerecord 6.1.7 → 7.1.5
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 +2030 -1020
- data/MIT-LICENSE +1 -1
- data/README.rdoc +18 -18
- data/lib/active_record/aggregations.rb +17 -14
- data/lib/active_record/association_relation.rb +1 -11
- data/lib/active_record/associations/association.rb +51 -19
- data/lib/active_record/associations/association_scope.rb +17 -12
- data/lib/active_record/associations/belongs_to_association.rb +28 -9
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
- data/lib/active_record/associations/builder/association.rb +11 -5
- data/lib/active_record/associations/builder/belongs_to.rb +40 -14
- data/lib/active_record/associations/builder/collection_association.rb +10 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
- data/lib/active_record/associations/builder/has_many.rb +3 -2
- data/lib/active_record/associations/builder/has_one.rb +2 -1
- data/lib/active_record/associations/builder/singular_association.rb +6 -2
- data/lib/active_record/associations/collection_association.rb +39 -35
- data/lib/active_record/associations/collection_proxy.rb +30 -15
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +28 -18
- 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 +3 -2
- data/lib/active_record/associations/join_dependency.rb +28 -20
- data/lib/active_record/associations/preloader/association.rb +210 -52
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +147 -0
- data/lib/active_record/associations/preloader/through_association.rb +50 -14
- data/lib/active_record/associations/preloader.rb +50 -121
- data/lib/active_record/associations/singular_association.rb +9 -3
- data/lib/active_record/associations/through_association.rb +25 -14
- data/lib/active_record/associations.rb +446 -306
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +1 -3
- data/lib/active_record/attribute_methods/before_type_cast.rb +24 -2
- data/lib/active_record/attribute_methods/dirty.rb +73 -22
- data/lib/active_record/attribute_methods/primary_key.rb +78 -26
- data/lib/active_record/attribute_methods/query.rb +31 -19
- data/lib/active_record/attribute_methods/read.rb +27 -12
- data/lib/active_record/attribute_methods/serialization.rb +194 -37
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +8 -3
- data/lib/active_record/attribute_methods/write.rb +12 -15
- data/lib/active_record/attribute_methods.rb +161 -40
- data/lib/active_record/attributes.rb +27 -38
- data/lib/active_record/autosave_association.rb +65 -31
- data/lib/active_record/base.rb +25 -2
- 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 +367 -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 +78 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +113 -597
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +172 -50
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -27
- data/lib/active_record/connection_adapters/abstract/quoting.rb +87 -73
- 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 +367 -141
- data/lib/active_record/connection_adapters/abstract/transaction.rb +281 -59
- data/lib/active_record/connection_adapters/abstract_adapter.rb +631 -150
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +317 -164
- 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 +25 -134
- data/lib/active_record/connection_adapters/mysql/quoting.rb +56 -25
- 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 +39 -14
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +151 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +112 -55
- data/lib/active_record/connection_adapters/pool_config.rb +20 -11
- 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 +89 -52
- 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/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.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +89 -56
- 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 +153 -3
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +397 -75
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +508 -246
- data/lib/active_record/connection_adapters/schema_cache.rb +319 -90
- data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +72 -53
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +37 -21
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +7 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -22
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +296 -104
- 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 +258 -0
- data/lib/active_record/connection_adapters.rb +9 -6
- data/lib/active_record/connection_handling.rb +108 -137
- data/lib/active_record/core.rb +242 -233
- data/lib/active_record/counter_cache.rb +52 -27
- data/lib/active_record/database_configurations/connection_url_resolver.rb +3 -2
- data/lib/active_record/database_configurations/database_config.rb +21 -12
- data/lib/active_record/database_configurations/hash_config.rb +88 -16
- data/lib/active_record/database_configurations/url_config.rb +18 -12
- data/lib/active_record/database_configurations.rb +95 -59
- data/lib/active_record/delegated_type.rb +66 -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 +1 -1
- 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 +155 -0
- data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
- data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
- data/lib/active_record/encryption/encryptor.rb +155 -0
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
- data/lib/active_record/encryption/errors.rb +15 -0
- data/lib/active_record/encryption/extended_deterministic_queries.rb +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_serializer.rb +92 -0
- data/lib/active_record/encryption/null_encryptor.rb +21 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
- data/lib/active_record/encryption/scheme.rb +100 -0
- data/lib/active_record/encryption.rb +58 -0
- data/lib/active_record/enum.rb +154 -63
- data/lib/active_record/errors.rb +172 -15
- data/lib/active_record/explain.rb +23 -3
- 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 +147 -86
- data/lib/active_record/future_result.rb +174 -0
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +81 -29
- data/lib/active_record/insert_all.rb +135 -22
- data/lib/active_record/integration.rb +11 -10
- data/lib/active_record/internal_metadata.rb +119 -33
- data/lib/active_record/legacy_yaml_adapter.rb +2 -39
- data/lib/active_record/locking/optimistic.rb +37 -22
- data/lib/active_record/locking/pessimistic.rb +15 -6
- data/lib/active_record/log_subscriber.rb +52 -19
- data/lib/active_record/marshalling.rb +59 -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 +112 -14
- data/lib/active_record/migration/compatibility.rb +233 -46
- data/lib/active_record/migration/default_strategy.rb +23 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +361 -173
- data/lib/active_record/model_schema.rb +125 -101
- data/lib/active_record/nested_attributes.rb +50 -20
- data/lib/active_record/no_touching.rb +3 -3
- data/lib/active_record/normalization.rb +167 -0
- data/lib/active_record/persistence.rb +409 -88
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +4 -22
- data/lib/active_record/query_logs.rb +174 -0
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +29 -6
- data/lib/active_record/railtie.rb +220 -44
- data/lib/active_record/railties/controller_runtime.rb +15 -10
- data/lib/active_record/railties/databases.rake +188 -252
- 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 +248 -81
- data/lib/active_record/relation/batches/batch_enumerator.rb +23 -7
- data/lib/active_record/relation/batches.rb +192 -63
- data/lib/active_record/relation/calculations.rb +246 -90
- data/lib/active_record/relation/delegation.rb +28 -14
- data/lib/active_record/relation/finder_methods.rb +108 -51
- data/lib/active_record/relation/merger.rb +22 -13
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +31 -3
- 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 +27 -20
- data/lib/active_record/relation/query_attribute.rb +30 -12
- data/lib/active_record/relation/query_methods.rb +670 -129
- data/lib/active_record/relation/record_fetch_warning.rb +7 -9
- data/lib/active_record/relation/spawn_methods.rb +20 -3
- data/lib/active_record/relation/where_clause.rb +10 -19
- data/lib/active_record/relation.rb +287 -120
- data/lib/active_record/result.rb +37 -11
- data/lib/active_record/runtime_registry.rb +32 -13
- data/lib/active_record/sanitization.rb +65 -20
- data/lib/active_record/schema.rb +36 -22
- data/lib/active_record/schema_dumper.rb +73 -24
- data/lib/active_record/schema_migration.rb +68 -33
- 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 +10 -8
- data/lib/active_record/store.rb +10 -10
- data/lib/active_record/suppressor.rb +13 -15
- data/lib/active_record/table_metadata.rb +16 -3
- data/lib/active_record/tasks/database_tasks.rb +251 -140
- 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 +15 -7
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +117 -96
- data/lib/active_record/timestamp.rb +32 -19
- data/lib/active_record/token_for.rb +113 -0
- data/lib/active_record/touch_later.rb +11 -6
- data/lib/active_record/transactions.rb +48 -27
- data/lib/active_record/translation.rb +3 -3
- 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 -5
- 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/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +4 -4
- 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 +51 -6
- data/lib/active_record/validations.rb +8 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +335 -32
- data/lib/arel/attributes/attribute.rb +0 -8
- data/lib/arel/crud.rb +28 -22
- data/lib/arel/delete_manager.rb +18 -4
- data/lib/arel/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/and.rb +4 -0
- data/lib/arel/nodes/binary.rb +6 -1
- data/lib/arel/nodes/bound_sql_literal.rb +61 -0
- data/lib/arel/nodes/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/node.rb +111 -2
- 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 +6 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes/update_statement.rb +8 -3
- data/lib/arel/nodes.rb +5 -0
- data/lib/arel/predications.rb +13 -3
- data/lib/arel/select_manager.rb +10 -4
- data/lib/arel/table.rb +9 -6
- data/lib/arel/tree_manager.rb +5 -13
- data/lib/arel/update_manager.rb +18 -4
- data/lib/arel/visitors/dot.rb +80 -90
- data/lib/arel/visitors/mysql.rb +16 -3
- data/lib/arel/visitors/postgresql.rb +0 -10
- data/lib/arel/visitors/to_sql.rb +141 -20
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +18 -3
- 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.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 +96 -16
- 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,19 +54,19 @@ 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)
|
@@ -72,80 +80,19 @@ module ActiveRecord
|
|
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
|
-
|
145
|
-
|
146
|
-
mattr_accessor :reading_role, instance_accessor: false, default: :reading
|
93
|
+
class_attribute :has_many_inversing, instance_accessor: false, default: false
|
147
94
|
|
148
|
-
|
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,35 @@ 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
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
105
|
+
def self.application_record_class? # :nodoc:
|
106
|
+
if ActiveRecord.application_record_class
|
107
|
+
self == ActiveRecord.application_record_class
|
108
|
+
else
|
109
|
+
if defined?(ApplicationRecord) && self == ApplicationRecord
|
110
|
+
true
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
165
114
|
|
166
115
|
self.filter_attributes = []
|
167
116
|
|
168
117
|
def self.connection_handler
|
169
|
-
|
118
|
+
ActiveSupport::IsolatedExecutionState[:active_record_connection_handler] || default_connection_handler
|
170
119
|
end
|
171
120
|
|
172
121
|
def self.connection_handler=(handler)
|
173
|
-
|
122
|
+
ActiveSupport::IsolatedExecutionState[:active_record_connection_handler] = handler
|
174
123
|
end
|
175
124
|
|
176
|
-
def self.
|
177
|
-
|
178
|
-
raise NotImplementedError, "The new connection handling does not support accessing multiple connection handlers."
|
179
|
-
end
|
180
|
-
|
181
|
-
@@connection_handlers ||= {}
|
125
|
+
def self.asynchronous_queries_session # :nodoc:
|
126
|
+
asynchronous_queries_tracker.current_session
|
182
127
|
end
|
183
128
|
|
184
|
-
def self.
|
185
|
-
|
186
|
-
|
187
|
-
end
|
188
|
-
|
189
|
-
@@connection_handlers = handlers
|
129
|
+
def self.asynchronous_queries_tracker # :nodoc:
|
130
|
+
ActiveSupport::IsolatedExecutionState[:active_record_asynchronous_queries_tracker] ||= \
|
131
|
+
AsynchronousQueriesTracker.new
|
190
132
|
end
|
191
133
|
|
192
134
|
# Returns the symbol representing the current connected role.
|
@@ -199,16 +141,12 @@ module ActiveRecord
|
|
199
141
|
# ActiveRecord::Base.current_role #=> :reading
|
200
142
|
# end
|
201
143
|
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
|
144
|
+
connected_to_stack.reverse_each do |hash|
|
145
|
+
return hash[:role] if hash[:role] && hash[:klasses].include?(Base)
|
146
|
+
return hash[:role] if hash[:role] && hash[:klasses].include?(connection_class_for_self)
|
211
147
|
end
|
148
|
+
|
149
|
+
default_role
|
212
150
|
end
|
213
151
|
|
214
152
|
# Returns the symbol representing the current connected shard.
|
@@ -223,7 +161,7 @@ module ActiveRecord
|
|
223
161
|
def self.current_shard
|
224
162
|
connected_to_stack.reverse_each do |hash|
|
225
163
|
return hash[:shard] if hash[:shard] && hash[:klasses].include?(Base)
|
226
|
-
return hash[:shard] if hash[:shard] && hash[:klasses].include?(
|
164
|
+
return hash[:shard] if hash[:shard] && hash[:klasses].include?(connection_class_for_self)
|
227
165
|
end
|
228
166
|
|
229
167
|
default_shard
|
@@ -240,24 +178,20 @@ module ActiveRecord
|
|
240
178
|
# ActiveRecord::Base.current_preventing_writes #=> false
|
241
179
|
# end
|
242
180
|
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
|
181
|
+
connected_to_stack.reverse_each do |hash|
|
182
|
+
return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(Base)
|
183
|
+
return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(connection_class_for_self)
|
252
184
|
end
|
185
|
+
|
186
|
+
false
|
253
187
|
end
|
254
188
|
|
255
189
|
def self.connected_to_stack # :nodoc:
|
256
|
-
if connected_to_stack =
|
190
|
+
if connected_to_stack = ActiveSupport::IsolatedExecutionState[:active_record_connected_to_stack]
|
257
191
|
connected_to_stack
|
258
192
|
else
|
259
193
|
connected_to_stack = Concurrent::Array.new
|
260
|
-
|
194
|
+
ActiveSupport::IsolatedExecutionState[:active_record_connected_to_stack] = connected_to_stack
|
261
195
|
connected_to_stack
|
262
196
|
end
|
263
197
|
end
|
@@ -266,7 +200,7 @@ module ActiveRecord
|
|
266
200
|
@connection_class = b
|
267
201
|
end
|
268
202
|
|
269
|
-
def self.connection_class # :nodoc
|
203
|
+
def self.connection_class # :nodoc:
|
270
204
|
@connection_class ||= false
|
271
205
|
end
|
272
206
|
|
@@ -274,7 +208,7 @@ module ActiveRecord
|
|
274
208
|
self.connection_class
|
275
209
|
end
|
276
210
|
|
277
|
-
def self.
|
211
|
+
def self.connection_class_for_self # :nodoc:
|
278
212
|
klass = self
|
279
213
|
|
280
214
|
until klass == Base
|
@@ -285,22 +219,14 @@ module ActiveRecord
|
|
285
219
|
klass
|
286
220
|
end
|
287
221
|
|
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
222
|
self.default_connection_handler = ConnectionAdapters::ConnectionHandler.new
|
297
|
-
self.default_role = writing_role
|
223
|
+
self.default_role = ActiveRecord.writing_role
|
298
224
|
self.default_shard = :default
|
299
225
|
|
300
226
|
def self.strict_loading_violation!(owner:, reflection:) # :nodoc:
|
301
|
-
case action_on_strict_loading_violation
|
227
|
+
case ActiveRecord.action_on_strict_loading_violation
|
302
228
|
when :raise
|
303
|
-
message =
|
229
|
+
message = reflection.strict_loading_violation_message(owner)
|
304
230
|
raise ActiveRecord::StrictLoadingViolationError.new(message)
|
305
231
|
when :log
|
306
232
|
name = "strict_loading_violation.active_record"
|
@@ -314,19 +240,6 @@ module ActiveRecord
|
|
314
240
|
@find_by_statement_cache = { true => Concurrent::Map.new, false => Concurrent::Map.new }
|
315
241
|
end
|
316
242
|
|
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
243
|
def find(*ids) # :nodoc:
|
331
244
|
# We don't have cache keys for this stuff yet
|
332
245
|
return super unless ids.length == 1
|
@@ -336,14 +249,8 @@ module ActiveRecord
|
|
336
249
|
|
337
250
|
return super if StatementCache.unsupported_value?(id)
|
338
251
|
|
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))
|
252
|
+
cached_find_by([primary_key], [id]) ||
|
253
|
+
raise(RecordNotFound.new("Couldn't find #{name} with '#{primary_key}'=#{id}", name, primary_key, id))
|
347
254
|
end
|
348
255
|
|
349
256
|
def find_by(*args) # :nodoc:
|
@@ -365,31 +272,36 @@ module ActiveRecord
|
|
365
272
|
elsif reflection.belongs_to? && !reflection.polymorphic?
|
366
273
|
key = reflection.join_foreign_key
|
367
274
|
pkey = reflection.join_primary_key
|
368
|
-
|
275
|
+
|
276
|
+
if pkey.is_a?(Array)
|
277
|
+
if pkey.all? { |attribute| value.respond_to?(attribute) }
|
278
|
+
value = pkey.map do |attribute|
|
279
|
+
if attribute == "id"
|
280
|
+
value.id_value
|
281
|
+
else
|
282
|
+
value.public_send(attribute)
|
283
|
+
end
|
284
|
+
end
|
285
|
+
composite_primary_key = true
|
286
|
+
end
|
287
|
+
else
|
288
|
+
value = value.public_send(pkey) if value.respond_to?(pkey)
|
289
|
+
end
|
369
290
|
end
|
370
291
|
|
371
|
-
if !
|
292
|
+
if !composite_primary_key &&
|
293
|
+
(!columns_hash.key?(key) || StatementCache.unsupported_value?(value))
|
372
294
|
return super
|
373
295
|
end
|
374
296
|
|
375
297
|
h[key] = value
|
376
298
|
end
|
377
299
|
|
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
|
300
|
+
cached_find_by(hash.keys, hash.values)
|
389
301
|
end
|
390
302
|
|
391
303
|
def find_by!(*args) # :nodoc:
|
392
|
-
find_by(*args) ||
|
304
|
+
find_by(*args) || where(*args).raise_record_not_found_exception!
|
393
305
|
end
|
394
306
|
|
395
307
|
def initialize_generated_modules # :nodoc:
|
@@ -408,10 +320,10 @@ module ActiveRecord
|
|
408
320
|
|
409
321
|
# Returns columns which shouldn't be exposed while calling +#inspect+.
|
410
322
|
def filter_attributes
|
411
|
-
if
|
412
|
-
@filter_attributes
|
413
|
-
else
|
323
|
+
if @filter_attributes.nil?
|
414
324
|
superclass.filter_attributes
|
325
|
+
else
|
326
|
+
@filter_attributes
|
415
327
|
end
|
416
328
|
end
|
417
329
|
|
@@ -422,19 +334,19 @@ module ActiveRecord
|
|
422
334
|
end
|
423
335
|
|
424
336
|
def inspection_filter # :nodoc:
|
425
|
-
if
|
337
|
+
if @filter_attributes.nil?
|
338
|
+
superclass.inspection_filter
|
339
|
+
else
|
426
340
|
@inspection_filter ||= begin
|
427
341
|
mask = InspectionMask.new(ActiveSupport::ParameterFilter::FILTERED)
|
428
342
|
ActiveSupport::ParameterFilter.new(@filter_attributes, mask: mask)
|
429
343
|
end
|
430
|
-
else
|
431
|
-
superclass.inspection_filter
|
432
344
|
end
|
433
345
|
end
|
434
346
|
|
435
347
|
# Returns a string like 'Post(id:integer, title:string, body:text)'
|
436
348
|
def inspect # :nodoc:
|
437
|
-
if self == Base
|
349
|
+
if self == Base || singleton_class?
|
438
350
|
super
|
439
351
|
elsif abstract_class?
|
440
352
|
"#{super}(abstract)"
|
@@ -448,25 +360,11 @@ module ActiveRecord
|
|
448
360
|
end
|
449
361
|
end
|
450
362
|
|
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
|
363
|
+
# Returns an instance of +Arel::Table+ loaded with the current table name.
|
461
364
|
def arel_table # :nodoc:
|
462
365
|
@arel_table ||= Arel::Table.new(table_name, klass: self)
|
463
366
|
end
|
464
367
|
|
465
|
-
def arel_attribute(name, table = arel_table) # :nodoc:
|
466
|
-
table[name]
|
467
|
-
end
|
468
|
-
deprecate :arel_attribute
|
469
|
-
|
470
368
|
def predicate_builder # :nodoc:
|
471
369
|
@predicate_builder ||= PredicateBuilder.new(table_metadata)
|
472
370
|
end
|
@@ -475,16 +373,34 @@ module ActiveRecord
|
|
475
373
|
TypeCaster::Map.new(self)
|
476
374
|
end
|
477
375
|
|
478
|
-
def _internal? # :nodoc:
|
479
|
-
false
|
480
|
-
end
|
481
|
-
|
482
376
|
def cached_find_by_statement(key, &block) # :nodoc:
|
483
377
|
cache = @find_by_statement_cache[connection.prepared_statements]
|
484
378
|
cache.compute_if_absent(key) { StatementCache.create(connection, &block) }
|
485
379
|
end
|
486
380
|
|
487
381
|
private
|
382
|
+
def inherited(subclass)
|
383
|
+
super
|
384
|
+
|
385
|
+
# initialize cache at class definition for thread safety
|
386
|
+
subclass.initialize_find_by_cache
|
387
|
+
unless subclass.base_class?
|
388
|
+
klass = self
|
389
|
+
until klass.base_class?
|
390
|
+
klass.initialize_find_by_cache
|
391
|
+
klass = klass.superclass
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
subclass.class_eval do
|
396
|
+
@arel_table = nil
|
397
|
+
@predicate_builder = nil
|
398
|
+
@inspection_filter = nil
|
399
|
+
@filter_attributes ||= nil
|
400
|
+
@generated_association_methods ||= nil
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
488
404
|
def relation
|
489
405
|
relation = Relation.create(self)
|
490
406
|
|
@@ -498,6 +414,25 @@ module ActiveRecord
|
|
498
414
|
def table_metadata
|
499
415
|
TableMetadata.new(self, arel_table)
|
500
416
|
end
|
417
|
+
|
418
|
+
def cached_find_by(keys, values)
|
419
|
+
statement = cached_find_by_statement(keys) { |params|
|
420
|
+
wheres = keys.index_with do |key|
|
421
|
+
if key.is_a?(Array)
|
422
|
+
[key.map { params.bind }]
|
423
|
+
else
|
424
|
+
params.bind
|
425
|
+
end
|
426
|
+
end
|
427
|
+
where(wheres).limit(1)
|
428
|
+
}
|
429
|
+
|
430
|
+
begin
|
431
|
+
statement.execute(values.flatten, connection).first
|
432
|
+
rescue TypeError
|
433
|
+
raise ActiveRecord::StatementInvalid
|
434
|
+
end
|
435
|
+
end
|
501
436
|
end
|
502
437
|
|
503
438
|
# New objects can be instantiated as either empty (pass no construction parameter) or pre-set with
|
@@ -505,7 +440,7 @@ module ActiveRecord
|
|
505
440
|
# In both instances, valid attribute keys are determined by the column names of the associated table --
|
506
441
|
# hence you can't have attributes that aren't part of the table columns.
|
507
442
|
#
|
508
|
-
# ==== Example
|
443
|
+
# ==== Example
|
509
444
|
# # Instantiates a single new object
|
510
445
|
# User.new(first_name: 'Jamie')
|
511
446
|
def initialize(attributes = nil)
|
@@ -536,7 +471,7 @@ module ActiveRecord
|
|
536
471
|
# post.init_with(coder)
|
537
472
|
# post.title # => 'hello world'
|
538
473
|
def init_with(coder, &block)
|
539
|
-
coder = LegacyYamlAdapter.convert(
|
474
|
+
coder = LegacyYamlAdapter.convert(coder)
|
540
475
|
attributes = self.class.yaml_encoder.decode(coder)
|
541
476
|
init_with_attributes(attributes, coder["new_record"], &block)
|
542
477
|
end
|
@@ -583,12 +518,17 @@ module ActiveRecord
|
|
583
518
|
# only, not its associations. The extent of a "deep" copy is application
|
584
519
|
# specific and is therefore left to the application to implement according
|
585
520
|
# to its need.
|
586
|
-
# The dup method does not preserve the timestamps (created|updated)_(at|on)
|
521
|
+
# The dup method does not preserve the timestamps (created|updated)_(at|on)
|
522
|
+
# and locking column.
|
587
523
|
|
588
524
|
##
|
589
525
|
def initialize_dup(other) # :nodoc:
|
590
526
|
@attributes = @attributes.deep_dup
|
591
|
-
|
527
|
+
if self.class.composite_primary_key?
|
528
|
+
@primary_key.each { |key| @attributes.reset(key) }
|
529
|
+
else
|
530
|
+
@attributes.reset(@primary_key)
|
531
|
+
end
|
592
532
|
|
593
533
|
_run_initialize_callbacks
|
594
534
|
|
@@ -618,6 +558,35 @@ module ActiveRecord
|
|
618
558
|
coder["active_record_yaml_version"] = 2
|
619
559
|
end
|
620
560
|
|
561
|
+
##
|
562
|
+
# :method: slice
|
563
|
+
#
|
564
|
+
# :call-seq: slice(*methods)
|
565
|
+
#
|
566
|
+
# Returns a hash of the given methods with their names as keys and returned
|
567
|
+
# values as values.
|
568
|
+
#
|
569
|
+
# topic = Topic.new(title: "Budget", author_name: "Jason")
|
570
|
+
# topic.slice(:title, :author_name)
|
571
|
+
# => { "title" => "Budget", "author_name" => "Jason" }
|
572
|
+
#
|
573
|
+
#--
|
574
|
+
# Implemented by ActiveModel::Access#slice.
|
575
|
+
|
576
|
+
##
|
577
|
+
# :method: values_at
|
578
|
+
#
|
579
|
+
# :call-seq: values_at(*methods)
|
580
|
+
#
|
581
|
+
# Returns an array of the values returned by the given methods.
|
582
|
+
#
|
583
|
+
# topic = Topic.new(title: "Budget", author_name: "Jason")
|
584
|
+
# topic.values_at(:title, :author_name)
|
585
|
+
# => ["Budget", "Jason"]
|
586
|
+
#
|
587
|
+
#--
|
588
|
+
# Implemented by ActiveModel::Access#values_at.
|
589
|
+
|
621
590
|
# Returns true if +comparison_object+ is the same exact object, or +comparison_object+
|
622
591
|
# is of the same type and +self+ has an ID and it is equal to +comparison_object.id+.
|
623
592
|
#
|
@@ -630,7 +599,7 @@ module ActiveRecord
|
|
630
599
|
def ==(comparison_object)
|
631
600
|
super ||
|
632
601
|
comparison_object.instance_of?(self.class) &&
|
633
|
-
|
602
|
+
primary_key_values_present? &&
|
634
603
|
comparison_object.id == id
|
635
604
|
end
|
636
605
|
alias :eql? :==
|
@@ -638,7 +607,9 @@ module ActiveRecord
|
|
638
607
|
# Delegates to id in order to allow two records of the same type and id to work with something like:
|
639
608
|
# [ Person.find(1), Person.find(2), Person.find(3) ] & [ Person.find(1), Person.find(4) ] # => [ Person.find(1) ]
|
640
609
|
def hash
|
641
|
-
|
610
|
+
id = self.id
|
611
|
+
|
612
|
+
if primary_key_values_present?
|
642
613
|
self.class.hash ^ id.hash
|
643
614
|
else
|
644
615
|
super
|
@@ -689,14 +660,57 @@ module ActiveRecord
|
|
689
660
|
# if the record tries to lazily load an association.
|
690
661
|
#
|
691
662
|
# user = User.first
|
692
|
-
# user.strict_loading!
|
663
|
+
# user.strict_loading! # => true
|
664
|
+
# user.address.city
|
665
|
+
# => ActiveRecord::StrictLoadingViolationError
|
693
666
|
# user.comments.to_a
|
694
667
|
# => ActiveRecord::StrictLoadingViolationError
|
695
|
-
|
696
|
-
|
668
|
+
#
|
669
|
+
# ==== Parameters
|
670
|
+
#
|
671
|
+
# * +value+ - Boolean specifying whether to enable or disable strict loading.
|
672
|
+
# * <tt>:mode</tt> - Symbol specifying strict loading mode. Defaults to :all. Using
|
673
|
+
# :n_plus_one_only mode will only raise an error if an association that
|
674
|
+
# will lead to an n plus one query is lazily loaded.
|
675
|
+
#
|
676
|
+
# ==== Examples
|
677
|
+
#
|
678
|
+
# user = User.first
|
679
|
+
# user.strict_loading!(false) # => false
|
680
|
+
# user.address.city # => "Tatooine"
|
681
|
+
# user.comments.to_a # => [#<Comment:0x00...]
|
682
|
+
#
|
683
|
+
# user.strict_loading!(mode: :n_plus_one_only)
|
684
|
+
# user.address.city # => "Tatooine"
|
685
|
+
# user.comments.to_a # => [#<Comment:0x00...]
|
686
|
+
# user.comments.first.ratings.to_a
|
687
|
+
# => ActiveRecord::StrictLoadingViolationError
|
688
|
+
def strict_loading!(value = true, mode: :all)
|
689
|
+
unless [:all, :n_plus_one_only].include?(mode)
|
690
|
+
raise ArgumentError, "The :mode option must be one of [:all, :n_plus_one_only] but #{mode.inspect} was provided."
|
691
|
+
end
|
692
|
+
|
693
|
+
@strict_loading_mode = mode
|
694
|
+
@strict_loading = value
|
695
|
+
end
|
696
|
+
|
697
|
+
attr_reader :strict_loading_mode
|
698
|
+
|
699
|
+
# Returns +true+ if the record uses strict_loading with +:n_plus_one_only+ mode enabled.
|
700
|
+
def strict_loading_n_plus_one_only?
|
701
|
+
@strict_loading_mode == :n_plus_one_only
|
702
|
+
end
|
703
|
+
|
704
|
+
# Returns +true+ if the record uses strict_loading with +:all+ mode enabled.
|
705
|
+
def strict_loading_all?
|
706
|
+
@strict_loading_mode == :all
|
697
707
|
end
|
698
708
|
|
699
709
|
# Marks this record as read only.
|
710
|
+
#
|
711
|
+
# customer = Customer.first
|
712
|
+
# customer.readonly!
|
713
|
+
# customer.save # Raises an ActiveRecord::ReadOnlyRecord
|
700
714
|
def readonly!
|
701
715
|
@readonly = true
|
702
716
|
end
|
@@ -710,11 +724,11 @@ module ActiveRecord
|
|
710
724
|
# We check defined?(@attributes) not to issue warnings if the object is
|
711
725
|
# allocated but not initialized.
|
712
726
|
inspection = if defined?(@attributes) && @attributes
|
713
|
-
|
727
|
+
attribute_names.filter_map do |name|
|
714
728
|
if _has_attribute?(name)
|
715
729
|
"#{name}: #{attribute_for_inspect(name)}"
|
716
730
|
end
|
717
|
-
end.
|
731
|
+
end.join(", ")
|
718
732
|
else
|
719
733
|
"not initialized"
|
720
734
|
end
|
@@ -747,16 +761,6 @@ module ActiveRecord
|
|
747
761
|
end
|
748
762
|
end
|
749
763
|
|
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
764
|
private
|
761
765
|
# +Array#flatten+ will call +#to_ary+ (recursively) on each of the elements of
|
762
766
|
# the array, and then rescues from the possible +NoMethodError+. If those elements are
|
@@ -771,16 +775,21 @@ module ActiveRecord
|
|
771
775
|
end
|
772
776
|
|
773
777
|
def init_internals
|
774
|
-
@primary_key = self.class.primary_key
|
775
778
|
@readonly = false
|
776
779
|
@previously_new_record = false
|
777
780
|
@destroyed = false
|
778
781
|
@marked_for_destruction = false
|
779
782
|
@destroyed_by_association = nil
|
780
783
|
@_start_transaction_state = nil
|
781
|
-
@strict_loading = self.class.strict_loading_by_default
|
782
784
|
|
783
|
-
self.class
|
785
|
+
klass = self.class
|
786
|
+
|
787
|
+
@primary_key = klass.primary_key
|
788
|
+
@strict_loading = klass.strict_loading_by_default
|
789
|
+
@strict_loading_mode = :all
|
790
|
+
|
791
|
+
klass.define_attribute_methods
|
792
|
+
klass.generate_alias_attributes
|
784
793
|
end
|
785
794
|
|
786
795
|
def initialize_internals_callback
|