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/MIT-LICENSE
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
Copyright (c) 2004-
|
1
|
+
Copyright (c) 2004-2022 David Heinemeier Hansson
|
2
|
+
|
3
|
+
Arel originally copyright (c) 2007-2016 Nick Kallen, Bryan Helmkamp, Emilio Tagua, Aaron Patterson
|
2
4
|
|
3
5
|
Permission is hereby granted, free of charge, to any person obtaining
|
4
6
|
a copy of this software and associated documentation files (the
|
data/README.rdoc
CHANGED
@@ -13,6 +13,8 @@ columns. Although these mappings can be defined explicitly, it's recommended
|
|
13
13
|
to follow naming conventions, especially when getting started with the
|
14
14
|
library.
|
15
15
|
|
16
|
+
You can read more about Active Record in the {Active Record Basics}[https://edgeguides.rubyonrails.org/active_record_basics.html] guide.
|
17
|
+
|
16
18
|
A short rundown of some of the major features:
|
17
19
|
|
18
20
|
* Automated mapping between classes and tables, attributes and columns.
|
@@ -130,7 +132,7 @@ This would also define the following accessors: <tt>Product#name</tt> and
|
|
130
132
|
SQLite3[link:classes/ActiveRecord/ConnectionAdapters/SQLite3Adapter.html].
|
131
133
|
|
132
134
|
|
133
|
-
* Logging support for Log4r[https://github.com/colbygk/log4r] and Logger[
|
135
|
+
* Logging support for Log4r[https://github.com/colbygk/log4r] and Logger[https://ruby-doc.org/stdlib/libdoc/logger/rdoc/].
|
134
136
|
|
135
137
|
ActiveRecord::Base.logger = ActiveSupport::Logger.new(STDOUT)
|
136
138
|
ActiveRecord::Base.logger = Log4r::Logger.new('Application Log')
|
@@ -138,7 +140,7 @@ This would also define the following accessors: <tt>Product#name</tt> and
|
|
138
140
|
|
139
141
|
* Database agnostic schema management with Migrations.
|
140
142
|
|
141
|
-
class AddSystemSettings < ActiveRecord::Migration[
|
143
|
+
class AddSystemSettings < ActiveRecord::Migration[7.0]
|
142
144
|
def up
|
143
145
|
create_table :system_settings do |t|
|
144
146
|
t.string :name
|
@@ -192,7 +194,7 @@ The latest version of Active Record can be installed with RubyGems:
|
|
192
194
|
|
193
195
|
Source code can be downloaded as part of the Rails project on GitHub:
|
194
196
|
|
195
|
-
* https://github.com/rails/rails/tree/
|
197
|
+
* https://github.com/rails/rails/tree/main/activerecord
|
196
198
|
|
197
199
|
|
198
200
|
== License
|
@@ -206,7 +208,7 @@ Active Record is released under the MIT license:
|
|
206
208
|
|
207
209
|
API documentation is at:
|
208
210
|
|
209
|
-
*
|
211
|
+
* https://api.rubyonrails.org
|
210
212
|
|
211
213
|
Bug reports for the Ruby on Rails project can be filed here:
|
212
214
|
|
@@ -214,4 +216,4 @@ Bug reports for the Ruby on Rails project can be filed here:
|
|
214
216
|
|
215
217
|
Feature requests should be discussed on the rails-core mailing list here:
|
216
218
|
|
217
|
-
* https://
|
219
|
+
* https://discuss.rubyonrails.org/c/rubyonrails-core
|
data/examples/performance.rb
CHANGED
@@ -3,8 +3,6 @@
|
|
3
3
|
module ActiveRecord
|
4
4
|
# See ActiveRecord::Aggregations::ClassMethods for documentation
|
5
5
|
module Aggregations
|
6
|
-
extend ActiveSupport::Concern
|
7
|
-
|
8
6
|
def initialize_dup(*) # :nodoc:
|
9
7
|
@aggregation_cache = {}
|
10
8
|
super
|
@@ -16,7 +14,6 @@ module ActiveRecord
|
|
16
14
|
end
|
17
15
|
|
18
16
|
private
|
19
|
-
|
20
17
|
def clear_aggregation_cache
|
21
18
|
@aggregation_cache.clear if persisted?
|
22
19
|
end
|
@@ -144,7 +141,7 @@ module ActiveRecord
|
|
144
141
|
# converted to an instance of value class if necessary.
|
145
142
|
#
|
146
143
|
# For example, the +NetworkResource+ model has +network_address+ and +cidr_range+ attributes that should be
|
147
|
-
# aggregated using the +NetAddr::CIDR+ value class (
|
144
|
+
# aggregated using the +NetAddr::CIDR+ value class (https://www.rubydoc.info/gems/netaddr/1.5.0/NetAddr/CIDR).
|
148
145
|
# The constructor for the value class is called +create+ and it expects a CIDR address string as a parameter.
|
149
146
|
# New values can be assigned to the value object using either another +NetAddr::CIDR+ object, a string
|
150
147
|
# or an array. The <tt>:constructor</tt> and <tt>:converter</tt> options can be used to meet
|
@@ -225,6 +222,10 @@ module ActiveRecord
|
|
225
222
|
def composed_of(part_id, options = {})
|
226
223
|
options.assert_valid_keys(:class_name, :mapping, :allow_nil, :constructor, :converter)
|
227
224
|
|
225
|
+
unless self < Aggregations
|
226
|
+
include Aggregations
|
227
|
+
end
|
228
|
+
|
228
229
|
name = part_id.id2name
|
229
230
|
class_name = options[:class_name] || name.camelize
|
230
231
|
mapping = options[:mapping] || [ name, name ]
|
@@ -243,8 +244,8 @@ module ActiveRecord
|
|
243
244
|
private
|
244
245
|
def reader_method(name, class_name, mapping, allow_nil, constructor)
|
245
246
|
define_method(name) do
|
246
|
-
if @aggregation_cache[name].nil? && (!allow_nil || mapping.any? { |key, _| !
|
247
|
-
attrs = mapping.collect { |key, _|
|
247
|
+
if @aggregation_cache[name].nil? && (!allow_nil || mapping.any? { |key, _| !read_attribute(key).nil? })
|
248
|
+
attrs = mapping.collect { |key, _| read_attribute(key) }
|
248
249
|
object = constructor.respond_to?(:call) ?
|
249
250
|
constructor.call(*attrs) :
|
250
251
|
class_name.constantize.send(constructor, *attrs)
|
@@ -263,17 +264,17 @@ module ActiveRecord
|
|
263
264
|
end
|
264
265
|
|
265
266
|
hash_from_multiparameter_assignment = part.is_a?(Hash) &&
|
266
|
-
part.
|
267
|
+
part.keys.all?(Integer)
|
267
268
|
if hash_from_multiparameter_assignment
|
268
269
|
raise ArgumentError unless part.size == part.each_key.max
|
269
270
|
part = klass.new(*part.sort.map(&:last))
|
270
271
|
end
|
271
272
|
|
272
273
|
if part.nil? && allow_nil
|
273
|
-
mapping.each { |key, _|
|
274
|
+
mapping.each { |key, _| write_attribute(key, nil) }
|
274
275
|
@aggregation_cache[name] = nil
|
275
276
|
else
|
276
|
-
mapping.each { |key, value|
|
277
|
+
mapping.each { |key, value| write_attribute(key, part.send(value)) }
|
277
278
|
@aggregation_cache[name] = part.freeze
|
278
279
|
end
|
279
280
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
|
-
class AssociationRelation < Relation
|
5
|
-
def initialize(klass, association)
|
4
|
+
class AssociationRelation < Relation # :nodoc:
|
5
|
+
def initialize(klass, association, **)
|
6
6
|
super(klass)
|
7
7
|
@association = association
|
8
8
|
end
|
@@ -15,20 +15,30 @@ module ActiveRecord
|
|
15
15
|
other == records
|
16
16
|
end
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
scoping { @association.create(*args, &block) }
|
25
|
-
end
|
18
|
+
%w(insert insert_all insert! insert_all! upsert upsert_all).each do |method|
|
19
|
+
class_eval <<~RUBY
|
20
|
+
def #{method}(attributes, **kwargs)
|
21
|
+
if @association.reflection.through_reflection?
|
22
|
+
raise ArgumentError, "Bulk insert or upsert is currently not supported for has_many through association"
|
23
|
+
end
|
26
24
|
|
27
|
-
|
28
|
-
|
25
|
+
scoping { klass.#{method}(attributes, **kwargs) }
|
26
|
+
end
|
27
|
+
RUBY
|
29
28
|
end
|
30
29
|
|
31
30
|
private
|
31
|
+
def _new(attributes, &block)
|
32
|
+
@association.build(attributes, &block)
|
33
|
+
end
|
34
|
+
|
35
|
+
def _create(attributes, &block)
|
36
|
+
@association.create(attributes, &block)
|
37
|
+
end
|
38
|
+
|
39
|
+
def _create!(attributes, &block)
|
40
|
+
@association.create!(attributes, &block)
|
41
|
+
end
|
32
42
|
|
33
43
|
def exec_queries
|
34
44
|
super do |record|
|
@@ -6,9 +6,14 @@ module ActiveRecord
|
|
6
6
|
module Associations
|
7
7
|
# Keeps track of table aliases for ActiveRecord::Associations::JoinDependency
|
8
8
|
class AliasTracker # :nodoc:
|
9
|
-
def self.create(connection, initial_table, joins)
|
9
|
+
def self.create(connection, initial_table, joins, aliases = nil)
|
10
10
|
if joins.empty?
|
11
|
-
aliases
|
11
|
+
aliases ||= Hash.new(0)
|
12
|
+
elsif aliases
|
13
|
+
default_proc = aliases.default_proc || proc { 0 }
|
14
|
+
aliases.default_proc = proc { |h, k|
|
15
|
+
h[k] = initial_count_for(connection, k, joins) + default_proc.call(h, k)
|
16
|
+
}
|
12
17
|
else
|
13
18
|
aliases = Hash.new { |h, k|
|
14
19
|
h[k] = initial_count_for(connection, k, joins)
|
@@ -32,8 +37,6 @@ module ActiveRecord
|
|
32
37
|
).size
|
33
38
|
elsif join.is_a?(Arel::Nodes::Join)
|
34
39
|
join.left.name == name ? 1 : 0
|
35
|
-
elsif join.is_a?(Hash)
|
36
|
-
join[name]
|
37
40
|
else
|
38
41
|
raise ArgumentError, "joins list should be initialized by list of Arel::Nodes::Join"
|
39
42
|
end
|
@@ -48,31 +51,31 @@ module ActiveRecord
|
|
48
51
|
@connection = connection
|
49
52
|
end
|
50
53
|
|
51
|
-
def aliased_table_for(
|
52
|
-
|
54
|
+
def aliased_table_for(arel_table, table_name = nil)
|
55
|
+
table_name ||= arel_table.name
|
56
|
+
|
57
|
+
if aliases[table_name] == 0
|
53
58
|
# If it's zero, we can have our table_name
|
54
59
|
aliases[table_name] = 1
|
55
|
-
|
60
|
+
arel_table = arel_table.alias(table_name) if arel_table.name != table_name
|
56
61
|
else
|
57
62
|
# Otherwise, we need to use an alias
|
58
|
-
aliased_name = @connection.table_alias_for(
|
63
|
+
aliased_name = @connection.table_alias_for(yield)
|
59
64
|
|
60
65
|
# Update the count
|
61
|
-
aliases[aliased_name] += 1
|
66
|
+
count = aliases[aliased_name] += 1
|
62
67
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
aliased_name
|
67
|
-
end
|
68
|
-
Arel::Table.new(table_name, type_caster: type_caster).alias(table_alias)
|
68
|
+
aliased_name = "#{truncate(aliased_name)}_#{count}" if count > 1
|
69
|
+
|
70
|
+
arel_table = arel_table.alias(aliased_name)
|
69
71
|
end
|
72
|
+
|
73
|
+
arel_table
|
70
74
|
end
|
71
75
|
|
72
76
|
attr_reader :aliases
|
73
77
|
|
74
78
|
private
|
75
|
-
|
76
79
|
def truncate(name)
|
77
80
|
name.slice(0, @connection.table_alias_length - 2)
|
78
81
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/core_ext/array/wrap"
|
4
|
-
|
5
3
|
module ActiveRecord
|
6
4
|
module Associations
|
7
5
|
# = Active Record Associations
|
@@ -17,8 +15,25 @@ module ActiveRecord
|
|
17
15
|
# CollectionAssociation
|
18
16
|
# HasManyAssociation + ForeignAssociation
|
19
17
|
# HasManyThroughAssociation + ThroughAssociation
|
20
|
-
|
21
|
-
|
18
|
+
#
|
19
|
+
# Associations in Active Record are middlemen between the object that
|
20
|
+
# holds the association, known as the <tt>owner</tt>, and the associated
|
21
|
+
# result set, known as the <tt>target</tt>. Association metadata is available in
|
22
|
+
# <tt>reflection</tt>, which is an instance of <tt>ActiveRecord::Reflection::AssociationReflection</tt>.
|
23
|
+
#
|
24
|
+
# For example, given
|
25
|
+
#
|
26
|
+
# class Blog < ActiveRecord::Base
|
27
|
+
# has_many :posts
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# blog = Blog.first
|
31
|
+
#
|
32
|
+
# The association of <tt>blog.posts</tt> has the object +blog+ as its
|
33
|
+
# <tt>owner</tt>, the collection of its posts as <tt>target</tt>, and
|
34
|
+
# the <tt>reflection</tt> object represents a <tt>:has_many</tt> macro.
|
35
|
+
class Association # :nodoc:
|
36
|
+
attr_reader :owner, :target, :reflection, :disable_joins
|
22
37
|
|
23
38
|
delegate :options, to: :reflection
|
24
39
|
|
@@ -26,6 +41,7 @@ module ActiveRecord
|
|
26
41
|
reflection.check_validity!
|
27
42
|
|
28
43
|
@owner, @reflection = owner, reflection
|
44
|
+
@disable_joins = @reflection.options[:disable_joins] || false
|
29
45
|
|
30
46
|
reset
|
31
47
|
reset_scope
|
@@ -36,11 +52,16 @@ module ActiveRecord
|
|
36
52
|
@loaded = false
|
37
53
|
@target = nil
|
38
54
|
@stale_state = nil
|
39
|
-
|
55
|
+
end
|
56
|
+
|
57
|
+
def reset_negative_cache # :nodoc:
|
58
|
+
reset if loaded? && target.nil?
|
40
59
|
end
|
41
60
|
|
42
61
|
# Reloads the \target and returns +self+ on success.
|
43
|
-
|
62
|
+
# The QueryCache is cleared if +force+ is true.
|
63
|
+
def reload(force = false)
|
64
|
+
klass.connection.clear_query_cache if force && klass
|
44
65
|
reset
|
45
66
|
reset_scope
|
46
67
|
load_target
|
@@ -56,7 +77,6 @@ module ActiveRecord
|
|
56
77
|
def loaded!
|
57
78
|
@loaded = true
|
58
79
|
@stale_state = stale_state
|
59
|
-
@inversed = false
|
60
80
|
end
|
61
81
|
|
62
82
|
# The target is stale if the target no longer points to the record(s) that the
|
@@ -66,7 +86,7 @@ module ActiveRecord
|
|
66
86
|
#
|
67
87
|
# Note that if the target has not been loaded, it is not considered stale.
|
68
88
|
def stale_target?
|
69
|
-
|
89
|
+
loaded? && @stale_state != stale_state
|
70
90
|
end
|
71
91
|
|
72
92
|
# Sets the target of this association to <tt>\target</tt>, and the \loaded flag to +true+.
|
@@ -76,18 +96,14 @@ module ActiveRecord
|
|
76
96
|
end
|
77
97
|
|
78
98
|
def scope
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
# actually gets built.
|
88
|
-
def association_scope
|
89
|
-
if klass
|
90
|
-
@association_scope ||= AssociationScope.scope(self)
|
99
|
+
if disable_joins
|
100
|
+
DisableJoinsAssociationScope.create.scope(self)
|
101
|
+
elsif (scope = klass.current_scope) && scope.try(:proxy_association) == self
|
102
|
+
scope.spawn
|
103
|
+
elsif scope = klass.global_current_scope
|
104
|
+
target_scope.merge!(association_scope).merge!(scope)
|
105
|
+
else
|
106
|
+
target_scope.merge!(association_scope)
|
91
107
|
end
|
92
108
|
end
|
93
109
|
|
@@ -119,9 +135,13 @@ module ActiveRecord
|
|
119
135
|
|
120
136
|
def inversed_from(record)
|
121
137
|
self.target = record
|
122
|
-
@inversed = !!record
|
123
138
|
end
|
124
|
-
|
139
|
+
|
140
|
+
def inversed_from_queries(record)
|
141
|
+
if inversable?(record)
|
142
|
+
self.target = record
|
143
|
+
end
|
144
|
+
end
|
125
145
|
|
126
146
|
# Returns the class of the target. belongs_to polymorphic overrides this to look at the
|
127
147
|
# polymorphic_type field on the owner.
|
@@ -129,12 +149,6 @@ module ActiveRecord
|
|
129
149
|
reflection.klass
|
130
150
|
end
|
131
151
|
|
132
|
-
# Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the
|
133
|
-
# through association's scope)
|
134
|
-
def target_scope
|
135
|
-
AssociationRelation.create(klass, self).merge!(klass.all)
|
136
|
-
end
|
137
|
-
|
138
152
|
def extensions
|
139
153
|
extensions = klass.default_extensions | reflection.extensions
|
140
154
|
|
@@ -176,7 +190,7 @@ module ActiveRecord
|
|
176
190
|
@reflection = @owner.class._reflect_on_association(reflection_name)
|
177
191
|
end
|
178
192
|
|
179
|
-
def initialize_attributes(record, except_from_scope_attributes = nil)
|
193
|
+
def initialize_attributes(record, except_from_scope_attributes = nil) # :nodoc:
|
180
194
|
except_from_scope_attributes ||= {}
|
181
195
|
skip_assign = [reflection.foreign_key, reflection.type].compact
|
182
196
|
assigned_keys = record.changed_attribute_names_to_save
|
@@ -186,40 +200,79 @@ module ActiveRecord
|
|
186
200
|
set_inverse_instance(record)
|
187
201
|
end
|
188
202
|
|
189
|
-
def create(attributes =
|
203
|
+
def create(attributes = nil, &block)
|
190
204
|
_create_record(attributes, &block)
|
191
205
|
end
|
192
206
|
|
193
|
-
def create!(attributes =
|
207
|
+
def create!(attributes = nil, &block)
|
194
208
|
_create_record(attributes, true, &block)
|
195
209
|
end
|
196
210
|
|
197
211
|
private
|
198
|
-
|
199
|
-
|
212
|
+
# Reader and writer methods call this so that consistent errors are presented
|
213
|
+
# when the association target class does not exist.
|
214
|
+
def ensure_klass_exists!
|
215
|
+
klass
|
200
216
|
end
|
201
217
|
|
202
|
-
def find_target
|
203
|
-
|
218
|
+
def find_target
|
219
|
+
if violates_strict_loading? && owner.validation_context.nil?
|
220
|
+
Base.strict_loading_violation!(owner: owner.class, reflection: reflection)
|
221
|
+
end
|
222
|
+
|
223
|
+
scope = self.scope
|
224
|
+
return scope.to_a if skip_statement_cache?(scope)
|
225
|
+
|
226
|
+
sc = reflection.association_scope_cache(klass, owner) do |params|
|
227
|
+
as = AssociationScope.create { params.bind }
|
228
|
+
target_scope.merge!(as.scope(self))
|
229
|
+
end
|
230
|
+
|
231
|
+
binds = AssociationScope.get_bind_values(owner, reflection.chain)
|
232
|
+
sc.execute(binds, klass.connection) do |record|
|
233
|
+
set_inverse_instance(record)
|
234
|
+
if owner.strict_loading_n_plus_one_only? && reflection.macro == :has_many
|
235
|
+
record.strict_loading!
|
236
|
+
else
|
237
|
+
record.strict_loading!(false, mode: owner.strict_loading_mode)
|
238
|
+
end
|
239
|
+
end
|
204
240
|
end
|
205
241
|
|
206
|
-
def
|
207
|
-
|
242
|
+
def violates_strict_loading?
|
243
|
+
return reflection.strict_loading? if reflection.options.key?(:strict_loading)
|
208
244
|
|
209
|
-
|
210
|
-
|
245
|
+
owner.strict_loading? && !owner.strict_loading_n_plus_one_only?
|
246
|
+
end
|
211
247
|
|
212
|
-
|
213
|
-
|
248
|
+
# The scope for this association.
|
249
|
+
#
|
250
|
+
# Note that the association_scope is merged into the target_scope only when the
|
251
|
+
# scope method is called. This is because at that point the call may be surrounded
|
252
|
+
# by scope.scoping { ... } or unscoped { ... } etc, which affects the scope which
|
253
|
+
# actually gets built.
|
254
|
+
def association_scope
|
255
|
+
if klass
|
256
|
+
@association_scope ||= if disable_joins
|
257
|
+
DisableJoinsAssociationScope.scope(self)
|
258
|
+
else
|
259
|
+
AssociationScope.scope(self)
|
214
260
|
end
|
215
261
|
end
|
262
|
+
end
|
263
|
+
|
264
|
+
# Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the
|
265
|
+
# through association's scope)
|
266
|
+
def target_scope
|
267
|
+
AssociationRelation.create(klass, self).merge!(klass.scope_for_association)
|
268
|
+
end
|
216
269
|
|
217
|
-
|
270
|
+
def scope_for_create
|
271
|
+
scope.scope_for_create
|
218
272
|
end
|
219
273
|
|
220
|
-
|
221
|
-
|
222
|
-
creation_attributes.each { |key, value| record[key] = value }
|
274
|
+
def find_target?
|
275
|
+
!loaded? && (!owner.new_record? || foreign_key_present?) && klass
|
223
276
|
end
|
224
277
|
|
225
278
|
# Returns true if there is a foreign key present on the owner which
|
@@ -236,7 +289,7 @@ module ActiveRecord
|
|
236
289
|
|
237
290
|
# Raises ActiveRecord::AssociationTypeMismatch unless +record+ is of
|
238
291
|
# the kind of the class of the associated objects. Meant to be used as
|
239
|
-
# a
|
292
|
+
# a safety check when you are about to assign an associated record.
|
240
293
|
def raise_on_type_mismatch!(record)
|
241
294
|
unless record.is_a?(reflection.klass)
|
242
295
|
fresh_class = reflection.class_name.safe_constantize
|
@@ -269,7 +322,7 @@ module ActiveRecord
|
|
269
322
|
|
270
323
|
# Returns true if record contains the foreign_key
|
271
324
|
def foreign_key_for?(record)
|
272
|
-
record.
|
325
|
+
record._has_attribute?(reflection.foreign_key)
|
273
326
|
end
|
274
327
|
|
275
328
|
# This should be implemented to return the values of the relevant key(s) on the owner,
|
@@ -294,6 +347,28 @@ module ActiveRecord
|
|
294
347
|
klass.scope_attributes? ||
|
295
348
|
reflection.source_reflection.active_record.default_scopes.any?
|
296
349
|
end
|
350
|
+
|
351
|
+
def enqueue_destroy_association(options)
|
352
|
+
job_class = owner.class.destroy_association_async_job
|
353
|
+
|
354
|
+
if job_class
|
355
|
+
owner._after_commit_jobs.push([job_class, options])
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
def inversable?(record)
|
360
|
+
record &&
|
361
|
+
((!record.persisted? || !owner.persisted?) || matches_foreign_key?(record))
|
362
|
+
end
|
363
|
+
|
364
|
+
def matches_foreign_key?(record)
|
365
|
+
if foreign_key_for?(record)
|
366
|
+
record.read_attribute(reflection.foreign_key) == owner.id ||
|
367
|
+
(foreign_key_for?(owner) && owner.read_attribute(reflection.foreign_key) == record.id)
|
368
|
+
else
|
369
|
+
owner.read_attribute(reflection.foreign_key) == record.id
|
370
|
+
end
|
371
|
+
end
|
297
372
|
end
|
298
373
|
end
|
299
374
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
module Associations
|
5
|
-
class AssociationScope
|
5
|
+
class AssociationScope # :nodoc:
|
6
6
|
def self.scope(association)
|
7
7
|
INSTANCE.scope(association)
|
8
8
|
end
|
@@ -26,7 +26,9 @@ module ActiveRecord
|
|
26
26
|
chain = get_chain(reflection, association, scope.alias_tracker)
|
27
27
|
|
28
28
|
scope.extending! reflection.extensions
|
29
|
-
add_constraints(scope, owner, chain)
|
29
|
+
scope = add_constraints(scope, owner, chain)
|
30
|
+
scope.limit!(1) unless reflection.collection?
|
31
|
+
scope
|
30
32
|
end
|
31
33
|
|
32
34
|
def self.get_bind_values(owner, chain)
|
@@ -46,25 +48,20 @@ module ActiveRecord
|
|
46
48
|
binds
|
47
49
|
end
|
48
50
|
|
49
|
-
|
50
|
-
# Workaround for Ruby 2.2 "private attribute?" warning.
|
51
|
-
protected
|
52
|
-
|
51
|
+
private
|
53
52
|
attr_reader :value_transformation
|
54
53
|
|
55
|
-
private
|
56
54
|
def join(table, constraint)
|
57
|
-
|
55
|
+
Arel::Nodes::LeadingJoin.new(table, Arel::Nodes::On.new(constraint))
|
58
56
|
end
|
59
57
|
|
60
58
|
def last_chain_scope(scope, reflection, owner)
|
61
|
-
|
62
|
-
|
63
|
-
foreign_key = join_keys.foreign_key
|
59
|
+
primary_key = reflection.join_primary_key
|
60
|
+
foreign_key = reflection.join_foreign_key
|
64
61
|
|
65
62
|
table = reflection.aliased_table
|
66
63
|
value = transform_value(owner[foreign_key])
|
67
|
-
scope = apply_scope(scope, table,
|
64
|
+
scope = apply_scope(scope, table, primary_key, value)
|
68
65
|
|
69
66
|
if reflection.type
|
70
67
|
polymorphic_type = transform_value(owner.class.polymorphic_name)
|
@@ -79,13 +76,12 @@ module ActiveRecord
|
|
79
76
|
end
|
80
77
|
|
81
78
|
def next_chain_scope(scope, reflection, next_reflection)
|
82
|
-
|
83
|
-
|
84
|
-
foreign_key = join_keys.foreign_key
|
79
|
+
primary_key = reflection.join_primary_key
|
80
|
+
foreign_key = reflection.join_foreign_key
|
85
81
|
|
86
82
|
table = reflection.aliased_table
|
87
83
|
foreign_table = next_reflection.aliased_table
|
88
|
-
constraint = table[
|
84
|
+
constraint = table[primary_key].eq(foreign_table[foreign_key])
|
89
85
|
|
90
86
|
if reflection.type
|
91
87
|
value = transform_value(next_reflection.klass.polymorphic_name)
|
@@ -110,11 +106,9 @@ module ActiveRecord
|
|
110
106
|
name = reflection.name
|
111
107
|
chain = [Reflection::RuntimeReflection.new(reflection, association)]
|
112
108
|
reflection.chain.drop(1).each do |refl|
|
113
|
-
aliased_table = tracker.aliased_table_for(
|
114
|
-
refl.
|
115
|
-
|
116
|
-
refl.klass.type_caster
|
117
|
-
)
|
109
|
+
aliased_table = tracker.aliased_table_for(refl.klass.arel_table) do
|
110
|
+
refl.alias_candidate(name)
|
111
|
+
end
|
118
112
|
chain << ReflectionProxy.new(refl, aliased_table)
|
119
113
|
end
|
120
114
|
chain
|
@@ -129,17 +123,23 @@ module ActiveRecord
|
|
129
123
|
|
130
124
|
chain_head = chain.first
|
131
125
|
chain.reverse_each do |reflection|
|
132
|
-
# Exclude the scope of the association itself, because that
|
133
|
-
# was already merged in the #scope method.
|
134
126
|
reflection.constraints.each do |scope_chain_item|
|
135
127
|
item = eval_scope(reflection, scope_chain_item, owner)
|
136
128
|
|
137
129
|
if scope_chain_item == chain_head.scope
|
138
130
|
scope.merge! item.except(:where, :includes, :unscope, :order)
|
131
|
+
elsif !item.references_values.empty?
|
132
|
+
scope.merge! item.only(:joins, :left_outer_joins)
|
133
|
+
|
134
|
+
associations = item.eager_load_values | item.includes_values
|
135
|
+
|
136
|
+
unless associations.empty?
|
137
|
+
scope.joins! item.construct_join_dependency(associations, Arel::Nodes::OuterJoin)
|
138
|
+
end
|
139
139
|
end
|
140
140
|
|
141
141
|
reflection.all_includes do
|
142
|
-
scope.
|
142
|
+
scope.includes_values |= item.includes_values
|
143
143
|
end
|
144
144
|
|
145
145
|
scope.unscope!(*item.unscope_values)
|