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
@@ -9,5 +9,25 @@ module ActiveRecord::Associations
|
|
9
9
|
false
|
10
10
|
end
|
11
11
|
end
|
12
|
+
|
13
|
+
def nullified_owner_attributes
|
14
|
+
Hash.new.tap do |attrs|
|
15
|
+
attrs[reflection.foreign_key] = nil
|
16
|
+
attrs[reflection.type] = nil if reflection.type.present?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
# Sets the owner attributes on the given record
|
22
|
+
def set_owner_attributes(record)
|
23
|
+
return if options[:through]
|
24
|
+
|
25
|
+
key = owner._read_attribute(reflection.join_foreign_key)
|
26
|
+
record._write_attribute(reflection.join_primary_key, key)
|
27
|
+
|
28
|
+
if reflection.type
|
29
|
+
record._write_attribute(reflection.type, owner.class.polymorphic_name)
|
30
|
+
end
|
31
|
+
end
|
12
32
|
end
|
13
33
|
end
|
@@ -7,7 +7,7 @@ module ActiveRecord
|
|
7
7
|
#
|
8
8
|
# If the association has a <tt>:through</tt> option further specialization
|
9
9
|
# is provided by its child HasManyThroughAssociation.
|
10
|
-
class HasManyAssociation < CollectionAssociation
|
10
|
+
class HasManyAssociation < CollectionAssociation # :nodoc:
|
11
11
|
include ForeignAssociation
|
12
12
|
|
13
13
|
def handle_dependency
|
@@ -26,6 +26,28 @@ module ActiveRecord
|
|
26
26
|
# No point in executing the counter update since we're going to destroy the parent anyway
|
27
27
|
load_target.each { |t| t.destroyed_by_association = reflection }
|
28
28
|
destroy_all
|
29
|
+
when :destroy_async
|
30
|
+
load_target.each do |t|
|
31
|
+
t.destroyed_by_association = reflection
|
32
|
+
end
|
33
|
+
|
34
|
+
unless target.empty?
|
35
|
+
association_class = target.first.class
|
36
|
+
primary_key_column = association_class.primary_key.to_sym
|
37
|
+
|
38
|
+
ids = target.collect do |assoc|
|
39
|
+
assoc.public_send(primary_key_column)
|
40
|
+
end
|
41
|
+
|
42
|
+
enqueue_destroy_association(
|
43
|
+
owner_model_name: owner.class.to_s,
|
44
|
+
owner_id: owner.id,
|
45
|
+
association_class: reflection.klass.to_s,
|
46
|
+
association_ids: ids,
|
47
|
+
association_primary_key_column: primary_key_column,
|
48
|
+
ensuring_owner_was_method: options.fetch(:ensuring_owner_was, nil)
|
49
|
+
)
|
50
|
+
end
|
29
51
|
else
|
30
52
|
delete_all
|
31
53
|
end
|
@@ -36,16 +58,7 @@ module ActiveRecord
|
|
36
58
|
super
|
37
59
|
end
|
38
60
|
|
39
|
-
def empty?
|
40
|
-
if reflection.has_cached_counter?
|
41
|
-
size.zero?
|
42
|
-
else
|
43
|
-
super
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
61
|
private
|
48
|
-
|
49
62
|
# Returns the number of records in this collection.
|
50
63
|
#
|
51
64
|
# If the association has a counter cache it gets that value. Otherwise
|
@@ -61,7 +74,7 @@ module ActiveRecord
|
|
61
74
|
# the loaded flag is set to true as well.
|
62
75
|
def count_records
|
63
76
|
count = if reflection.has_cached_counter?
|
64
|
-
owner.
|
77
|
+
owner.read_attribute(reflection.counter_cache_column).to_i
|
65
78
|
else
|
66
79
|
scope.count(:all)
|
67
80
|
end
|
@@ -69,7 +82,7 @@ module ActiveRecord
|
|
69
82
|
# If there's nothing in the database and @target has no new records
|
70
83
|
# we are certain the current target is an empty array. This is a
|
71
84
|
# documented side-effect of the method that may avoid an extra SELECT.
|
72
|
-
|
85
|
+
loaded! if count == 0
|
73
86
|
|
74
87
|
[association_scope.limit_value, count].compact.min
|
75
88
|
end
|
@@ -84,7 +97,7 @@ module ActiveRecord
|
|
84
97
|
if reflection.counter_must_be_updated_by_has_many?
|
85
98
|
counter = reflection.counter_cache_column
|
86
99
|
owner.increment(counter, difference)
|
87
|
-
owner.send(:
|
100
|
+
owner.send(:"clear_#{counter}_change")
|
88
101
|
end
|
89
102
|
end
|
90
103
|
|
@@ -92,7 +105,7 @@ module ActiveRecord
|
|
92
105
|
if method == :delete_all
|
93
106
|
scope.delete_all
|
94
107
|
else
|
95
|
-
scope.update_all(
|
108
|
+
scope.update_all(nullified_owner_attributes)
|
96
109
|
end
|
97
110
|
end
|
98
111
|
|
@@ -3,12 +3,12 @@
|
|
3
3
|
module ActiveRecord
|
4
4
|
module Associations
|
5
5
|
# = Active Record Has Many Through Association
|
6
|
-
class HasManyThroughAssociation < HasManyAssociation
|
6
|
+
class HasManyThroughAssociation < HasManyAssociation # :nodoc:
|
7
7
|
include ThroughAssociation
|
8
8
|
|
9
9
|
def initialize(owner, reflection)
|
10
10
|
super
|
11
|
-
@through_records = {}
|
11
|
+
@through_records = {}.compare_by_identity
|
12
12
|
end
|
13
13
|
|
14
14
|
def concat(*records)
|
@@ -21,20 +21,6 @@ module ActiveRecord
|
|
21
21
|
super
|
22
22
|
end
|
23
23
|
|
24
|
-
def concat_records(records)
|
25
|
-
ensure_not_nested
|
26
|
-
|
27
|
-
records = super(records, true)
|
28
|
-
|
29
|
-
if owner.new_record? && records
|
30
|
-
records.flatten.each do |record|
|
31
|
-
build_through_record(record)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
records
|
36
|
-
end
|
37
|
-
|
38
24
|
def insert_record(record, validate = true, raise = false)
|
39
25
|
ensure_not_nested
|
40
26
|
|
@@ -48,13 +34,27 @@ module ActiveRecord
|
|
48
34
|
end
|
49
35
|
|
50
36
|
private
|
37
|
+
def concat_records(records)
|
38
|
+
ensure_not_nested
|
39
|
+
|
40
|
+
records = super(records, true)
|
41
|
+
|
42
|
+
if owner.new_record? && records
|
43
|
+
records.flatten.each do |record|
|
44
|
+
build_through_record(record)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
records
|
49
|
+
end
|
50
|
+
|
51
51
|
# The through record (built with build_record) is temporarily cached
|
52
52
|
# so that it may be reused if insert_record is subsequently called.
|
53
53
|
#
|
54
54
|
# However, after insert_record has been called, the cache is cleared in
|
55
55
|
# order to allow multiple instances of the same record in an association.
|
56
56
|
def build_through_record(record)
|
57
|
-
@through_records[record
|
57
|
+
@through_records[record] ||= begin
|
58
58
|
ensure_mutable
|
59
59
|
|
60
60
|
attributes = through_scope_attributes
|
@@ -65,7 +65,10 @@ module ActiveRecord
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
|
+
attr_reader :through_scope
|
69
|
+
|
68
70
|
def through_scope_attributes
|
71
|
+
scope = through_scope || self.scope
|
69
72
|
scope.where_values_hash(through_association.reflection.name.to_s).
|
70
73
|
except!(through_association.reflection.foreign_key,
|
71
74
|
through_association.reflection.klass.inheritance_column)
|
@@ -77,12 +80,13 @@ module ActiveRecord
|
|
77
80
|
association.save!
|
78
81
|
end
|
79
82
|
ensure
|
80
|
-
@through_records.delete(record
|
83
|
+
@through_records.delete(record)
|
81
84
|
end
|
82
85
|
|
83
86
|
def build_record(attributes)
|
84
87
|
ensure_not_nested
|
85
88
|
|
89
|
+
@through_scope = scope
|
86
90
|
record = super
|
87
91
|
|
88
92
|
inverse = source_reflection.inverse_of
|
@@ -95,6 +99,8 @@ module ActiveRecord
|
|
95
99
|
end
|
96
100
|
|
97
101
|
record
|
102
|
+
ensure
|
103
|
+
@through_scope = nil
|
98
104
|
end
|
99
105
|
|
100
106
|
def remove_records(existing_records, records, method)
|
@@ -202,12 +208,13 @@ module ActiveRecord
|
|
202
208
|
end
|
203
209
|
end
|
204
210
|
|
205
|
-
@through_records.delete(record
|
211
|
+
@through_records.delete(record)
|
206
212
|
end
|
207
213
|
end
|
208
214
|
|
209
215
|
def find_target
|
210
216
|
return [] unless target_reflection_has_associated_record?
|
217
|
+
return scope.to_a if disable_joins
|
211
218
|
super
|
212
219
|
end
|
213
220
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module ActiveRecord
|
4
4
|
module Associations
|
5
5
|
# = Active Record Has One Association
|
6
|
-
class HasOneAssociation < SingularAssociation
|
6
|
+
class HasOneAssociation < SingularAssociation # :nodoc:
|
7
7
|
include ForeignAssociation
|
8
8
|
|
9
9
|
def handle_dependency
|
@@ -23,35 +23,6 @@ module ActiveRecord
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
def replace(record, save = true)
|
27
|
-
raise_on_type_mismatch!(record) if record
|
28
|
-
load_target
|
29
|
-
|
30
|
-
return target unless target || record
|
31
|
-
|
32
|
-
assigning_another_record = target != record
|
33
|
-
if assigning_another_record || record.has_changes_to_save?
|
34
|
-
save &&= owner.persisted?
|
35
|
-
|
36
|
-
transaction_if(save) do
|
37
|
-
remove_target!(options[:dependent]) if target && !target.destroyed? && assigning_another_record
|
38
|
-
|
39
|
-
if record
|
40
|
-
set_owner_attributes(record)
|
41
|
-
set_inverse_instance(record)
|
42
|
-
|
43
|
-
if save && !record.save
|
44
|
-
nullify_owner_attributes(record)
|
45
|
-
set_owner_attributes(target) if target
|
46
|
-
raise RecordNotSaved, "Failed to save the new associated #{reflection.name}."
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
self.target = record
|
53
|
-
end
|
54
|
-
|
55
26
|
def delete(method = options[:dependent])
|
56
27
|
if load_target
|
57
28
|
case method
|
@@ -61,13 +32,52 @@ module ActiveRecord
|
|
61
32
|
target.destroyed_by_association = reflection
|
62
33
|
target.destroy
|
63
34
|
throw(:abort) unless target.destroyed?
|
35
|
+
when :destroy_async
|
36
|
+
primary_key_column = target.class.primary_key.to_sym
|
37
|
+
id = target.public_send(primary_key_column)
|
38
|
+
|
39
|
+
enqueue_destroy_association(
|
40
|
+
owner_model_name: owner.class.to_s,
|
41
|
+
owner_id: owner.id,
|
42
|
+
association_class: reflection.klass.to_s,
|
43
|
+
association_ids: [id],
|
44
|
+
association_primary_key_column: primary_key_column,
|
45
|
+
ensuring_owner_was_method: options.fetch(:ensuring_owner_was, nil)
|
46
|
+
)
|
64
47
|
when :nullify
|
65
|
-
target.update_columns(
|
48
|
+
target.update_columns(nullified_owner_attributes) if target.persisted?
|
66
49
|
end
|
67
50
|
end
|
68
51
|
end
|
69
52
|
|
70
53
|
private
|
54
|
+
def replace(record, save = true)
|
55
|
+
raise_on_type_mismatch!(record) if record
|
56
|
+
|
57
|
+
return target unless load_target || record
|
58
|
+
|
59
|
+
assigning_another_record = target != record
|
60
|
+
if assigning_another_record || record.has_changes_to_save?
|
61
|
+
save &&= owner.persisted?
|
62
|
+
|
63
|
+
transaction_if(save) do
|
64
|
+
remove_target!(options[:dependent]) if target && !target.destroyed? && assigning_another_record
|
65
|
+
|
66
|
+
if record
|
67
|
+
set_owner_attributes(record)
|
68
|
+
set_inverse_instance(record)
|
69
|
+
|
70
|
+
if save && !record.save
|
71
|
+
nullify_owner_attributes(record)
|
72
|
+
set_owner_attributes(target) if target
|
73
|
+
raise RecordNotSaved.new("Failed to save the new associated #{reflection.name}.", record)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
self.target = record
|
80
|
+
end
|
71
81
|
|
72
82
|
# The reason that the save param for replace is false, if for create (not just build),
|
73
83
|
# is because the setting of the foreign keys is actually handled by the scoping when
|
@@ -83,15 +93,20 @@ module ActiveRecord
|
|
83
93
|
target.delete
|
84
94
|
when :destroy
|
85
95
|
target.destroyed_by_association = reflection
|
86
|
-
target.
|
96
|
+
if target.persisted?
|
97
|
+
target.destroy
|
98
|
+
end
|
87
99
|
else
|
88
100
|
nullify_owner_attributes(target)
|
89
101
|
remove_inverse_instance(target)
|
90
102
|
|
91
103
|
if target.persisted? && owner.persisted? && !target.save
|
92
104
|
set_owner_attributes(target)
|
93
|
-
raise RecordNotSaved
|
94
|
-
|
105
|
+
raise RecordNotSaved.new(
|
106
|
+
"Failed to remove the existing associated #{reflection.name}. " \
|
107
|
+
"The record failed to save after its foreign key was set to nil.",
|
108
|
+
target
|
109
|
+
)
|
95
110
|
end
|
96
111
|
end
|
97
112
|
end
|
@@ -100,9 +115,9 @@ module ActiveRecord
|
|
100
115
|
record[reflection.foreign_key] = nil
|
101
116
|
end
|
102
117
|
|
103
|
-
def transaction_if(value)
|
118
|
+
def transaction_if(value, &block)
|
104
119
|
if value
|
105
|
-
reflection.klass.transaction
|
120
|
+
reflection.klass.transaction(&block)
|
106
121
|
else
|
107
122
|
yield
|
108
123
|
end
|
@@ -110,7 +125,7 @@ module ActiveRecord
|
|
110
125
|
|
111
126
|
def _create_record(attributes, raise_error = false, &block)
|
112
127
|
unless owner.persisted?
|
113
|
-
raise ActiveRecord::RecordNotSaved
|
128
|
+
raise ActiveRecord::RecordNotSaved.new("You cannot call create unless the parent is saved", owner)
|
114
129
|
end
|
115
130
|
|
116
131
|
super
|
@@ -3,15 +3,15 @@
|
|
3
3
|
module ActiveRecord
|
4
4
|
module Associations
|
5
5
|
# = Active Record Has One Through Association
|
6
|
-
class HasOneThroughAssociation < HasOneAssociation
|
6
|
+
class HasOneThroughAssociation < HasOneAssociation # :nodoc:
|
7
7
|
include ThroughAssociation
|
8
8
|
|
9
|
-
def replace(record, save = true)
|
10
|
-
create_through_record(record, save)
|
11
|
-
self.target = record
|
12
|
-
end
|
13
|
-
|
14
9
|
private
|
10
|
+
def replace(record, save = true)
|
11
|
+
create_through_record(record, save)
|
12
|
+
self.target = record
|
13
|
+
end
|
14
|
+
|
15
15
|
def create_through_record(record, save)
|
16
16
|
ensure_not_nested
|
17
17
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_record/associations/join_dependency/join_part"
|
4
|
+
require "active_support/core_ext/array/extract"
|
4
5
|
|
5
6
|
module ActiveRecord
|
6
7
|
module Associations
|
@@ -13,7 +14,6 @@ module ActiveRecord
|
|
13
14
|
super(reflection.klass, children)
|
14
15
|
|
15
16
|
@reflection = reflection
|
16
|
-
@tables = nil
|
17
17
|
end
|
18
18
|
|
19
19
|
def match?(other)
|
@@ -23,26 +23,47 @@ module ActiveRecord
|
|
23
23
|
|
24
24
|
def join_constraints(foreign_table, foreign_klass, join_type, alias_tracker)
|
25
25
|
joins = []
|
26
|
+
chain = []
|
27
|
+
|
28
|
+
reflection.chain.each do |reflection|
|
29
|
+
table, terminated = yield reflection
|
30
|
+
@table ||= table
|
31
|
+
|
32
|
+
if terminated
|
33
|
+
foreign_table, foreign_klass = table, reflection.klass
|
34
|
+
break
|
35
|
+
end
|
36
|
+
|
37
|
+
chain << [reflection, table]
|
38
|
+
end
|
26
39
|
|
27
40
|
# The chain starts with the target table, but we want to end with it here (makes
|
28
41
|
# more sense in this context), so we reverse
|
29
|
-
|
30
|
-
table = tables[-i]
|
42
|
+
chain.reverse_each do |reflection, table|
|
31
43
|
klass = reflection.klass
|
32
44
|
|
33
|
-
|
45
|
+
scope = reflection.join_scope(table, foreign_table, foreign_klass)
|
46
|
+
|
47
|
+
unless scope.references_values.empty?
|
48
|
+
associations = scope.eager_load_values | scope.includes_values
|
49
|
+
|
50
|
+
unless associations.empty?
|
51
|
+
scope.joins! scope.construct_join_dependency(associations, Arel::Nodes::OuterJoin)
|
52
|
+
end
|
53
|
+
end
|
34
54
|
|
35
|
-
arel =
|
55
|
+
arel = scope.arel(alias_tracker.aliases)
|
36
56
|
nodes = arel.constraints.first
|
37
57
|
|
38
|
-
|
39
|
-
|
58
|
+
if nodes.is_a?(Arel::Nodes::And)
|
59
|
+
others = nodes.children.extract! do |node|
|
60
|
+
!Arel.fetch_attribute(node) { |attr| attr.relation.name == table.name }
|
61
|
+
end
|
40
62
|
end
|
41
|
-
nodes = table.create_and(children)
|
42
63
|
|
43
|
-
joins <<
|
64
|
+
joins << join_type.new(table, Arel::Nodes::On.new(nodes))
|
44
65
|
|
45
|
-
|
66
|
+
if others && !others.empty?
|
46
67
|
joins.concat arel.join_sources
|
47
68
|
append_constraints(joins.last, others)
|
48
69
|
end
|
@@ -54,25 +75,26 @@ module ActiveRecord
|
|
54
75
|
joins
|
55
76
|
end
|
56
77
|
|
57
|
-
def
|
58
|
-
@
|
59
|
-
|
78
|
+
def readonly?
|
79
|
+
return @readonly if defined?(@readonly)
|
80
|
+
|
81
|
+
@readonly = reflection.scope && reflection.scope_for(base_klass.unscoped).readonly_value
|
60
82
|
end
|
61
83
|
|
62
|
-
|
63
|
-
|
64
|
-
case value
|
65
|
-
when Arel::Nodes::Between, Arel::Nodes::In, Arel::Nodes::NotIn, Arel::Nodes::Equality, Arel::Nodes::NotEqual, Arel::Nodes::LessThan, Arel::Nodes::LessThanOrEqual, Arel::Nodes::GreaterThan, Arel::Nodes::GreaterThanOrEqual
|
66
|
-
yield value.left.is_a?(Arel::Attributes::Attribute) ? value.left : value.right
|
67
|
-
end
|
68
|
-
end
|
84
|
+
def strict_loading?
|
85
|
+
return @strict_loading if defined?(@strict_loading)
|
69
86
|
|
87
|
+
@strict_loading = reflection.scope && reflection.scope_for(base_klass.unscoped).strict_loading_value
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
70
91
|
def append_constraints(join, constraints)
|
71
92
|
if join.is_a?(Arel::Nodes::StringJoin)
|
72
|
-
join_string =
|
93
|
+
join_string = Arel::Nodes::And.new(constraints.unshift join.left)
|
73
94
|
join.left = Arel.sql(base_klass.connection.visitor.compile(join_string))
|
74
95
|
else
|
75
|
-
join.right
|
96
|
+
right = join.right
|
97
|
+
right.expr = Arel::Nodes::And.new(constraints.unshift right.expr)
|
76
98
|
end
|
77
99
|
end
|
78
100
|
end
|
@@ -17,7 +17,7 @@ module ActiveRecord
|
|
17
17
|
# association.
|
18
18
|
attr_reader :base_klass, :children
|
19
19
|
|
20
|
-
delegate :table_name, :column_names, :primary_key, to: :base_klass
|
20
|
+
delegate :table_name, :column_names, :primary_key, :attribute_types, to: :base_klass
|
21
21
|
|
22
22
|
def initialize(base_klass, children)
|
23
23
|
@base_klass = base_klass
|
@@ -54,16 +54,16 @@ module ActiveRecord
|
|
54
54
|
length = column_names_with_alias.length
|
55
55
|
|
56
56
|
while index < length
|
57
|
-
|
58
|
-
hash[
|
57
|
+
column = column_names_with_alias[index]
|
58
|
+
hash[column.name] = row[column.alias]
|
59
59
|
index += 1
|
60
60
|
end
|
61
61
|
|
62
62
|
hash
|
63
63
|
end
|
64
64
|
|
65
|
-
def instantiate(row, aliases, &block)
|
66
|
-
base_klass.instantiate(extract_record(row, aliases), &block)
|
65
|
+
def instantiate(row, aliases, column_types = {}, &block)
|
66
|
+
base_klass.instantiate(extract_record(row, aliases), column_types, &block)
|
67
67
|
end
|
68
68
|
end
|
69
69
|
end
|