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
@@ -11,6 +11,17 @@ module ActiveRecord
|
|
11
11
|
module ClassMethods
|
12
12
|
# Attributes listed as readonly will be used to create a new record but update operations will
|
13
13
|
# ignore these fields.
|
14
|
+
#
|
15
|
+
# You can assign a new value to a readonly attribute, but it will be ignored when the record is updated.
|
16
|
+
#
|
17
|
+
# ==== Examples
|
18
|
+
#
|
19
|
+
# class Post < ActiveRecord::Base
|
20
|
+
# attr_readonly :title
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# post = Post.create!(title: "Introducing Ruby on Rails!")
|
24
|
+
# post.update(title: "a different title") # change to title will be ignored
|
14
25
|
def attr_readonly(*attributes)
|
15
26
|
self._attr_readonly = Set.new(attributes.map(&:to_s)) + (_attr_readonly || [])
|
16
27
|
end
|
@@ -19,6 +30,10 @@ module ActiveRecord
|
|
19
30
|
def readonly_attributes
|
20
31
|
_attr_readonly
|
21
32
|
end
|
33
|
+
|
34
|
+
def readonly_attribute?(name) # :nodoc:
|
35
|
+
_attr_readonly.include?(name)
|
36
|
+
end
|
22
37
|
end
|
23
38
|
end
|
24
39
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_support/core_ext/string/filters"
|
4
|
-
require "concurrent/map"
|
5
4
|
|
6
5
|
module ActiveRecord
|
7
6
|
# = Active Record Reflection
|
@@ -11,35 +10,40 @@ module ActiveRecord
|
|
11
10
|
included do
|
12
11
|
class_attribute :_reflections, instance_writer: false, default: {}
|
13
12
|
class_attribute :aggregate_reflections, instance_writer: false, default: {}
|
13
|
+
class_attribute :automatic_scope_inversing, instance_writer: false, default: false
|
14
14
|
end
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
when :has_many
|
22
|
-
HasManyReflection
|
23
|
-
when :has_one
|
24
|
-
HasOneReflection
|
25
|
-
when :belongs_to
|
26
|
-
BelongsToReflection
|
27
|
-
else
|
28
|
-
raise "Unsupported Macro: #{macro}"
|
29
|
-
end
|
16
|
+
class << self
|
17
|
+
def create(macro, name, scope, options, ar)
|
18
|
+
reflection = reflection_class_for(macro).new(name, scope, options, ar)
|
19
|
+
options[:through] ? ThroughReflection.new(reflection) : reflection
|
20
|
+
end
|
30
21
|
|
31
|
-
|
32
|
-
|
33
|
-
|
22
|
+
def add_reflection(ar, name, reflection)
|
23
|
+
ar.clear_reflections_cache
|
24
|
+
name = -name.to_s
|
25
|
+
ar._reflections = ar._reflections.except(name).merge!(name => reflection)
|
26
|
+
end
|
34
27
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
ar._reflections = ar._reflections.except(name).merge!(name => reflection)
|
39
|
-
end
|
28
|
+
def add_aggregate_reflection(ar, name, reflection)
|
29
|
+
ar.aggregate_reflections = ar.aggregate_reflections.merge(-name.to_s => reflection)
|
30
|
+
end
|
40
31
|
|
41
|
-
|
42
|
-
|
32
|
+
private
|
33
|
+
def reflection_class_for(macro)
|
34
|
+
case macro
|
35
|
+
when :composed_of
|
36
|
+
AggregateReflection
|
37
|
+
when :has_many
|
38
|
+
HasManyReflection
|
39
|
+
when :has_one
|
40
|
+
HasOneReflection
|
41
|
+
when :belongs_to
|
42
|
+
BelongsToReflection
|
43
|
+
else
|
44
|
+
raise "Unsupported Macro: #{macro}"
|
45
|
+
end
|
46
|
+
end
|
43
47
|
end
|
44
48
|
|
45
49
|
# \Reflection enables the ability to examine the associations and aggregations of
|
@@ -112,7 +116,7 @@ module ActiveRecord
|
|
112
116
|
reflections[association.to_s]
|
113
117
|
end
|
114
118
|
|
115
|
-
def _reflect_on_association(association)
|
119
|
+
def _reflect_on_association(association) # :nodoc:
|
116
120
|
_reflections[association.to_s]
|
117
121
|
end
|
118
122
|
|
@@ -159,13 +163,7 @@ module ActiveRecord
|
|
159
163
|
# <tt>composed_of :balance, class_name: 'Money'</tt> returns <tt>'Money'</tt>
|
160
164
|
# <tt>has_many :clients</tt> returns <tt>'Client'</tt>
|
161
165
|
def class_name
|
162
|
-
@class_name ||= (options[:class_name] || derive_class_name).to_s
|
163
|
-
end
|
164
|
-
|
165
|
-
JoinKeys = Struct.new(:key, :foreign_key) # :nodoc:
|
166
|
-
|
167
|
-
def join_keys
|
168
|
-
@join_keys ||= get_join_keys(klass)
|
166
|
+
@class_name ||= -(options[:class_name] || derive_class_name).to_s
|
169
167
|
end
|
170
168
|
|
171
169
|
# Returns a list of scopes that should be applied for this Reflection
|
@@ -179,25 +177,27 @@ module ActiveRecord
|
|
179
177
|
scope_chain_items = join_scopes(table, predicate_builder)
|
180
178
|
klass_scope = klass_join_scope(table, predicate_builder)
|
181
179
|
|
182
|
-
key = join_keys.key
|
183
|
-
foreign_key = join_keys.foreign_key
|
184
|
-
|
185
|
-
klass_scope.where!(table[key].eq(foreign_table[foreign_key]))
|
186
|
-
|
187
180
|
if type
|
188
181
|
klass_scope.where!(type => foreign_klass.polymorphic_name)
|
189
182
|
end
|
190
183
|
|
184
|
+
scope_chain_items.inject(klass_scope, &:merge!)
|
185
|
+
|
186
|
+
primary_key = join_primary_key
|
187
|
+
foreign_key = join_foreign_key
|
188
|
+
|
189
|
+
klass_scope.where!(table[primary_key].eq(foreign_table[foreign_key]))
|
190
|
+
|
191
191
|
if klass.finder_needs_type_condition?
|
192
192
|
klass_scope.where!(klass.send(:type_condition, table))
|
193
193
|
end
|
194
194
|
|
195
|
-
|
195
|
+
klass_scope
|
196
196
|
end
|
197
197
|
|
198
|
-
def join_scopes(table, predicate_builder) # :nodoc:
|
198
|
+
def join_scopes(table, predicate_builder, klass = self.klass, record = nil) # :nodoc:
|
199
199
|
if scope
|
200
|
-
[scope_for(build_scope(table, predicate_builder))]
|
200
|
+
[scope_for(build_scope(table, predicate_builder, klass), record)]
|
201
201
|
else
|
202
202
|
[]
|
203
203
|
end
|
@@ -213,14 +213,14 @@ module ActiveRecord
|
|
213
213
|
end
|
214
214
|
|
215
215
|
def counter_cache_column
|
216
|
-
if belongs_to?
|
216
|
+
@counter_cache_column ||= if belongs_to?
|
217
217
|
if options[:counter_cache] == true
|
218
|
-
"#{active_record.name.demodulize.underscore.pluralize}_count"
|
218
|
+
-"#{active_record.name.demodulize.underscore.pluralize}_count"
|
219
219
|
elsif options[:counter_cache]
|
220
|
-
options[:counter_cache].to_s
|
220
|
+
-options[:counter_cache].to_s
|
221
221
|
end
|
222
222
|
else
|
223
|
-
options[:counter_cache]
|
223
|
+
-(options[:counter_cache]&.to_s || "#{name}_count")
|
224
224
|
end
|
225
225
|
end
|
226
226
|
|
@@ -235,10 +235,13 @@ module ActiveRecord
|
|
235
235
|
if has_inverse? && inverse_of.nil?
|
236
236
|
raise InverseOfAssociationNotFoundError.new(self)
|
237
237
|
end
|
238
|
+
if has_inverse? && inverse_of == self
|
239
|
+
raise InverseOfAssociationRecursiveError.new(self)
|
240
|
+
end
|
238
241
|
end
|
239
242
|
end
|
240
243
|
|
241
|
-
#
|
244
|
+
# We need to avoid the following situation:
|
242
245
|
#
|
243
246
|
# * An associated record is deleted via record.destroy
|
244
247
|
# * Hence the callbacks run, and they find a belongs_to on the record with a
|
@@ -267,7 +270,7 @@ module ActiveRecord
|
|
267
270
|
def has_cached_counter?
|
268
271
|
options[:counter_cache] ||
|
269
272
|
inverse_which_updates_counter_cache && inverse_which_updates_counter_cache.options[:counter_cache] &&
|
270
|
-
|
273
|
+
active_record.has_attribute?(counter_cache_column)
|
271
274
|
end
|
272
275
|
|
273
276
|
def counter_must_be_updated_by_has_many?
|
@@ -282,11 +285,7 @@ module ActiveRecord
|
|
282
285
|
collect_join_chain
|
283
286
|
end
|
284
287
|
|
285
|
-
def
|
286
|
-
JoinKeys.new(join_primary_key(association_klass), join_foreign_key)
|
287
|
-
end
|
288
|
-
|
289
|
-
def build_scope(table, predicate_builder = predicate_builder(table))
|
288
|
+
def build_scope(table, predicate_builder = predicate_builder(table), klass = self.klass)
|
290
289
|
Relation.create(
|
291
290
|
klass,
|
292
291
|
table: table,
|
@@ -294,12 +293,8 @@ module ActiveRecord
|
|
294
293
|
)
|
295
294
|
end
|
296
295
|
|
297
|
-
def
|
298
|
-
|
299
|
-
end
|
300
|
-
|
301
|
-
def join_foreign_key
|
302
|
-
active_record_primary_key
|
296
|
+
def strict_loading?
|
297
|
+
options[:strict_loading]
|
303
298
|
end
|
304
299
|
|
305
300
|
protected
|
@@ -315,6 +310,12 @@ module ActiveRecord
|
|
315
310
|
def primary_key(klass)
|
316
311
|
klass.primary_key || raise(UnknownPrimaryKey.new(klass))
|
317
312
|
end
|
313
|
+
|
314
|
+
def ensure_option_not_given_as_class!(option_name)
|
315
|
+
if options[option_name] && options[option_name].class == Class
|
316
|
+
raise ArgumentError, "A class was passed to `:#{option_name}` but we are expecting a string."
|
317
|
+
end
|
318
|
+
end
|
318
319
|
end
|
319
320
|
|
320
321
|
# Base class for AggregateReflection and AssociationReflection. Objects of
|
@@ -401,7 +402,7 @@ module ActiveRecord
|
|
401
402
|
|
402
403
|
# Holds all the metadata about an aggregation as it was specified in the
|
403
404
|
# Active Record class.
|
404
|
-
class AggregateReflection < MacroReflection
|
405
|
+
class AggregateReflection < MacroReflection # :nodoc:
|
405
406
|
def mapping
|
406
407
|
mapping = options[:mapping] || [name, name]
|
407
408
|
mapping.first.is_a?(Array) ? mapping : [mapping]
|
@@ -410,12 +411,29 @@ module ActiveRecord
|
|
410
411
|
|
411
412
|
# Holds all the metadata about an association as it was specified in the
|
412
413
|
# Active Record class.
|
413
|
-
class AssociationReflection < MacroReflection
|
414
|
+
class AssociationReflection < MacroReflection # :nodoc:
|
414
415
|
def compute_class(name)
|
415
416
|
if polymorphic?
|
416
|
-
raise ArgumentError, "Polymorphic
|
417
|
+
raise ArgumentError, "Polymorphic associations do not support computing the class."
|
418
|
+
end
|
419
|
+
|
420
|
+
msg = <<-MSG.squish
|
421
|
+
Rails couldn't find a valid model for #{name} association.
|
422
|
+
Please provide the :class_name option on the association declaration.
|
423
|
+
If :class_name is already provided, make sure it's an ActiveRecord::Base subclass.
|
424
|
+
MSG
|
425
|
+
|
426
|
+
begin
|
427
|
+
klass = active_record.send(:compute_type, name)
|
428
|
+
|
429
|
+
unless klass < ActiveRecord::Base
|
430
|
+
raise ArgumentError, msg
|
431
|
+
end
|
432
|
+
|
433
|
+
klass
|
434
|
+
rescue NameError
|
435
|
+
raise NameError, msg
|
417
436
|
end
|
418
|
-
active_record.send(:compute_type, name)
|
419
437
|
end
|
420
438
|
|
421
439
|
attr_reader :type, :foreign_type
|
@@ -423,65 +441,63 @@ module ActiveRecord
|
|
423
441
|
|
424
442
|
def initialize(name, scope, options, active_record)
|
425
443
|
super
|
426
|
-
@type
|
427
|
-
@foreign_type =
|
428
|
-
@constructable = calculate_constructable(macro, options)
|
429
|
-
@association_scope_cache = Concurrent::Map.new
|
444
|
+
@type = -(options[:foreign_type]&.to_s || "#{options[:as]}_type") if options[:as]
|
445
|
+
@foreign_type = -(options[:foreign_type]&.to_s || "#{name}_type") if options[:polymorphic]
|
430
446
|
|
431
|
-
|
432
|
-
raise ArgumentError, "A class was passed to `:class_name` but we are expecting a string."
|
433
|
-
end
|
447
|
+
ensure_option_not_given_as_class!(:class_name)
|
434
448
|
end
|
435
449
|
|
436
|
-
def association_scope_cache(
|
437
|
-
key =
|
450
|
+
def association_scope_cache(klass, owner, &block)
|
451
|
+
key = self
|
438
452
|
if polymorphic?
|
439
453
|
key = [key, owner._read_attribute(@foreign_type)]
|
440
454
|
end
|
441
|
-
|
442
|
-
end
|
443
|
-
|
444
|
-
def constructable? # :nodoc:
|
445
|
-
@constructable
|
455
|
+
klass.cached_find_by_statement(key, &block)
|
446
456
|
end
|
447
457
|
|
448
458
|
def join_table
|
449
|
-
@join_table ||= options[:join_table] || derive_join_table
|
459
|
+
@join_table ||= -(options[:join_table]&.to_s || derive_join_table)
|
450
460
|
end
|
451
461
|
|
452
462
|
def foreign_key
|
453
|
-
@foreign_key ||= options[:foreign_key] || derive_foreign_key
|
463
|
+
@foreign_key ||= -(options[:foreign_key]&.to_s || derive_foreign_key)
|
454
464
|
end
|
455
465
|
|
456
466
|
def association_foreign_key
|
457
|
-
@association_foreign_key ||= options[:association_foreign_key] || class_name.foreign_key
|
467
|
+
@association_foreign_key ||= -(options[:association_foreign_key]&.to_s || class_name.foreign_key)
|
458
468
|
end
|
459
469
|
|
460
|
-
# klass option is necessary to support loading polymorphic associations
|
461
470
|
def association_primary_key(klass = nil)
|
462
|
-
|
471
|
+
primary_key(klass || self.klass)
|
463
472
|
end
|
464
473
|
|
465
474
|
def active_record_primary_key
|
466
|
-
@active_record_primary_key ||= options[:primary_key] || primary_key(active_record)
|
475
|
+
@active_record_primary_key ||= -(options[:primary_key]&.to_s || primary_key(active_record))
|
476
|
+
end
|
477
|
+
|
478
|
+
def join_primary_key(klass = nil)
|
479
|
+
foreign_key
|
480
|
+
end
|
481
|
+
|
482
|
+
def join_foreign_key
|
483
|
+
active_record_primary_key
|
467
484
|
end
|
468
485
|
|
469
486
|
def check_validity!
|
470
487
|
check_validity_of_inverse!
|
471
488
|
end
|
472
489
|
|
473
|
-
def
|
490
|
+
def check_eager_loadable!
|
474
491
|
return unless scope
|
475
492
|
|
476
|
-
|
493
|
+
unless scope.arity == 0
|
477
494
|
raise ArgumentError, <<-MSG.squish
|
478
495
|
The association scope '#{name}' is instance dependent (the scope
|
479
|
-
block takes an argument).
|
480
|
-
not supported.
|
496
|
+
block takes an argument). Eager loading instance dependent scopes
|
497
|
+
is not supported.
|
481
498
|
MSG
|
482
499
|
end
|
483
500
|
end
|
484
|
-
alias :check_eager_loadable! :check_preloadable!
|
485
501
|
|
486
502
|
def join_id_for(owner) # :nodoc:
|
487
503
|
owner[join_foreign_key]
|
@@ -504,7 +520,7 @@ module ActiveRecord
|
|
504
520
|
# This is for clearing cache on the reflection. Useful for tests that need to compare
|
505
521
|
# SQL queries on associations.
|
506
522
|
def clear_association_scope_cache # :nodoc:
|
507
|
-
|
523
|
+
klass.initialize_find_by_cache
|
508
524
|
end
|
509
525
|
|
510
526
|
def nested?
|
@@ -566,9 +582,6 @@ module ActiveRecord
|
|
566
582
|
options[:polymorphic]
|
567
583
|
end
|
568
584
|
|
569
|
-
VALID_AUTOMATIC_INVERSE_MACROS = [:has_many, :has_one, :belongs_to]
|
570
|
-
INVALID_AUTOMATIC_INVERSE_OPTIONS = [:through, :foreign_key]
|
571
|
-
|
572
585
|
def add_as_source(seed)
|
573
586
|
seed
|
574
587
|
end
|
@@ -586,11 +599,6 @@ module ActiveRecord
|
|
586
599
|
end
|
587
600
|
|
588
601
|
private
|
589
|
-
|
590
|
-
def calculate_constructable(macro, options)
|
591
|
-
true
|
592
|
-
end
|
593
|
-
|
594
602
|
# Attempts to find the inverse association name automatically.
|
595
603
|
# If it cannot find a suitable inverse association name, it returns
|
596
604
|
# +nil+.
|
@@ -616,7 +624,7 @@ module ActiveRecord
|
|
616
624
|
end
|
617
625
|
|
618
626
|
if valid_inverse_reflection?(reflection)
|
619
|
-
|
627
|
+
inverse_name
|
620
628
|
end
|
621
629
|
end
|
622
630
|
end
|
@@ -627,8 +635,10 @@ module ActiveRecord
|
|
627
635
|
# with the current reflection's klass name.
|
628
636
|
def valid_inverse_reflection?(reflection)
|
629
637
|
reflection &&
|
638
|
+
reflection != self &&
|
639
|
+
foreign_key == reflection.foreign_key &&
|
630
640
|
klass <= reflection.active_record &&
|
631
|
-
can_find_inverse_of_automatically?(reflection)
|
641
|
+
can_find_inverse_of_automatically?(reflection, true)
|
632
642
|
end
|
633
643
|
|
634
644
|
# Checks to see if the reflection doesn't have any options that prevent
|
@@ -637,14 +647,25 @@ module ActiveRecord
|
|
637
647
|
# have <tt>has_many</tt>, <tt>has_one</tt>, <tt>belongs_to</tt> associations.
|
638
648
|
# Third, we must not have options such as <tt>:foreign_key</tt>
|
639
649
|
# which prevent us from correctly guessing the inverse association.
|
640
|
-
|
641
|
-
# Anything with a scope can additionally ruin our attempt at finding an
|
642
|
-
# inverse, so we exclude reflections with scopes.
|
643
|
-
def can_find_inverse_of_automatically?(reflection)
|
650
|
+
def can_find_inverse_of_automatically?(reflection, inverse_reflection = false)
|
644
651
|
reflection.options[:inverse_of] != false &&
|
645
|
-
|
646
|
-
!
|
652
|
+
!reflection.options[:through] &&
|
653
|
+
!reflection.options[:foreign_key] &&
|
654
|
+
scope_allows_automatic_inverse_of?(reflection, inverse_reflection)
|
655
|
+
end
|
656
|
+
|
657
|
+
# Scopes on the potential inverse reflection prevent automatic
|
658
|
+
# <tt>inverse_of</tt>, since the scope could exclude the owner record
|
659
|
+
# we would inverse from. Scopes on the reflection itself allow for
|
660
|
+
# automatic <tt>inverse_of</tt> as long as
|
661
|
+
# <tt>config.active_record.automatic_scope_inversing<tt> is set to
|
662
|
+
# +true+ (the default for new applications).
|
663
|
+
def scope_allows_automatic_inverse_of?(reflection, inverse_reflection)
|
664
|
+
if inverse_reflection
|
647
665
|
!reflection.scope
|
666
|
+
else
|
667
|
+
!reflection.scope || reflection.klass.automatic_scope_inversing
|
668
|
+
end
|
648
669
|
end
|
649
670
|
|
650
671
|
def derive_class_name
|
@@ -659,7 +680,7 @@ module ActiveRecord
|
|
659
680
|
elsif options[:as]
|
660
681
|
"#{options[:as]}_id"
|
661
682
|
else
|
662
|
-
active_record.
|
683
|
+
active_record.model_name.to_s.foreign_key
|
663
684
|
end
|
664
685
|
end
|
665
686
|
|
@@ -680,10 +701,6 @@ module ActiveRecord
|
|
680
701
|
Associations::HasManyAssociation
|
681
702
|
end
|
682
703
|
end
|
683
|
-
|
684
|
-
def association_primary_key(klass = nil)
|
685
|
-
primary_key(klass || self.klass)
|
686
|
-
end
|
687
704
|
end
|
688
705
|
|
689
706
|
class HasOneReflection < AssociationReflection # :nodoc:
|
@@ -698,12 +715,6 @@ module ActiveRecord
|
|
698
715
|
Associations::HasOneAssociation
|
699
716
|
end
|
700
717
|
end
|
701
|
-
|
702
|
-
private
|
703
|
-
|
704
|
-
def calculate_constructable(macro, options)
|
705
|
-
!options[:through]
|
706
|
-
end
|
707
718
|
end
|
708
719
|
|
709
720
|
class BelongsToReflection < AssociationReflection # :nodoc:
|
@@ -719,6 +730,15 @@ module ActiveRecord
|
|
719
730
|
end
|
720
731
|
end
|
721
732
|
|
733
|
+
# klass option is necessary to support loading polymorphic associations
|
734
|
+
def association_primary_key(klass = nil)
|
735
|
+
if primary_key = options[:primary_key]
|
736
|
+
@association_primary_key ||= -primary_key.to_s
|
737
|
+
else
|
738
|
+
primary_key(klass || self.klass)
|
739
|
+
end
|
740
|
+
end
|
741
|
+
|
722
742
|
def join_primary_key(klass = nil)
|
723
743
|
polymorphic? ? association_primary_key(klass) : association_primary_key
|
724
744
|
end
|
@@ -727,14 +747,14 @@ module ActiveRecord
|
|
727
747
|
foreign_key
|
728
748
|
end
|
729
749
|
|
750
|
+
def join_foreign_type
|
751
|
+
foreign_type
|
752
|
+
end
|
753
|
+
|
730
754
|
private
|
731
|
-
def can_find_inverse_of_automatically?(
|
755
|
+
def can_find_inverse_of_automatically?(*)
|
732
756
|
!polymorphic? && super
|
733
757
|
end
|
734
|
-
|
735
|
-
def calculate_constructable(macro, options)
|
736
|
-
!polymorphic?
|
737
|
-
end
|
738
758
|
end
|
739
759
|
|
740
760
|
class HasAndBelongsToManyReflection < AssociationReflection # :nodoc:
|
@@ -747,14 +767,16 @@ module ActiveRecord
|
|
747
767
|
|
748
768
|
# Holds all the metadata about a :through association as it was specified
|
749
769
|
# in the Active Record class.
|
750
|
-
class ThroughReflection < AbstractReflection
|
751
|
-
delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for,
|
752
|
-
:active_record_primary_key, :
|
770
|
+
class ThroughReflection < AbstractReflection # :nodoc:
|
771
|
+
delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for, :type,
|
772
|
+
:active_record_primary_key, :join_foreign_key, to: :source_reflection
|
753
773
|
|
754
774
|
def initialize(delegate_reflection)
|
755
775
|
@delegate_reflection = delegate_reflection
|
756
776
|
@klass = delegate_reflection.options[:anonymous_class]
|
757
777
|
@source_reflection_name = delegate_reflection.options[:source]
|
778
|
+
|
779
|
+
ensure_option_not_given_as_class!(:source_type)
|
758
780
|
end
|
759
781
|
|
760
782
|
def through_reflection?
|
@@ -835,8 +857,8 @@ module ActiveRecord
|
|
835
857
|
source_reflection.scopes + super
|
836
858
|
end
|
837
859
|
|
838
|
-
def join_scopes(table, predicate_builder) # :nodoc:
|
839
|
-
source_reflection.join_scopes(table, predicate_builder) + super
|
860
|
+
def join_scopes(table, predicate_builder, klass = self.klass, record = nil) # :nodoc:
|
861
|
+
source_reflection.join_scopes(table, predicate_builder, klass, record) + super
|
840
862
|
end
|
841
863
|
|
842
864
|
def has_scope?
|
@@ -856,7 +878,15 @@ module ActiveRecord
|
|
856
878
|
def association_primary_key(klass = nil)
|
857
879
|
# Get the "actual" source reflection if the immediate source reflection has a
|
858
880
|
# source reflection itself
|
859
|
-
actual_source_reflection.options[:primary_key]
|
881
|
+
if primary_key = actual_source_reflection.options[:primary_key]
|
882
|
+
@association_primary_key ||= -primary_key.to_s
|
883
|
+
else
|
884
|
+
primary_key(klass || self.klass)
|
885
|
+
end
|
886
|
+
end
|
887
|
+
|
888
|
+
def join_primary_key(klass = self.klass)
|
889
|
+
source_reflection.join_primary_key(klass)
|
860
890
|
end
|
861
891
|
|
862
892
|
# Gets an array of possible <tt>:through</tt> source reflection names in both singular and plural form.
|
@@ -905,7 +935,7 @@ module ActiveRecord
|
|
905
935
|
|
906
936
|
def check_validity!
|
907
937
|
if through_reflection.nil?
|
908
|
-
raise HasManyThroughAssociationNotFoundError.new(active_record
|
938
|
+
raise HasManyThroughAssociationNotFoundError.new(active_record, self)
|
909
939
|
end
|
910
940
|
|
911
941
|
if through_reflection.polymorphic?
|
@@ -961,16 +991,14 @@ module ActiveRecord
|
|
961
991
|
collect_join_reflections(seed + [self])
|
962
992
|
end
|
963
993
|
|
964
|
-
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
965
|
-
# Workaround for Ruby 2.2 "private attribute?" warning.
|
966
994
|
protected
|
967
|
-
attr_reader :delegate_reflection
|
968
|
-
|
969
995
|
def actual_source_reflection # FIXME: this is a horrible name
|
970
996
|
source_reflection.actual_source_reflection
|
971
997
|
end
|
972
998
|
|
973
999
|
private
|
1000
|
+
attr_reader :delegate_reflection
|
1001
|
+
|
974
1002
|
def collect_join_reflections(seed)
|
975
1003
|
a = source_reflection.add_as_source seed
|
976
1004
|
if options[:source_type]
|
@@ -994,16 +1022,17 @@ module ActiveRecord
|
|
994
1022
|
end
|
995
1023
|
|
996
1024
|
class PolymorphicReflection < AbstractReflection # :nodoc:
|
997
|
-
delegate :klass, :scope, :plural_name, :type, :
|
1025
|
+
delegate :klass, :scope, :plural_name, :type, :join_primary_key, :join_foreign_key,
|
1026
|
+
:name, :scope_for, to: :@reflection
|
998
1027
|
|
999
1028
|
def initialize(reflection, previous_reflection)
|
1000
1029
|
@reflection = reflection
|
1001
1030
|
@previous_reflection = previous_reflection
|
1002
1031
|
end
|
1003
1032
|
|
1004
|
-
def join_scopes(table, predicate_builder) # :nodoc:
|
1005
|
-
scopes = @previous_reflection.join_scopes(table, predicate_builder) + super
|
1006
|
-
scopes << build_scope(table, predicate_builder).instance_exec(
|
1033
|
+
def join_scopes(table, predicate_builder, klass = self.klass, record = nil) # :nodoc:
|
1034
|
+
scopes = @previous_reflection.join_scopes(table, predicate_builder, klass, record) + super
|
1035
|
+
scopes << build_scope(table, predicate_builder, klass).instance_exec(record, &source_type_scope)
|
1007
1036
|
end
|
1008
1037
|
|
1009
1038
|
def constraints
|
@@ -1019,7 +1048,7 @@ module ActiveRecord
|
|
1019
1048
|
end
|
1020
1049
|
|
1021
1050
|
class RuntimeReflection < AbstractReflection # :nodoc:
|
1022
|
-
delegate :scope, :type, :constraints, :
|
1051
|
+
delegate :scope, :type, :constraints, :join_foreign_key, to: :@reflection
|
1023
1052
|
|
1024
1053
|
def initialize(reflection, association)
|
1025
1054
|
@reflection = reflection
|
@@ -1031,7 +1060,11 @@ module ActiveRecord
|
|
1031
1060
|
end
|
1032
1061
|
|
1033
1062
|
def aliased_table
|
1034
|
-
|
1063
|
+
klass.arel_table
|
1064
|
+
end
|
1065
|
+
|
1066
|
+
def join_primary_key(klass = self.klass)
|
1067
|
+
@reflection.join_primary_key(klass)
|
1035
1068
|
end
|
1036
1069
|
|
1037
1070
|
def all_includes; yield; end
|