activerecord 7.0.8 → 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 +530 -2004
- data/MIT-LICENSE +1 -1
- data/README.rdoc +29 -29
- data/examples/performance.rb +2 -2
- data/lib/active_record/aggregations.rb +16 -13
- data/lib/active_record/association_relation.rb +2 -2
- data/lib/active_record/associations/alias_tracker.rb +25 -19
- data/lib/active_record/associations/association.rb +35 -12
- data/lib/active_record/associations/association_scope.rb +16 -9
- data/lib/active_record/associations/belongs_to_association.rb +23 -8
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
- data/lib/active_record/associations/builder/association.rb +3 -3
- data/lib/active_record/associations/builder/belongs_to.rb +22 -8
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -7
- data/lib/active_record/associations/builder/has_many.rb +3 -4
- data/lib/active_record/associations/builder/has_one.rb +3 -4
- data/lib/active_record/associations/builder/singular_association.rb +4 -0
- data/lib/active_record/associations/collection_association.rb +26 -14
- data/lib/active_record/associations/collection_proxy.rb +29 -11
- 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 +21 -14
- data/lib/active_record/associations/has_many_through_association.rb +10 -6
- data/lib/active_record/associations/has_one_association.rb +10 -3
- data/lib/active_record/associations/join_dependency/join_association.rb +27 -25
- data/lib/active_record/associations/join_dependency.rb +5 -5
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +33 -8
- data/lib/active_record/associations/preloader/branch.rb +7 -1
- data/lib/active_record/associations/preloader/through_association.rb +1 -3
- data/lib/active_record/associations/preloader.rb +13 -10
- data/lib/active_record/associations/singular_association.rb +7 -1
- data/lib/active_record/associations/through_association.rb +22 -11
- data/lib/active_record/associations.rb +328 -471
- data/lib/active_record/attribute_assignment.rb +1 -13
- data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +53 -35
- data/lib/active_record/attribute_methods/primary_key.rb +45 -25
- data/lib/active_record/attribute_methods/query.rb +28 -16
- data/lib/active_record/attribute_methods/read.rb +8 -7
- data/lib/active_record/attribute_methods/serialization.rb +131 -32
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +7 -6
- data/lib/active_record/attribute_methods/write.rb +6 -6
- data/lib/active_record/attribute_methods.rb +148 -33
- data/lib/active_record/attributes.rb +58 -45
- data/lib/active_record/autosave_association.rb +69 -37
- data/lib/active_record/base.rb +9 -5
- data/lib/active_record/callbacks.rb +10 -24
- data/lib/active_record/coders/column_serializer.rb +61 -0
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +70 -42
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +123 -131
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +4 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +317 -88
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +160 -45
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +188 -63
- data/lib/active_record/connection_adapters/abstract/quoting.rb +72 -63
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +18 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +137 -11
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +306 -128
- data/lib/active_record/connection_adapters/abstract/transaction.rb +367 -75
- data/lib/active_record/connection_adapters/abstract_adapter.rb +510 -111
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +274 -125
- data/lib/active_record/connection_adapters/column.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +26 -139
- data/lib/active_record/connection_adapters/mysql/quoting.rb +53 -54
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +6 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +25 -13
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +101 -68
- data/lib/active_record/connection_adapters/pool_config.rb +20 -10
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +14 -3
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +100 -43
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
- 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 +11 -2
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +65 -61
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +3 -9
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +151 -2
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +53 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +368 -63
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +364 -198
- data/lib/active_record/connection_adapters/schema_cache.rb +302 -79
- data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +60 -43
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +45 -46
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +14 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +50 -8
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +290 -110
- 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 +124 -1
- data/lib/active_record/connection_handling.rb +96 -104
- data/lib/active_record/core.rb +217 -174
- data/lib/active_record/counter_cache.rb +68 -34
- data/lib/active_record/database_configurations/connection_url_resolver.rb +7 -2
- data/lib/active_record/database_configurations/database_config.rb +26 -5
- data/lib/active_record/database_configurations/hash_config.rb +52 -34
- data/lib/active_record/database_configurations/url_config.rb +37 -12
- data/lib/active_record/database_configurations.rb +87 -34
- data/lib/active_record/delegated_type.rb +39 -10
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +3 -1
- data/lib/active_record/dynamic_matchers.rb +2 -2
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +4 -1
- data/lib/active_record/encryption/config.rb +25 -1
- data/lib/active_record/encryption/configurable.rb +12 -19
- data/lib/active_record/encryption/context.rb +10 -3
- data/lib/active_record/encryption/contexts.rb +5 -1
- data/lib/active_record/encryption/derived_secret_key_provider.rb +8 -2
- data/lib/active_record/encryption/encryptable_record.rb +44 -20
- data/lib/active_record/encryption/encrypted_attribute_type.rb +45 -10
- data/lib/active_record/encryption/encryptor.rb +17 -2
- data/lib/active_record/encryption/extended_deterministic_queries.rb +66 -69
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +3 -3
- data/lib/active_record/encryption/key_generator.rb +12 -1
- data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +6 -0
- data/lib/active_record/encryption/null_encryptor.rb +4 -0
- data/lib/active_record/encryption/properties.rb +3 -3
- data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
- data/lib/active_record/encryption/scheme.rb +22 -21
- data/lib/active_record/encryption.rb +1 -0
- data/lib/active_record/enum.rb +122 -29
- data/lib/active_record/errors.rb +151 -31
- data/lib/active_record/explain.rb +21 -12
- data/lib/active_record/fixture_set/model_metadata.rb +14 -4
- data/lib/active_record/fixture_set/render_context.rb +2 -0
- data/lib/active_record/fixture_set/table_row.rb +29 -8
- data/lib/active_record/fixtures.rb +167 -97
- data/lib/active_record/future_result.rb +47 -8
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +34 -18
- data/lib/active_record/insert_all.rb +72 -22
- data/lib/active_record/integration.rb +11 -8
- data/lib/active_record/internal_metadata.rb +124 -20
- data/lib/active_record/locking/optimistic.rb +8 -7
- data/lib/active_record/locking/pessimistic.rb +5 -2
- data/lib/active_record/log_subscriber.rb +18 -22
- data/lib/active_record/marshalling.rb +56 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +4 -0
- data/lib/active_record/middleware/database_selector.rb +6 -8
- data/lib/active_record/middleware/shard_selector.rb +3 -1
- data/lib/active_record/migration/command_recorder.rb +106 -8
- data/lib/active_record/migration/compatibility.rb +147 -5
- 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/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +234 -117
- data/lib/active_record/model_schema.rb +88 -103
- data/lib/active_record/nested_attributes.rb +35 -9
- data/lib/active_record/normalization.rb +163 -0
- data/lib/active_record/persistence.rb +168 -339
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +19 -25
- data/lib/active_record/query_logs.rb +92 -52
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +33 -8
- data/lib/active_record/railtie.rb +135 -86
- data/lib/active_record/railties/controller_runtime.rb +22 -7
- data/lib/active_record/railties/databases.rake +145 -154
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +32 -5
- data/lib/active_record/reflection.rb +259 -68
- data/lib/active_record/relation/batches/batch_enumerator.rb +20 -5
- data/lib/active_record/relation/batches.rb +196 -61
- data/lib/active_record/relation/calculations.rb +249 -92
- data/lib/active_record/relation/delegation.rb +30 -19
- data/lib/active_record/relation/finder_methods.rb +93 -18
- data/lib/active_record/relation/merger.rb +6 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +18 -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 +28 -16
- data/lib/active_record/relation/query_attribute.rb +2 -1
- data/lib/active_record/relation/query_methods.rb +548 -94
- data/lib/active_record/relation/record_fetch_warning.rb +3 -0
- data/lib/active_record/relation/spawn_methods.rb +5 -4
- data/lib/active_record/relation/where_clause.rb +7 -19
- data/lib/active_record/relation.rb +580 -90
- data/lib/active_record/result.rb +49 -48
- data/lib/active_record/runtime_registry.rb +63 -1
- data/lib/active_record/sanitization.rb +70 -25
- data/lib/active_record/schema.rb +8 -7
- data/lib/active_record/schema_dumper.rb +63 -14
- data/lib/active_record/schema_migration.rb +75 -24
- data/lib/active_record/scoping/default.rb +15 -5
- data/lib/active_record/scoping/named.rb +2 -2
- data/lib/active_record/scoping.rb +2 -1
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/signed_id.rb +27 -6
- data/lib/active_record/statement_cache.rb +7 -7
- data/lib/active_record/store.rb +8 -8
- data/lib/active_record/suppressor.rb +3 -1
- data/lib/active_record/table_metadata.rb +1 -1
- data/lib/active_record/tasks/database_tasks.rb +180 -119
- data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
- data/lib/active_record/tasks/postgresql_database_tasks.rb +16 -13
- data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -7
- data/lib/active_record/test_fixtures.rb +170 -155
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +31 -17
- 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 +106 -24
- data/lib/active_record/translation.rb +0 -2
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +1 -3
- data/lib/active_record/type/time.rb +4 -0
- 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 +9 -3
- 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 +60 -11
- data/lib/active_record/validations.rb +12 -5
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +247 -33
- data/lib/arel/alias_predication.rb +1 -1
- 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/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/nodes/binary.rb +6 -7
- data/lib/arel/nodes/bound_sql_literal.rb +65 -0
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/homogeneous_in.rb +1 -9
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/{and.rb → nary.rb} +5 -2
- data/lib/arel/nodes/node.rb +115 -5
- data/lib/arel/nodes/sql_literal.rb +13 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes.rb +6 -2
- data/lib/arel/predications.rb +3 -1
- data/lib/arel/select_manager.rb +1 -1
- data/lib/arel/table.rb +9 -5
- data/lib/arel/tree_manager.rb +8 -3
- data/lib/arel/update_manager.rb +2 -1
- data/lib/arel/visitors/dot.rb +1 -0
- data/lib/arel/visitors/mysql.rb +17 -5
- data/lib/arel/visitors/postgresql.rb +1 -12
- data/lib/arel/visitors/to_sql.rb +112 -34
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +21 -3
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- 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
- metadata +56 -14
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -63
data/lib/active_record/core.rb
CHANGED
|
@@ -1,29 +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
|
-
#
|
|
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.
|
|
20
22
|
class_attribute :logger, instance_writer: false
|
|
21
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
|
|
35
|
+
|
|
36
|
+
singleton_class.alias_method :destroy_association_async_job=, :_destroy_association_async_job=
|
|
37
|
+
delegate :destroy_association_async_job, to: :class
|
|
38
|
+
|
|
22
39
|
##
|
|
23
40
|
# :singleton-method:
|
|
24
41
|
#
|
|
25
|
-
# Specifies the
|
|
26
|
-
|
|
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
|
|
27
48
|
|
|
28
49
|
##
|
|
29
50
|
# Contains the database configuration - as is typically stored in config/database.yml -
|
|
@@ -33,26 +54,26 @@ module ActiveRecord
|
|
|
33
54
|
#
|
|
34
55
|
# development:
|
|
35
56
|
# adapter: sqlite3
|
|
36
|
-
# database:
|
|
57
|
+
# database: storage/development.sqlite3
|
|
37
58
|
#
|
|
38
59
|
# production:
|
|
39
60
|
# adapter: sqlite3
|
|
40
|
-
# database:
|
|
61
|
+
# database: storage/production.sqlite3
|
|
41
62
|
#
|
|
42
63
|
# ...would result in ActiveRecord::Base.configurations to look like this:
|
|
43
64
|
#
|
|
44
65
|
# #<ActiveRecord::DatabaseConfigurations:0x00007fd1acbdf800 @configurations=[
|
|
45
66
|
# #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10 @env_name="development",
|
|
46
|
-
# @name="primary", @config={adapter: "sqlite3", database: "
|
|
67
|
+
# @name="primary", @config={adapter: "sqlite3", database: "storage/development.sqlite3"}>,
|
|
47
68
|
# #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbdea90 @env_name="production",
|
|
48
|
-
# @name="primary", @config={adapter: "sqlite3", database: "
|
|
69
|
+
# @name="primary", @config={adapter: "sqlite3", database: "storage/production.sqlite3"}>
|
|
49
70
|
# ]>
|
|
50
71
|
def self.configurations=(config)
|
|
51
72
|
@@configurations = ActiveRecord::DatabaseConfigurations.new(config)
|
|
52
73
|
end
|
|
53
74
|
self.configurations = {}
|
|
54
75
|
|
|
55
|
-
# Returns fully resolved ActiveRecord::DatabaseConfigurations object
|
|
76
|
+
# Returns a fully resolved ActiveRecord::DatabaseConfigurations object.
|
|
56
77
|
def self.configurations
|
|
57
78
|
@@configurations
|
|
58
79
|
end
|
|
@@ -71,6 +92,8 @@ module ActiveRecord
|
|
|
71
92
|
|
|
72
93
|
class_attribute :has_many_inversing, instance_accessor: false, default: false
|
|
73
94
|
|
|
95
|
+
class_attribute :run_commit_callbacks_on_first_saved_instances_in_transaction, instance_accessor: false, default: true
|
|
96
|
+
|
|
74
97
|
class_attribute :default_connection_handler, instance_writer: false
|
|
75
98
|
|
|
76
99
|
class_attribute :default_role, instance_writer: false
|
|
@@ -79,6 +102,9 @@ module ActiveRecord
|
|
|
79
102
|
|
|
80
103
|
class_attribute :shard_selector, instance_accessor: false, default: nil
|
|
81
104
|
|
|
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]
|
|
107
|
+
|
|
82
108
|
def self.application_record_class? # :nodoc:
|
|
83
109
|
if ActiveRecord.application_record_class
|
|
84
110
|
self == ActiveRecord.application_record_class
|
|
@@ -99,33 +125,6 @@ module ActiveRecord
|
|
|
99
125
|
ActiveSupport::IsolatedExecutionState[:active_record_connection_handler] = handler
|
|
100
126
|
end
|
|
101
127
|
|
|
102
|
-
def self.connection_handlers
|
|
103
|
-
if ActiveRecord.legacy_connection_handling
|
|
104
|
-
else
|
|
105
|
-
raise NotImplementedError, "The new connection handling does not support accessing multiple connection handlers."
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
@@connection_handlers ||= {}
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
def self.connection_handlers=(handlers)
|
|
112
|
-
if ActiveRecord.legacy_connection_handling
|
|
113
|
-
ActiveSupport::Deprecation.warn(<<~MSG)
|
|
114
|
-
Using legacy connection handling is deprecated. Please set
|
|
115
|
-
`legacy_connection_handling` to `false` in your application.
|
|
116
|
-
|
|
117
|
-
The new connection handling does not support `connection_handlers`
|
|
118
|
-
getter and setter.
|
|
119
|
-
|
|
120
|
-
Read more about how to migrate at: https://guides.rubyonrails.org/active_record_multiple_databases.html#migrate-to-the-new-connection-handling
|
|
121
|
-
MSG
|
|
122
|
-
else
|
|
123
|
-
raise NotImplementedError, "The new connection handling does not support multiple connection handlers."
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
@@connection_handlers = handlers
|
|
127
|
-
end
|
|
128
|
-
|
|
129
128
|
def self.asynchronous_queries_session # :nodoc:
|
|
130
129
|
asynchronous_queries_tracker.current_session
|
|
131
130
|
end
|
|
@@ -145,16 +144,12 @@ module ActiveRecord
|
|
|
145
144
|
# ActiveRecord::Base.current_role #=> :reading
|
|
146
145
|
# end
|
|
147
146
|
def self.current_role
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
connected_to_stack.reverse_each do |hash|
|
|
152
|
-
return hash[:role] if hash[:role] && hash[:klasses].include?(Base)
|
|
153
|
-
return hash[:role] if hash[:role] && hash[:klasses].include?(connection_class_for_self)
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
default_role
|
|
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)
|
|
157
150
|
end
|
|
151
|
+
|
|
152
|
+
default_role
|
|
158
153
|
end
|
|
159
154
|
|
|
160
155
|
# Returns the symbol representing the current connected shard.
|
|
@@ -186,16 +181,12 @@ module ActiveRecord
|
|
|
186
181
|
# ActiveRecord::Base.current_preventing_writes #=> false
|
|
187
182
|
# end
|
|
188
183
|
def self.current_preventing_writes
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
connected_to_stack.reverse_each do |hash|
|
|
193
|
-
return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(Base)
|
|
194
|
-
return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(connection_class_for_self)
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
false
|
|
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)
|
|
198
187
|
end
|
|
188
|
+
|
|
189
|
+
false
|
|
199
190
|
end
|
|
200
191
|
|
|
201
192
|
def self.connected_to_stack # :nodoc:
|
|
@@ -252,19 +243,6 @@ module ActiveRecord
|
|
|
252
243
|
@find_by_statement_cache = { true => Concurrent::Map.new, false => Concurrent::Map.new }
|
|
253
244
|
end
|
|
254
245
|
|
|
255
|
-
def inherited(child_class) # :nodoc:
|
|
256
|
-
# initialize cache at class definition for thread safety
|
|
257
|
-
child_class.initialize_find_by_cache
|
|
258
|
-
unless child_class.base_class?
|
|
259
|
-
klass = self
|
|
260
|
-
until klass.base_class?
|
|
261
|
-
klass.initialize_find_by_cache
|
|
262
|
-
klass = klass.superclass
|
|
263
|
-
end
|
|
264
|
-
end
|
|
265
|
-
super
|
|
266
|
-
end
|
|
267
|
-
|
|
268
246
|
def find(*ids) # :nodoc:
|
|
269
247
|
# We don't have cache keys for this stuff yet
|
|
270
248
|
return super unless ids.length == 1
|
|
@@ -274,14 +252,8 @@ module ActiveRecord
|
|
|
274
252
|
|
|
275
253
|
return super if StatementCache.unsupported_value?(id)
|
|
276
254
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
statement = cached_find_by_statement(key) { |params|
|
|
280
|
-
where(key => params.bind).limit(1)
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
statement.execute([id], connection).first ||
|
|
284
|
-
raise(RecordNotFound.new("Couldn't find #{name} with '#{key}'=#{id}", name, key, id))
|
|
255
|
+
cached_find_by([primary_key], [id]) ||
|
|
256
|
+
raise(RecordNotFound.new("Couldn't find #{name} with '#{primary_key}'=#{id}", name, primary_key, id))
|
|
285
257
|
end
|
|
286
258
|
|
|
287
259
|
def find_by(*args) # :nodoc:
|
|
@@ -303,58 +275,38 @@ module ActiveRecord
|
|
|
303
275
|
elsif reflection.belongs_to? && !reflection.polymorphic?
|
|
304
276
|
key = reflection.join_foreign_key
|
|
305
277
|
pkey = reflection.join_primary_key
|
|
306
|
-
|
|
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
|
|
307
293
|
end
|
|
308
294
|
|
|
309
|
-
if !
|
|
295
|
+
if !composite_primary_key &&
|
|
296
|
+
(!columns_hash.key?(key) || StatementCache.unsupported_value?(value))
|
|
310
297
|
return super
|
|
311
298
|
end
|
|
312
299
|
|
|
313
300
|
h[key] = value
|
|
314
301
|
end
|
|
315
302
|
|
|
316
|
-
keys
|
|
317
|
-
statement = cached_find_by_statement(keys) { |params|
|
|
318
|
-
wheres = keys.index_with { params.bind }
|
|
319
|
-
where(wheres).limit(1)
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
begin
|
|
323
|
-
statement.execute(hash.values, connection).first
|
|
324
|
-
rescue TypeError
|
|
325
|
-
raise ActiveRecord::StatementInvalid
|
|
326
|
-
end
|
|
303
|
+
cached_find_by(hash.keys, hash.values)
|
|
327
304
|
end
|
|
328
305
|
|
|
329
306
|
def find_by!(*args) # :nodoc:
|
|
330
307
|
find_by(*args) || where(*args).raise_record_not_found_exception!
|
|
331
308
|
end
|
|
332
309
|
|
|
333
|
-
%w(
|
|
334
|
-
reading_role writing_role legacy_connection_handling default_timezone index_nested_attribute_errors
|
|
335
|
-
verbose_query_logs queues warn_on_records_fetched_greater_than maintain_test_schema
|
|
336
|
-
application_record_class action_on_strict_loading_violation schema_format error_on_ignored_order
|
|
337
|
-
timestamped_migrations dump_schema_after_migration dump_schemas suppress_multiple_database_warning
|
|
338
|
-
).each do |attr|
|
|
339
|
-
module_eval(<<~RUBY, __FILE__, __LINE__ + 1)
|
|
340
|
-
def #{attr}
|
|
341
|
-
ActiveSupport::Deprecation.warn(<<~MSG)
|
|
342
|
-
ActiveRecord::Base.#{attr} is deprecated and will be removed in Rails 7.1.
|
|
343
|
-
Use `ActiveRecord.#{attr}` instead.
|
|
344
|
-
MSG
|
|
345
|
-
ActiveRecord.#{attr}
|
|
346
|
-
end
|
|
347
|
-
|
|
348
|
-
def #{attr}=(value)
|
|
349
|
-
ActiveSupport::Deprecation.warn(<<~MSG)
|
|
350
|
-
ActiveRecord::Base.#{attr}= is deprecated and will be removed in Rails 7.1.
|
|
351
|
-
Use `ActiveRecord.#{attr}=` instead.
|
|
352
|
-
MSG
|
|
353
|
-
ActiveRecord.#{attr} = value
|
|
354
|
-
end
|
|
355
|
-
RUBY
|
|
356
|
-
end
|
|
357
|
-
|
|
358
310
|
def initialize_generated_modules # :nodoc:
|
|
359
311
|
generated_association_methods
|
|
360
312
|
end
|
|
@@ -371,10 +323,10 @@ module ActiveRecord
|
|
|
371
323
|
|
|
372
324
|
# Returns columns which shouldn't be exposed while calling +#inspect+.
|
|
373
325
|
def filter_attributes
|
|
374
|
-
if
|
|
375
|
-
@filter_attributes
|
|
376
|
-
else
|
|
326
|
+
if @filter_attributes.nil?
|
|
377
327
|
superclass.filter_attributes
|
|
328
|
+
else
|
|
329
|
+
@filter_attributes
|
|
378
330
|
end
|
|
379
331
|
end
|
|
380
332
|
|
|
@@ -385,13 +337,13 @@ module ActiveRecord
|
|
|
385
337
|
end
|
|
386
338
|
|
|
387
339
|
def inspection_filter # :nodoc:
|
|
388
|
-
if
|
|
340
|
+
if @filter_attributes.nil?
|
|
341
|
+
superclass.inspection_filter
|
|
342
|
+
else
|
|
389
343
|
@inspection_filter ||= begin
|
|
390
344
|
mask = InspectionMask.new(ActiveSupport::ParameterFilter::FILTERED)
|
|
391
345
|
ActiveSupport::ParameterFilter.new(@filter_attributes, mask: mask)
|
|
392
346
|
end
|
|
393
|
-
else
|
|
394
|
-
superclass.inspection_filter
|
|
395
347
|
end
|
|
396
348
|
end
|
|
397
349
|
|
|
@@ -402,7 +354,7 @@ module ActiveRecord
|
|
|
402
354
|
elsif abstract_class?
|
|
403
355
|
"#{super}(abstract)"
|
|
404
356
|
elsif !connected?
|
|
405
|
-
"#{super} (call '#{super}.
|
|
357
|
+
"#{super} (call '#{super}.lease_connection' to establish a connection)"
|
|
406
358
|
elsif table_exists?
|
|
407
359
|
attr_list = attribute_types.map { |name, type| "#{name}: #{type.type}" } * ", "
|
|
408
360
|
"#{super}(#{attr_list})"
|
|
@@ -411,12 +363,7 @@ module ActiveRecord
|
|
|
411
363
|
end
|
|
412
364
|
end
|
|
413
365
|
|
|
414
|
-
#
|
|
415
|
-
def ===(object) # :nodoc:
|
|
416
|
-
object.is_a?(self)
|
|
417
|
-
end
|
|
418
|
-
|
|
419
|
-
# Returns an instance of <tt>Arel::Table</tt> loaded with the current table name.
|
|
366
|
+
# Returns an instance of +Arel::Table+ loaded with the current table name.
|
|
420
367
|
def arel_table # :nodoc:
|
|
421
368
|
@arel_table ||= Arel::Table.new(table_name, klass: self)
|
|
422
369
|
end
|
|
@@ -429,12 +376,34 @@ module ActiveRecord
|
|
|
429
376
|
TypeCaster::Map.new(self)
|
|
430
377
|
end
|
|
431
378
|
|
|
432
|
-
def cached_find_by_statement(key, &block) # :nodoc:
|
|
379
|
+
def cached_find_by_statement(connection, key, &block) # :nodoc:
|
|
433
380
|
cache = @find_by_statement_cache[connection.prepared_statements]
|
|
434
381
|
cache.compute_if_absent(key) { StatementCache.create(connection, &block) }
|
|
435
382
|
end
|
|
436
383
|
|
|
437
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
|
+
|
|
438
407
|
def relation
|
|
439
408
|
relation = Relation.create(self)
|
|
440
409
|
|
|
@@ -448,6 +417,27 @@ module ActiveRecord
|
|
|
448
417
|
def table_metadata
|
|
449
418
|
TableMetadata.new(self, arel_table)
|
|
450
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
|
|
451
441
|
end
|
|
452
442
|
|
|
453
443
|
# New objects can be instantiated as either empty (pass no construction parameter) or pre-set with
|
|
@@ -455,7 +445,7 @@ module ActiveRecord
|
|
|
455
445
|
# In both instances, valid attribute keys are determined by the column names of the associated table --
|
|
456
446
|
# hence you can't have attributes that aren't part of the table columns.
|
|
457
447
|
#
|
|
458
|
-
# ==== Example
|
|
448
|
+
# ==== Example
|
|
459
449
|
# # Instantiates a single new object
|
|
460
450
|
# User.new(first_name: 'Jamie')
|
|
461
451
|
def initialize(attributes = nil)
|
|
@@ -465,7 +455,7 @@ module ActiveRecord
|
|
|
465
455
|
init_internals
|
|
466
456
|
initialize_internals_callback
|
|
467
457
|
|
|
468
|
-
|
|
458
|
+
super
|
|
469
459
|
|
|
470
460
|
yield self if block_given?
|
|
471
461
|
_run_initialize_callbacks
|
|
@@ -533,12 +523,17 @@ module ActiveRecord
|
|
|
533
523
|
# only, not its associations. The extent of a "deep" copy is application
|
|
534
524
|
# specific and is therefore left to the application to implement according
|
|
535
525
|
# to its need.
|
|
536
|
-
# 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.
|
|
537
528
|
|
|
538
529
|
##
|
|
539
530
|
def initialize_dup(other) # :nodoc:
|
|
540
531
|
@attributes = @attributes.deep_dup
|
|
541
|
-
|
|
532
|
+
if self.class.composite_primary_key?
|
|
533
|
+
@primary_key.each { |key| @attributes.reset(key) }
|
|
534
|
+
else
|
|
535
|
+
@attributes.reset(@primary_key)
|
|
536
|
+
end
|
|
542
537
|
|
|
543
538
|
_run_initialize_callbacks
|
|
544
539
|
|
|
@@ -568,6 +563,35 @@ module ActiveRecord
|
|
|
568
563
|
coder["active_record_yaml_version"] = 2
|
|
569
564
|
end
|
|
570
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
|
+
|
|
571
595
|
# Returns true if +comparison_object+ is the same exact object, or +comparison_object+
|
|
572
596
|
# is of the same type and +self+ has an ID and it is equal to +comparison_object.id+.
|
|
573
597
|
#
|
|
@@ -580,7 +604,7 @@ module ActiveRecord
|
|
|
580
604
|
def ==(comparison_object)
|
|
581
605
|
super ||
|
|
582
606
|
comparison_object.instance_of?(self.class) &&
|
|
583
|
-
|
|
607
|
+
primary_key_values_present? &&
|
|
584
608
|
comparison_object.id == id
|
|
585
609
|
end
|
|
586
610
|
alias :eql? :==
|
|
@@ -590,7 +614,7 @@ module ActiveRecord
|
|
|
590
614
|
def hash
|
|
591
615
|
id = self.id
|
|
592
616
|
|
|
593
|
-
if
|
|
617
|
+
if primary_key_values_present?
|
|
594
618
|
self.class.hash ^ id.hash
|
|
595
619
|
else
|
|
596
620
|
super
|
|
@@ -642,25 +666,33 @@ module ActiveRecord
|
|
|
642
666
|
#
|
|
643
667
|
# user = User.first
|
|
644
668
|
# user.strict_loading! # => true
|
|
645
|
-
# user.
|
|
669
|
+
# user.address.city
|
|
670
|
+
# => ActiveRecord::StrictLoadingViolationError
|
|
671
|
+
# user.comments.to_a
|
|
646
672
|
# => ActiveRecord::StrictLoadingViolationError
|
|
647
673
|
#
|
|
648
|
-
#
|
|
674
|
+
# ==== Parameters
|
|
649
675
|
#
|
|
650
|
-
# * value - Boolean specifying whether to enable or disable strict loading.
|
|
651
|
-
# * mode - Symbol specifying strict loading mode. Defaults to :all. Using
|
|
652
|
-
#
|
|
653
|
-
#
|
|
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.
|
|
654
680
|
#
|
|
655
|
-
#
|
|
681
|
+
# ==== Examples
|
|
656
682
|
#
|
|
657
683
|
# user = User.first
|
|
658
684
|
# user.strict_loading!(false) # => false
|
|
659
|
-
# user.
|
|
660
|
-
# => #<
|
|
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
|
|
661
693
|
def strict_loading!(value = true, mode: :all)
|
|
662
694
|
unless [:all, :n_plus_one_only].include?(mode)
|
|
663
|
-
raise ArgumentError, "The :mode option must be one of [:all, :n_plus_one_only]."
|
|
695
|
+
raise ArgumentError, "The :mode option must be one of [:all, :n_plus_one_only] but #{mode.inspect} was provided."
|
|
664
696
|
end
|
|
665
697
|
|
|
666
698
|
@strict_loading_mode = mode
|
|
@@ -674,7 +706,16 @@ module ActiveRecord
|
|
|
674
706
|
@strict_loading_mode == :n_plus_one_only
|
|
675
707
|
end
|
|
676
708
|
|
|
709
|
+
# Returns +true+ if the record uses strict_loading with +:all+ mode enabled.
|
|
710
|
+
def strict_loading_all?
|
|
711
|
+
@strict_loading_mode == :all
|
|
712
|
+
end
|
|
713
|
+
|
|
677
714
|
# Marks this record as read only.
|
|
715
|
+
#
|
|
716
|
+
# customer = Customer.first
|
|
717
|
+
# customer.readonly!
|
|
718
|
+
# customer.save # Raises an ActiveRecord::ReadOnlyRecord
|
|
678
719
|
def readonly!
|
|
679
720
|
@readonly = true
|
|
680
721
|
end
|
|
@@ -683,21 +724,14 @@ module ActiveRecord
|
|
|
683
724
|
self.class.connection_handler
|
|
684
725
|
end
|
|
685
726
|
|
|
686
|
-
# Returns the
|
|
727
|
+
# Returns the attributes specified by <tt>.attributes_for_inspect</tt> as a nicely formatted string.
|
|
687
728
|
def inspect
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
inspection = if defined?(@attributes) && @attributes
|
|
691
|
-
self.class.attribute_names.filter_map do |name|
|
|
692
|
-
if _has_attribute?(name)
|
|
693
|
-
"#{name}: #{attribute_for_inspect(name)}"
|
|
694
|
-
end
|
|
695
|
-
end.join(", ")
|
|
696
|
-
else
|
|
697
|
-
"not initialized"
|
|
698
|
-
end
|
|
729
|
+
inspect_with_attributes(attributes_for_inspect)
|
|
730
|
+
end
|
|
699
731
|
|
|
700
|
-
|
|
732
|
+
# Returns the full contents of the record as a nicely formatted string.
|
|
733
|
+
def full_inspect
|
|
734
|
+
inspect_with_attributes(attribute_names)
|
|
701
735
|
end
|
|
702
736
|
|
|
703
737
|
# Takes a PP and prettily prints this record to it, allowing you to get a nice result from <tt>pp record</tt>
|
|
@@ -705,17 +739,17 @@ module ActiveRecord
|
|
|
705
739
|
def pretty_print(pp)
|
|
706
740
|
return super if custom_inspect_method_defined?
|
|
707
741
|
pp.object_address_group(self) do
|
|
708
|
-
if
|
|
709
|
-
attr_names =
|
|
742
|
+
if @attributes
|
|
743
|
+
attr_names = attributes_for_inspect.select { |name| _has_attribute?(name.to_s) }
|
|
710
744
|
pp.seplist(attr_names, proc { pp.text "," }) do |attr_name|
|
|
745
|
+
attr_name = attr_name.to_s
|
|
711
746
|
pp.breakable " "
|
|
712
747
|
pp.group(1) do
|
|
713
748
|
pp.text attr_name
|
|
714
749
|
pp.text ":"
|
|
715
750
|
pp.breakable
|
|
716
|
-
value =
|
|
717
|
-
|
|
718
|
-
pp.pp value
|
|
751
|
+
value = attribute_for_inspect(attr_name)
|
|
752
|
+
pp.text value
|
|
719
753
|
end
|
|
720
754
|
end
|
|
721
755
|
else
|
|
@@ -725,16 +759,6 @@ module ActiveRecord
|
|
|
725
759
|
end
|
|
726
760
|
end
|
|
727
761
|
|
|
728
|
-
# Returns a hash of the given methods with their names as keys and returned values as values.
|
|
729
|
-
def slice(*methods)
|
|
730
|
-
methods.flatten.index_with { |method| public_send(method) }.with_indifferent_access
|
|
731
|
-
end
|
|
732
|
-
|
|
733
|
-
# Returns an array of the values returned by the given methods.
|
|
734
|
-
def values_at(*methods)
|
|
735
|
-
methods.flatten.map! { |method| public_send(method) }
|
|
736
|
-
end
|
|
737
|
-
|
|
738
762
|
private
|
|
739
763
|
# +Array#flatten+ will call +#to_ary+ (recursively) on each of the elements of
|
|
740
764
|
# the array, and then rescues from the possible +NoMethodError+. If those elements are
|
|
@@ -782,5 +806,24 @@ module ActiveRecord
|
|
|
782
806
|
def inspection_filter
|
|
783
807
|
self.class.inspection_filter
|
|
784
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
|
|
785
828
|
end
|
|
786
829
|
end
|