activerecord 5.2.8 → 7.0.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1393 -587
- data/MIT-LICENSE +3 -1
- data/README.rdoc +7 -5
- data/examples/performance.rb +1 -1
- data/lib/active_record/aggregations.rb +10 -9
- data/lib/active_record/association_relation.rb +22 -12
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +122 -47
- data/lib/active_record/associations/association_scope.rb +24 -24
- data/lib/active_record/associations/belongs_to_association.rb +67 -49
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +16 -7
- data/lib/active_record/associations/builder/association.rb +52 -23
- data/lib/active_record/associations/builder/belongs_to.rb +44 -61
- data/lib/active_record/associations/builder/collection_association.rb +17 -19
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -41
- data/lib/active_record/associations/builder/has_many.rb +10 -3
- data/lib/active_record/associations/builder/has_one.rb +35 -3
- data/lib/active_record/associations/builder/singular_association.rb +5 -3
- data/lib/active_record/associations/collection_association.rb +59 -50
- data/lib/active_record/associations/collection_proxy.rb +32 -23
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/foreign_association.rb +20 -0
- data/lib/active_record/associations/has_many_association.rb +27 -14
- data/lib/active_record/associations/has_many_through_association.rb +26 -19
- data/lib/active_record/associations/has_one_association.rb +52 -37
- data/lib/active_record/associations/has_one_through_association.rb +6 -6
- data/lib/active_record/associations/join_dependency/join_association.rb +44 -22
- data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
- data/lib/active_record/associations/join_dependency.rb +97 -62
- data/lib/active_record/associations/preloader/association.rb +220 -60
- 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 +85 -40
- data/lib/active_record/associations/preloader.rb +44 -105
- data/lib/active_record/associations/singular_association.rb +9 -17
- data/lib/active_record/associations/through_association.rb +4 -4
- data/lib/active_record/associations.rb +207 -66
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +17 -19
- data/lib/active_record/attribute_methods/before_type_cast.rb +19 -8
- data/lib/active_record/attribute_methods/dirty.rb +141 -47
- data/lib/active_record/attribute_methods/primary_key.rb +22 -27
- data/lib/active_record/attribute_methods/query.rb +6 -10
- data/lib/active_record/attribute_methods/read.rb +15 -55
- data/lib/active_record/attribute_methods/serialization.rb +77 -18
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +16 -18
- data/lib/active_record/attribute_methods/write.rb +18 -37
- data/lib/active_record/attribute_methods.rb +90 -153
- data/lib/active_record/attributes.rb +38 -12
- data/lib/active_record/autosave_association.rb +50 -50
- data/lib/active_record/base.rb +23 -18
- data/lib/active_record/callbacks.rb +159 -44
- data/lib/active_record/coders/yaml_column.rb +12 -3
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +292 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +209 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +76 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +92 -464
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -51
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +209 -164
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +38 -22
- data/lib/active_record/connection_adapters/abstract/quoting.rb +103 -82
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +140 -110
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -94
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +16 -5
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +456 -159
- data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -78
- data/lib/active_record/connection_adapters/abstract_adapter.rb +367 -162
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +311 -327
- data/lib/active_record/connection_adapters/column.rb +33 -11
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +113 -45
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +71 -5
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +34 -10
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +48 -32
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +25 -8
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +143 -19
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +63 -22
- data/lib/active_record/connection_adapters/pool_config.rb +73 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +53 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +56 -63
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +10 -2
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +15 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +54 -16
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- 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 +26 -12
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +15 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +4 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +89 -52
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +34 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +39 -4
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +128 -91
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +25 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +149 -113
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +31 -26
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +386 -182
- data/lib/active_record/connection_adapters/schema_cache.rb +161 -22
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +17 -6
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +152 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +65 -18
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +92 -26
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +251 -204
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_adapters.rb +53 -0
- data/lib/active_record/connection_handling.rb +292 -38
- data/lib/active_record/core.rb +385 -158
- data/lib/active_record/counter_cache.rb +8 -30
- data/lib/active_record/database_configurations/connection_url_resolver.rb +100 -0
- data/lib/active_record/database_configurations/database_config.rb +83 -0
- data/lib/active_record/database_configurations/hash_config.rb +154 -0
- data/lib/active_record/database_configurations/url_config.rb +53 -0
- data/lib/active_record/database_configurations.rb +256 -0
- data/lib/active_record/delegated_type.rb +250 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +4 -5
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +98 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +44 -0
- data/lib/active_record/encryption/configurable.rb +61 -0
- data/lib/active_record/encryption/context.rb +35 -0
- data/lib/active_record/encryption/contexts.rb +72 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +12 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +208 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +140 -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 +160 -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 +42 -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 +90 -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 +99 -0
- data/lib/active_record/encryption.rb +55 -0
- data/lib/active_record/enum.rb +130 -51
- data/lib/active_record/errors.rb +129 -23
- data/lib/active_record/explain.rb +10 -6
- 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 +22 -15
- data/lib/active_record/fixture_set/model_metadata.rb +32 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +187 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +206 -490
- data/lib/active_record/future_result.rb +139 -0
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +104 -37
- data/lib/active_record/insert_all.rb +278 -0
- data/lib/active_record/integration.rb +69 -18
- data/lib/active_record/internal_metadata.rb +24 -9
- data/lib/active_record/legacy_yaml_adapter.rb +3 -36
- data/lib/active_record/locking/optimistic.rb +41 -26
- data/lib/active_record/locking/pessimistic.rb +18 -8
- data/lib/active_record/log_subscriber.rb +46 -35
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +88 -0
- data/lib/active_record/middleware/database_selector.rb +82 -0
- data/lib/active_record/middleware/shard_selector.rb +60 -0
- data/lib/active_record/migration/command_recorder.rb +96 -44
- data/lib/active_record/migration/compatibility.rb +246 -64
- data/lib/active_record/migration/join_table.rb +1 -2
- data/lib/active_record/migration.rb +266 -187
- data/lib/active_record/model_schema.rb +165 -52
- data/lib/active_record/nested_attributes.rb +17 -19
- data/lib/active_record/no_touching.rb +11 -4
- data/lib/active_record/null_relation.rb +2 -7
- data/lib/active_record/persistence.rb +467 -92
- data/lib/active_record/query_cache.rb +21 -4
- data/lib/active_record/query_logs.rb +138 -0
- data/lib/active_record/querying.rb +51 -24
- data/lib/active_record/railtie.rb +224 -57
- data/lib/active_record/railties/console_sandbox.rb +2 -4
- data/lib/active_record/railties/controller_runtime.rb +31 -36
- data/lib/active_record/railties/databases.rake +369 -101
- data/lib/active_record/readonly_attributes.rb +15 -0
- data/lib/active_record/reflection.rb +170 -137
- data/lib/active_record/relation/batches/batch_enumerator.rb +44 -14
- data/lib/active_record/relation/batches.rb +46 -37
- data/lib/active_record/relation/calculations.rb +168 -96
- data/lib/active_record/relation/delegation.rb +37 -52
- data/lib/active_record/relation/finder_methods.rb +79 -58
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +50 -51
- data/lib/active_record/relation/predicate_builder/array_handler.rb +13 -13
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +5 -9
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +11 -10
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +58 -46
- data/lib/active_record/relation/query_attribute.rb +9 -10
- data/lib/active_record/relation/query_methods.rb +685 -208
- data/lib/active_record/relation/record_fetch_warning.rb +9 -11
- data/lib/active_record/relation/spawn_methods.rb +10 -10
- data/lib/active_record/relation/where_clause.rb +108 -64
- data/lib/active_record/relation.rb +515 -151
- data/lib/active_record/result.rb +78 -42
- data/lib/active_record/runtime_registry.rb +9 -13
- data/lib/active_record/sanitization.rb +29 -44
- data/lib/active_record/schema.rb +37 -31
- data/lib/active_record/schema_dumper.rb +74 -23
- data/lib/active_record/schema_migration.rb +7 -9
- data/lib/active_record/scoping/default.rb +62 -17
- data/lib/active_record/scoping/named.rb +17 -32
- data/lib/active_record/scoping.rb +70 -41
- data/lib/active_record/secure_token.rb +16 -8
- data/lib/active_record/serialization.rb +6 -4
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +49 -6
- data/lib/active_record/store.rb +88 -9
- data/lib/active_record/suppressor.rb +13 -17
- data/lib/active_record/table_metadata.rb +42 -43
- data/lib/active_record/tasks/database_tasks.rb +352 -94
- data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
- data/lib/active_record/tasks/postgresql_database_tasks.rb +41 -39
- data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -17
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +287 -0
- data/lib/active_record/timestamp.rb +44 -34
- data/lib/active_record/touch_later.rb +23 -22
- data/lib/active_record/transactions.rb +67 -128
- data/lib/active_record/translation.rb +3 -3
- data/lib/active_record/type/adapter_specific_registry.rb +34 -19
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -2
- data/lib/active_record/type/internal/timezone.rb +2 -2
- data/lib/active_record/type/serialized.rb +7 -4
- data/lib/active_record/type/time.rb +10 -0
- data/lib/active_record/type/type_map.rb +17 -21
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type.rb +9 -5
- data/lib/active_record/type_caster/connection.rb +15 -15
- data/lib/active_record/type_caster/map.rb +8 -8
- data/lib/active_record/validations/associated.rb +2 -3
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +39 -31
- data/lib/active_record/validations.rb +4 -3
- data/lib/active_record.rb +209 -32
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +33 -0
- data/lib/arel/collectors/bind.rb +29 -0
- data/lib/arel/collectors/composite.rb +39 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +27 -0
- data/lib/arel/collectors/substitute_binds.rb +35 -0
- data/lib/arel/crud.rb +48 -0
- data/lib/arel/delete_manager.rb +32 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +48 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +126 -0
- data/lib/arel/nodes/bind_param.rb +44 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +62 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +44 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +15 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +45 -0
- data/lib/arel/nodes/grouping.rb +11 -0
- data/lib/arel/nodes/homogeneous_in.rb +76 -0
- data/lib/arel/nodes/in.rb +15 -0
- data/lib/arel/nodes/infix_operation.rb +92 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +51 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +19 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +31 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +46 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +71 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +258 -0
- data/lib/arel/select_manager.rb +276 -0
- data/lib/arel/table.rb +117 -0
- data/lib/arel/tree_manager.rb +60 -0
- data/lib/arel/update_manager.rb +48 -0
- data/lib/arel/visitors/dot.rb +298 -0
- data/lib/arel/visitors/mysql.rb +99 -0
- data/lib/arel/visitors/postgresql.rb +110 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +955 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors.rb +13 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +55 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -5
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +3 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +7 -5
- data/lib/rails/generators/active_record/migration.rb +19 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -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 +162 -32
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/collection_cache_key.rb +0 -53
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -287
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -33
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -19
- data/lib/active_record/relation/where_clause_factory.rb +0 -34
data/lib/active_record/core.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/core_ext/enumerable"
|
3
4
|
require "active_support/core_ext/hash/indifferent_access"
|
4
5
|
require "active_support/core_ext/string/filters"
|
6
|
+
require "active_support/parameter_filter"
|
5
7
|
require "concurrent/map"
|
6
8
|
|
7
9
|
module ActiveRecord
|
@@ -15,18 +17,17 @@ module ActiveRecord
|
|
15
17
|
# Accepts a logger conforming to the interface of Log4r which is then
|
16
18
|
# passed on to any new database connections made and which can be
|
17
19
|
# retrieved on both a class and instance level by calling +logger+.
|
18
|
-
|
20
|
+
class_attribute :logger, instance_writer: false
|
19
21
|
|
20
22
|
##
|
21
23
|
# :singleton-method:
|
22
24
|
#
|
23
|
-
# Specifies
|
24
|
-
|
25
|
-
mattr_accessor :verbose_query_logs, instance_writer: false, default: false
|
25
|
+
# Specifies the job used to destroy associations in the background
|
26
|
+
class_attribute :destroy_association_async_job, instance_writer: false, instance_predicate: false, default: false
|
26
27
|
|
27
28
|
##
|
28
29
|
# Contains the database configuration - as is typically stored in config/database.yml -
|
29
|
-
# as
|
30
|
+
# as an ActiveRecord::DatabaseConfigurations object.
|
30
31
|
#
|
31
32
|
# For example, the following database.yml...
|
32
33
|
#
|
@@ -40,110 +41,213 @@ module ActiveRecord
|
|
40
41
|
#
|
41
42
|
# ...would result in ActiveRecord::Base.configurations to look like this:
|
42
43
|
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
# 'adapter' => 'sqlite3',
|
50
|
-
# 'database' => 'db/production.sqlite3'
|
51
|
-
# }
|
52
|
-
# }
|
44
|
+
# #<ActiveRecord::DatabaseConfigurations:0x00007fd1acbdf800 @configurations=[
|
45
|
+
# #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10 @env_name="development",
|
46
|
+
# @name="primary", @config={adapter: "sqlite3", database: "db/development.sqlite3"}>,
|
47
|
+
# #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbdea90 @env_name="production",
|
48
|
+
# @name="primary", @config={adapter: "sqlite3", database: "db/production.sqlite3"}>
|
49
|
+
# ]>
|
53
50
|
def self.configurations=(config)
|
54
|
-
@@configurations = ActiveRecord::
|
51
|
+
@@configurations = ActiveRecord::DatabaseConfigurations.new(config)
|
55
52
|
end
|
56
53
|
self.configurations = {}
|
57
54
|
|
58
|
-
# Returns fully resolved
|
55
|
+
# Returns fully resolved ActiveRecord::DatabaseConfigurations object
|
59
56
|
def self.configurations
|
60
57
|
@@configurations
|
61
58
|
end
|
62
59
|
|
63
60
|
##
|
64
61
|
# :singleton-method:
|
65
|
-
#
|
66
|
-
#
|
67
|
-
|
62
|
+
# Force enumeration of all columns in SELECT statements.
|
63
|
+
# e.g. `SELECT first_name, last_name FROM ...` instead of `SELECT * FROM ...`
|
64
|
+
# This avoids +PreparedStatementCacheExpired+ errors when a column is added
|
65
|
+
# to the database while the app is running.
|
66
|
+
class_attribute :enumerate_columns_in_select_statements, instance_accessor: false, default: false
|
68
67
|
|
69
|
-
|
70
|
-
# :singleton-method:
|
71
|
-
# Specifies the format to use when dumping the database schema with Rails'
|
72
|
-
# Rakefile. If :sql, the schema is dumped as (potentially database-
|
73
|
-
# specific) SQL statements. If :ruby, the schema is dumped as an
|
74
|
-
# ActiveRecord::Schema file which can be loaded into any database that
|
75
|
-
# supports migrations. Use :ruby if you want to have different database
|
76
|
-
# adapters for, e.g., your development and test environments.
|
77
|
-
mattr_accessor :schema_format, instance_writer: false, default: :ruby
|
78
|
-
|
79
|
-
##
|
80
|
-
# :singleton-method:
|
81
|
-
# Specifies if an error should be raised if the query has an order being
|
82
|
-
# ignored when doing batch queries. Useful in applications where the
|
83
|
-
# scope being ignored is error-worthy, rather than a warning.
|
84
|
-
mattr_accessor :error_on_ignored_order, instance_writer: false, default: false
|
68
|
+
class_attribute :belongs_to_required_by_default, instance_accessor: false
|
85
69
|
|
86
|
-
|
87
|
-
# Specify the behavior for unsafe raw query methods. Values are as follows
|
88
|
-
# deprecated - Warnings are logged when unsafe raw SQL is passed to
|
89
|
-
# query methods.
|
90
|
-
# disabled - Unsafe raw SQL passed to query methods results in
|
91
|
-
# UnknownAttributeReference exception.
|
92
|
-
mattr_accessor :allow_unsafe_raw_sql, instance_writer: false, default: :deprecated
|
70
|
+
class_attribute :strict_loading_by_default, instance_accessor: false, default: false
|
93
71
|
|
94
|
-
|
95
|
-
# :singleton-method:
|
96
|
-
# Specify whether or not to use timestamps for migration versions
|
97
|
-
mattr_accessor :timestamped_migrations, instance_writer: false, default: true
|
72
|
+
class_attribute :has_many_inversing, instance_accessor: false, default: false
|
98
73
|
|
99
|
-
|
100
|
-
# :singleton-method:
|
101
|
-
# Specify whether schema dump should happen at the end of the
|
102
|
-
# db:migrate rake task. This is true by default, which is useful for the
|
103
|
-
# development environment. This should ideally be false in the production
|
104
|
-
# environment where dumping schema is rarely needed.
|
105
|
-
mattr_accessor :dump_schema_after_migration, instance_writer: false, default: true
|
74
|
+
class_attribute :default_connection_handler, instance_writer: false
|
106
75
|
|
107
|
-
|
108
|
-
# :singleton-method:
|
109
|
-
# Specifies which database schemas to dump when calling db:structure:dump.
|
110
|
-
# If the value is :schema_search_path (the default), any schemas listed in
|
111
|
-
# schema_search_path are dumped. Use :all to dump all schemas regardless
|
112
|
-
# of schema_search_path, or a string of comma separated schemas for a
|
113
|
-
# custom list.
|
114
|
-
mattr_accessor :dump_schemas, instance_writer: false, default: :schema_search_path
|
76
|
+
class_attribute :default_role, instance_writer: false
|
115
77
|
|
116
|
-
|
117
|
-
# :singleton-method:
|
118
|
-
# Specify a threshold for the size of query result sets. If the number of
|
119
|
-
# records in the set exceeds the threshold, a warning is logged. This can
|
120
|
-
# be used to identify queries which load thousands of records and
|
121
|
-
# potentially cause memory bloat.
|
122
|
-
mattr_accessor :warn_on_records_fetched_greater_than, instance_writer: false
|
78
|
+
class_attribute :default_shard, instance_writer: false
|
123
79
|
|
124
|
-
|
80
|
+
class_attribute :shard_selector, instance_accessor: false, default: nil
|
125
81
|
|
126
|
-
|
82
|
+
def self.application_record_class? # :nodoc:
|
83
|
+
if ActiveRecord.application_record_class
|
84
|
+
self == ActiveRecord.application_record_class
|
85
|
+
else
|
86
|
+
if defined?(ApplicationRecord) && self == ApplicationRecord
|
87
|
+
true
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
127
91
|
|
128
|
-
|
92
|
+
self.filter_attributes = []
|
129
93
|
|
130
94
|
def self.connection_handler
|
131
|
-
|
95
|
+
ActiveSupport::IsolatedExecutionState[:active_record_connection_handler] || default_connection_handler
|
132
96
|
end
|
133
97
|
|
134
98
|
def self.connection_handler=(handler)
|
135
|
-
|
99
|
+
ActiveSupport::IsolatedExecutionState[:active_record_connection_handler] = handler
|
136
100
|
end
|
137
101
|
|
138
|
-
self.
|
139
|
-
|
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
|
140
107
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
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
|
+
def self.asynchronous_queries_session # :nodoc:
|
130
|
+
asynchronous_queries_tracker.current_session
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.asynchronous_queries_tracker # :nodoc:
|
134
|
+
ActiveSupport::IsolatedExecutionState[:active_record_asynchronous_queries_tracker] ||= \
|
135
|
+
AsynchronousQueriesTracker.new
|
136
|
+
end
|
137
|
+
|
138
|
+
# Returns the symbol representing the current connected role.
|
139
|
+
#
|
140
|
+
# ActiveRecord::Base.connected_to(role: :writing) do
|
141
|
+
# ActiveRecord::Base.current_role #=> :writing
|
142
|
+
# end
|
143
|
+
#
|
144
|
+
# ActiveRecord::Base.connected_to(role: :reading) do
|
145
|
+
# ActiveRecord::Base.current_role #=> :reading
|
146
|
+
# end
|
147
|
+
def self.current_role
|
148
|
+
if ActiveRecord.legacy_connection_handling
|
149
|
+
connection_handlers.key(connection_handler) || default_role
|
150
|
+
else
|
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
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# Returns the symbol representing the current connected shard.
|
161
|
+
#
|
162
|
+
# ActiveRecord::Base.connected_to(role: :reading) do
|
163
|
+
# ActiveRecord::Base.current_shard #=> :default
|
164
|
+
# end
|
165
|
+
#
|
166
|
+
# ActiveRecord::Base.connected_to(role: :writing, shard: :one) do
|
167
|
+
# ActiveRecord::Base.current_shard #=> :one
|
168
|
+
# end
|
169
|
+
def self.current_shard
|
170
|
+
connected_to_stack.reverse_each do |hash|
|
171
|
+
return hash[:shard] if hash[:shard] && hash[:klasses].include?(Base)
|
172
|
+
return hash[:shard] if hash[:shard] && hash[:klasses].include?(connection_class_for_self)
|
173
|
+
end
|
174
|
+
|
175
|
+
default_shard
|
176
|
+
end
|
177
|
+
|
178
|
+
# Returns the symbol representing the current setting for
|
179
|
+
# preventing writes.
|
180
|
+
#
|
181
|
+
# ActiveRecord::Base.connected_to(role: :reading) do
|
182
|
+
# ActiveRecord::Base.current_preventing_writes #=> true
|
183
|
+
# end
|
184
|
+
#
|
185
|
+
# ActiveRecord::Base.connected_to(role: :writing) do
|
186
|
+
# ActiveRecord::Base.current_preventing_writes #=> false
|
187
|
+
# end
|
188
|
+
def self.current_preventing_writes
|
189
|
+
if ActiveRecord.legacy_connection_handling
|
190
|
+
connection_handler.prevent_writes
|
191
|
+
else
|
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
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def self.connected_to_stack # :nodoc:
|
202
|
+
if connected_to_stack = ActiveSupport::IsolatedExecutionState[:active_record_connected_to_stack]
|
203
|
+
connected_to_stack
|
204
|
+
else
|
205
|
+
connected_to_stack = Concurrent::Array.new
|
206
|
+
ActiveSupport::IsolatedExecutionState[:active_record_connected_to_stack] = connected_to_stack
|
207
|
+
connected_to_stack
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def self.connection_class=(b) # :nodoc:
|
212
|
+
@connection_class = b
|
213
|
+
end
|
214
|
+
|
215
|
+
def self.connection_class # :nodoc:
|
216
|
+
@connection_class ||= false
|
217
|
+
end
|
218
|
+
|
219
|
+
def self.connection_class? # :nodoc:
|
220
|
+
self.connection_class
|
221
|
+
end
|
222
|
+
|
223
|
+
def self.connection_class_for_self # :nodoc:
|
224
|
+
klass = self
|
225
|
+
|
226
|
+
until klass == Base
|
227
|
+
break if klass.connection_class?
|
228
|
+
klass = klass.superclass
|
229
|
+
end
|
230
|
+
|
231
|
+
klass
|
232
|
+
end
|
233
|
+
|
234
|
+
self.default_connection_handler = ConnectionAdapters::ConnectionHandler.new
|
235
|
+
self.default_role = ActiveRecord.writing_role
|
236
|
+
self.default_shard = :default
|
237
|
+
|
238
|
+
def self.strict_loading_violation!(owner:, reflection:) # :nodoc:
|
239
|
+
case ActiveRecord.action_on_strict_loading_violation
|
240
|
+
when :raise
|
241
|
+
message = "`#{owner}` is marked for strict_loading. The `#{reflection.klass}` association named `:#{reflection.name}` cannot be lazily loaded."
|
242
|
+
raise ActiveRecord::StrictLoadingViolationError.new(message)
|
243
|
+
when :log
|
244
|
+
name = "strict_loading_violation.active_record"
|
245
|
+
ActiveSupport::Notifications.instrument(name, owner: owner, reflection: reflection)
|
246
|
+
end
|
145
247
|
end
|
248
|
+
end
|
146
249
|
|
250
|
+
module ClassMethods
|
147
251
|
def initialize_find_by_cache # :nodoc:
|
148
252
|
@find_by_statement_cache = { true => Concurrent::Map.new, false => Concurrent::Map.new }
|
149
253
|
end
|
@@ -151,16 +255,20 @@ module ActiveRecord
|
|
151
255
|
def inherited(child_class) # :nodoc:
|
152
256
|
# initialize cache at class definition for thread safety
|
153
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
|
154
265
|
super
|
155
266
|
end
|
156
267
|
|
157
268
|
def find(*ids) # :nodoc:
|
158
269
|
# We don't have cache keys for this stuff yet
|
159
270
|
return super unless ids.length == 1
|
160
|
-
return super if block_given? ||
|
161
|
-
primary_key.nil? ||
|
162
|
-
scope_attributes? ||
|
163
|
-
columns_hash.include?(inheritance_column)
|
271
|
+
return super if block_given? || primary_key.nil? || scope_attributes?
|
164
272
|
|
165
273
|
id = ids.first
|
166
274
|
|
@@ -172,56 +280,86 @@ module ActiveRecord
|
|
172
280
|
where(key => params.bind).limit(1)
|
173
281
|
}
|
174
282
|
|
175
|
-
|
176
|
-
|
177
|
-
raise RecordNotFound.new("Couldn't find #{name} with '#{primary_key}'=#{id}",
|
178
|
-
name, primary_key, id)
|
179
|
-
end
|
180
|
-
record
|
181
|
-
rescue ::RangeError
|
182
|
-
raise RecordNotFound.new("Couldn't find #{name} with an out of range value for '#{primary_key}'",
|
183
|
-
name, primary_key)
|
283
|
+
statement.execute([id], connection).first ||
|
284
|
+
raise(RecordNotFound.new("Couldn't find #{name} with '#{key}'=#{id}", name, key, id))
|
184
285
|
end
|
185
286
|
|
186
287
|
def find_by(*args) # :nodoc:
|
187
|
-
return super if scope_attributes?
|
188
|
-
columns_hash.key?(inheritance_column) && base_class != self
|
288
|
+
return super if scope_attributes?
|
189
289
|
|
190
290
|
hash = args.first
|
291
|
+
return super unless Hash === hash
|
191
292
|
|
192
|
-
|
193
|
-
|
194
|
-
|
293
|
+
hash = hash.each_with_object({}) do |(key, value), h|
|
294
|
+
key = key.to_s
|
295
|
+
key = attribute_aliases[key] || key
|
195
296
|
|
196
|
-
|
197
|
-
return super unless hash.keys.all? { |k| columns_hash.has_key?(k.to_s) }
|
297
|
+
return super if reflect_on_aggregation(key)
|
198
298
|
|
199
|
-
|
299
|
+
reflection = _reflect_on_association(key)
|
300
|
+
|
301
|
+
if !reflection
|
302
|
+
value = value.id if value.respond_to?(:id)
|
303
|
+
elsif reflection.belongs_to? && !reflection.polymorphic?
|
304
|
+
key = reflection.join_foreign_key
|
305
|
+
pkey = reflection.join_primary_key
|
306
|
+
value = value.public_send(pkey) if value.respond_to?(pkey)
|
307
|
+
end
|
308
|
+
|
309
|
+
if !columns_hash.key?(key) || StatementCache.unsupported_value?(value)
|
310
|
+
return super
|
311
|
+
end
|
312
|
+
|
313
|
+
h[key] = value
|
314
|
+
end
|
200
315
|
|
316
|
+
keys = hash.keys
|
201
317
|
statement = cached_find_by_statement(keys) { |params|
|
202
|
-
wheres = keys.
|
203
|
-
o[param] = params.bind
|
204
|
-
}
|
318
|
+
wheres = keys.index_with { params.bind }
|
205
319
|
where(wheres).limit(1)
|
206
320
|
}
|
321
|
+
|
207
322
|
begin
|
208
323
|
statement.execute(hash.values, connection).first
|
209
324
|
rescue TypeError
|
210
325
|
raise ActiveRecord::StatementInvalid
|
211
|
-
rescue ::RangeError
|
212
|
-
nil
|
213
326
|
end
|
214
327
|
end
|
215
328
|
|
216
329
|
def find_by!(*args) # :nodoc:
|
217
|
-
find_by(*args) ||
|
330
|
+
find_by(*args) || where(*args).raise_record_not_found_exception!
|
331
|
+
end
|
332
|
+
|
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
|
218
356
|
end
|
219
357
|
|
220
358
|
def initialize_generated_modules # :nodoc:
|
221
359
|
generated_association_methods
|
222
360
|
end
|
223
361
|
|
224
|
-
def generated_association_methods
|
362
|
+
def generated_association_methods # :nodoc:
|
225
363
|
@generated_association_methods ||= begin
|
226
364
|
mod = const_set(:GeneratedAssociationMethods, Module.new)
|
227
365
|
private_constant :GeneratedAssociationMethods
|
@@ -231,8 +369,34 @@ module ActiveRecord
|
|
231
369
|
end
|
232
370
|
end
|
233
371
|
|
372
|
+
# Returns columns which shouldn't be exposed while calling +#inspect+.
|
373
|
+
def filter_attributes
|
374
|
+
if defined?(@filter_attributes)
|
375
|
+
@filter_attributes
|
376
|
+
else
|
377
|
+
superclass.filter_attributes
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
# Specifies columns which shouldn't be exposed while calling +#inspect+.
|
382
|
+
def filter_attributes=(filter_attributes)
|
383
|
+
@inspection_filter = nil
|
384
|
+
@filter_attributes = filter_attributes
|
385
|
+
end
|
386
|
+
|
387
|
+
def inspection_filter # :nodoc:
|
388
|
+
if defined?(@filter_attributes)
|
389
|
+
@inspection_filter ||= begin
|
390
|
+
mask = InspectionMask.new(ActiveSupport::ParameterFilter::FILTERED)
|
391
|
+
ActiveSupport::ParameterFilter.new(@filter_attributes, mask: mask)
|
392
|
+
end
|
393
|
+
else
|
394
|
+
superclass.inspection_filter
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
234
398
|
# Returns a string like 'Post(id:integer, title:string, body:text)'
|
235
|
-
def inspect
|
399
|
+
def inspect # :nodoc:
|
236
400
|
if self == Base
|
237
401
|
super
|
238
402
|
elsif abstract_class?
|
@@ -248,22 +412,13 @@ module ActiveRecord
|
|
248
412
|
end
|
249
413
|
|
250
414
|
# Overwrite the default class equality method to provide support for decorated models.
|
251
|
-
def ===(object)
|
415
|
+
def ===(object) # :nodoc:
|
252
416
|
object.is_a?(self)
|
253
417
|
end
|
254
418
|
|
255
419
|
# Returns an instance of <tt>Arel::Table</tt> loaded with the current table name.
|
256
|
-
#
|
257
|
-
# class Post < ActiveRecord::Base
|
258
|
-
# scope :published_and_commented, -> { published.and(arel_table[:comments_count].gt(0)) }
|
259
|
-
# end
|
260
420
|
def arel_table # :nodoc:
|
261
|
-
@arel_table ||= Arel::Table.new(table_name,
|
262
|
-
end
|
263
|
-
|
264
|
-
def arel_attribute(name, table = arel_table) # :nodoc:
|
265
|
-
name = attribute_alias(name) if attribute_alias?(name)
|
266
|
-
table[name]
|
421
|
+
@arel_table ||= Arel::Table.new(table_name, klass: self)
|
267
422
|
end
|
268
423
|
|
269
424
|
def predicate_builder # :nodoc:
|
@@ -274,19 +429,17 @@ module ActiveRecord
|
|
274
429
|
TypeCaster::Map.new(self)
|
275
430
|
end
|
276
431
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
cache.compute_if_absent(key) { StatementCache.create(connection, &block) }
|
282
|
-
end
|
432
|
+
def cached_find_by_statement(key, &block) # :nodoc:
|
433
|
+
cache = @find_by_statement_cache[connection.prepared_statements]
|
434
|
+
cache.compute_if_absent(key) { StatementCache.create(connection, &block) }
|
435
|
+
end
|
283
436
|
|
437
|
+
private
|
284
438
|
def relation
|
285
439
|
relation = Relation.create(self)
|
286
440
|
|
287
441
|
if finder_needs_type_condition? && !ignore_default_scope?
|
288
442
|
relation.where!(type_condition)
|
289
|
-
relation.create_with!(inheritance_column.to_s => sti_name)
|
290
443
|
else
|
291
444
|
relation
|
292
445
|
end
|
@@ -306,7 +459,7 @@ module ActiveRecord
|
|
306
459
|
# # Instantiates a single new object
|
307
460
|
# User.new(first_name: 'Jamie')
|
308
461
|
def initialize(attributes = nil)
|
309
|
-
|
462
|
+
@new_record = true
|
310
463
|
@attributes = self.class._default_attributes.deep_dup
|
311
464
|
|
312
465
|
init_internals
|
@@ -332,15 +485,21 @@ module ActiveRecord
|
|
332
485
|
# post = Post.allocate
|
333
486
|
# post.init_with(coder)
|
334
487
|
# post.title # => 'hello world'
|
335
|
-
def init_with(coder)
|
336
|
-
coder = LegacyYamlAdapter.convert(
|
337
|
-
|
338
|
-
|
339
|
-
|
488
|
+
def init_with(coder, &block)
|
489
|
+
coder = LegacyYamlAdapter.convert(coder)
|
490
|
+
attributes = self.class.yaml_encoder.decode(coder)
|
491
|
+
init_with_attributes(attributes, coder["new_record"], &block)
|
492
|
+
end
|
340
493
|
|
341
|
-
|
494
|
+
##
|
495
|
+
# Initialize an empty model object from +attributes+.
|
496
|
+
# +attributes+ should be an attributes object, and unlike the
|
497
|
+
# `initialize` method, no assignment calls are made per attribute.
|
498
|
+
def init_with_attributes(attributes, new_record = false) # :nodoc:
|
499
|
+
@new_record = new_record
|
500
|
+
@attributes = attributes
|
342
501
|
|
343
|
-
|
502
|
+
init_internals
|
344
503
|
|
345
504
|
yield self if block_given?
|
346
505
|
|
@@ -379,14 +538,14 @@ module ActiveRecord
|
|
379
538
|
##
|
380
539
|
def initialize_dup(other) # :nodoc:
|
381
540
|
@attributes = @attributes.deep_dup
|
382
|
-
@attributes.reset(
|
541
|
+
@attributes.reset(@primary_key)
|
383
542
|
|
384
543
|
_run_initialize_callbacks
|
385
544
|
|
386
545
|
@new_record = true
|
546
|
+
@previously_new_record = false
|
387
547
|
@destroyed = false
|
388
|
-
@_start_transaction_state =
|
389
|
-
@transaction_state = nil
|
548
|
+
@_start_transaction_state = nil
|
390
549
|
|
391
550
|
super
|
392
551
|
end
|
@@ -429,6 +588,8 @@ module ActiveRecord
|
|
429
588
|
# Delegates to id in order to allow two records of the same type and id to work with something like:
|
430
589
|
# [ Person.find(1), Person.find(2), Person.find(3) ] & [ Person.find(1), Person.find(4) ] # => [ Person.find(1) ]
|
431
590
|
def hash
|
591
|
+
id = self.id
|
592
|
+
|
432
593
|
if id
|
433
594
|
self.class.hash ^ id.hash
|
434
595
|
else
|
@@ -458,12 +619,61 @@ module ActiveRecord
|
|
458
619
|
end
|
459
620
|
end
|
460
621
|
|
461
|
-
|
462
|
-
|
622
|
+
def present? # :nodoc:
|
623
|
+
true
|
624
|
+
end
|
625
|
+
|
626
|
+
def blank? # :nodoc:
|
627
|
+
false
|
628
|
+
end
|
629
|
+
|
630
|
+
# Returns +true+ if the record is read only.
|
463
631
|
def readonly?
|
464
632
|
@readonly
|
465
633
|
end
|
466
634
|
|
635
|
+
# Returns +true+ if the record is in strict_loading mode.
|
636
|
+
def strict_loading?
|
637
|
+
@strict_loading
|
638
|
+
end
|
639
|
+
|
640
|
+
# Sets the record to strict_loading mode. This will raise an error
|
641
|
+
# if the record tries to lazily load an association.
|
642
|
+
#
|
643
|
+
# user = User.first
|
644
|
+
# user.strict_loading! # => true
|
645
|
+
# user.comments
|
646
|
+
# => ActiveRecord::StrictLoadingViolationError
|
647
|
+
#
|
648
|
+
# === Parameters:
|
649
|
+
#
|
650
|
+
# * value - Boolean specifying whether to enable or disable strict loading.
|
651
|
+
# * mode - Symbol specifying strict loading mode. Defaults to :all. Using
|
652
|
+
# :n_plus_one_only mode will only raise an error if an association
|
653
|
+
# that will lead to an n plus one query is lazily loaded.
|
654
|
+
#
|
655
|
+
# === Example:
|
656
|
+
#
|
657
|
+
# user = User.first
|
658
|
+
# user.strict_loading!(false) # => false
|
659
|
+
# user.comments
|
660
|
+
# => #<ActiveRecord::Associations::CollectionProxy>
|
661
|
+
def strict_loading!(value = true, mode: :all)
|
662
|
+
unless [:all, :n_plus_one_only].include?(mode)
|
663
|
+
raise ArgumentError, "The :mode option must be one of [:all, :n_plus_one_only]."
|
664
|
+
end
|
665
|
+
|
666
|
+
@strict_loading_mode = mode
|
667
|
+
@strict_loading = value
|
668
|
+
end
|
669
|
+
|
670
|
+
attr_reader :strict_loading_mode
|
671
|
+
|
672
|
+
# Returns +true+ if the record uses strict_loading with +:n_plus_one_only+ mode enabled.
|
673
|
+
def strict_loading_n_plus_one_only?
|
674
|
+
@strict_loading_mode == :n_plus_one_only
|
675
|
+
end
|
676
|
+
|
467
677
|
# Marks this record as read only.
|
468
678
|
def readonly!
|
469
679
|
@readonly = true
|
@@ -478,11 +688,11 @@ module ActiveRecord
|
|
478
688
|
# We check defined?(@attributes) not to issue warnings if the object is
|
479
689
|
# allocated but not initialized.
|
480
690
|
inspection = if defined?(@attributes) && @attributes
|
481
|
-
self.class.attribute_names.
|
482
|
-
if
|
691
|
+
self.class.attribute_names.filter_map do |name|
|
692
|
+
if _has_attribute?(name)
|
483
693
|
"#{name}: #{attribute_for_inspect(name)}"
|
484
694
|
end
|
485
|
-
end.
|
695
|
+
end.join(", ")
|
486
696
|
else
|
487
697
|
"not initialized"
|
488
698
|
end
|
@@ -496,15 +706,16 @@ module ActiveRecord
|
|
496
706
|
return super if custom_inspect_method_defined?
|
497
707
|
pp.object_address_group(self) do
|
498
708
|
if defined?(@attributes) && @attributes
|
499
|
-
|
500
|
-
pp.seplist(
|
501
|
-
column_value = read_attribute(column_name)
|
709
|
+
attr_names = self.class.attribute_names.select { |name| _has_attribute?(name) }
|
710
|
+
pp.seplist(attr_names, proc { pp.text "," }) do |attr_name|
|
502
711
|
pp.breakable " "
|
503
712
|
pp.group(1) do
|
504
|
-
pp.text
|
713
|
+
pp.text attr_name
|
505
714
|
pp.text ":"
|
506
715
|
pp.breakable
|
507
|
-
|
716
|
+
value = _read_attribute(attr_name)
|
717
|
+
value = inspection_filter.filter_param(attr_name, value) unless value.nil?
|
718
|
+
pp.pp value
|
508
719
|
end
|
509
720
|
end
|
510
721
|
else
|
@@ -516,11 +727,15 @@ module ActiveRecord
|
|
516
727
|
|
517
728
|
# Returns a hash of the given methods with their names as keys and returned values as values.
|
518
729
|
def slice(*methods)
|
519
|
-
|
730
|
+
methods.flatten.index_with { |method| public_send(method) }.with_indifferent_access
|
520
731
|
end
|
521
732
|
|
522
|
-
|
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
|
523
737
|
|
738
|
+
private
|
524
739
|
# +Array#flatten+ will call +#to_ary+ (recursively) on each of the elements of
|
525
740
|
# the array, and then rescues from the possible +NoMethodError+. If those elements are
|
526
741
|
# +ActiveRecord::Base+'s, then this triggers the various +method_missing+'s that we have,
|
@@ -535,25 +750,37 @@ module ActiveRecord
|
|
535
750
|
|
536
751
|
def init_internals
|
537
752
|
@readonly = false
|
753
|
+
@previously_new_record = false
|
538
754
|
@destroyed = false
|
539
755
|
@marked_for_destruction = false
|
540
756
|
@destroyed_by_association = nil
|
541
|
-
@
|
542
|
-
|
543
|
-
|
757
|
+
@_start_transaction_state = nil
|
758
|
+
|
759
|
+
klass = self.class
|
760
|
+
|
761
|
+
@primary_key = klass.primary_key
|
762
|
+
@strict_loading = klass.strict_loading_by_default
|
763
|
+
@strict_loading_mode = :all
|
764
|
+
|
765
|
+
klass.define_attribute_methods
|
544
766
|
end
|
545
767
|
|
546
768
|
def initialize_internals_callback
|
547
769
|
end
|
548
770
|
|
549
|
-
def
|
550
|
-
|
551
|
-
|
771
|
+
def custom_inspect_method_defined?
|
772
|
+
self.class.instance_method(:inspect).owner != ActiveRecord::Base.instance_method(:inspect).owner
|
773
|
+
end
|
774
|
+
|
775
|
+
class InspectionMask < DelegateClass(::String)
|
776
|
+
def pretty_print(pp)
|
777
|
+
pp.text __getobj__
|
552
778
|
end
|
553
779
|
end
|
780
|
+
private_constant :InspectionMask
|
554
781
|
|
555
|
-
def
|
556
|
-
self.class.
|
782
|
+
def inspection_filter
|
783
|
+
self.class.inspection_filter
|
557
784
|
end
|
558
785
|
end
|
559
786
|
end
|