activerecord 5.0.6 → 6.0.1
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 +5 -5
- data/CHANGELOG.md +638 -2023
- data/MIT-LICENSE +3 -1
- data/README.rdoc +8 -6
- data/examples/performance.rb +31 -29
- data/examples/simple.rb +5 -3
- data/lib/active_record/aggregations.rb +249 -246
- data/lib/active_record/association_relation.rb +24 -13
- data/lib/active_record/associations/alias_tracker.rb +24 -33
- data/lib/active_record/associations/association.rb +119 -56
- data/lib/active_record/associations/association_scope.rb +94 -94
- data/lib/active_record/associations/belongs_to_association.rb +58 -42
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
- data/lib/active_record/associations/builder/association.rb +18 -25
- data/lib/active_record/associations/builder/belongs_to.rb +43 -54
- data/lib/active_record/associations/builder/collection_association.rb +7 -18
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +42 -61
- data/lib/active_record/associations/builder/has_many.rb +4 -0
- data/lib/active_record/associations/builder/has_one.rb +37 -1
- data/lib/active_record/associations/builder/singular_association.rb +4 -0
- data/lib/active_record/associations/collection_association.rb +80 -252
- data/lib/active_record/associations/collection_proxy.rb +158 -121
- data/lib/active_record/associations/foreign_association.rb +9 -0
- data/lib/active_record/associations/has_many_association.rb +23 -29
- data/lib/active_record/associations/has_many_through_association.rb +58 -44
- data/lib/active_record/associations/has_one_association.rb +59 -54
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency/join_association.rb +38 -90
- data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +12 -12
- data/lib/active_record/associations/join_dependency.rb +134 -176
- data/lib/active_record/associations/preloader/association.rb +84 -125
- data/lib/active_record/associations/preloader/through_association.rb +82 -75
- data/lib/active_record/associations/preloader.rb +90 -102
- data/lib/active_record/associations/singular_association.rb +12 -45
- data/lib/active_record/associations/through_association.rb +26 -14
- data/lib/active_record/associations.rb +1603 -1592
- data/lib/active_record/attribute_assignment.rb +54 -60
- data/lib/active_record/attribute_decorators.rb +38 -15
- data/lib/active_record/attribute_methods/before_type_cast.rb +12 -7
- data/lib/active_record/attribute_methods/dirty.rb +179 -109
- data/lib/active_record/attribute_methods/primary_key.rb +86 -91
- data/lib/active_record/attribute_methods/query.rb +4 -3
- data/lib/active_record/attribute_methods/read.rb +21 -49
- data/lib/active_record/attribute_methods/serialization.rb +30 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -64
- data/lib/active_record/attribute_methods/write.rb +35 -33
- data/lib/active_record/attribute_methods.rb +66 -106
- data/lib/active_record/attributes.rb +38 -24
- data/lib/active_record/autosave_association.rb +53 -32
- data/lib/active_record/base.rb +27 -24
- data/lib/active_record/callbacks.rb +63 -33
- data/lib/active_record/coders/json.rb +2 -0
- data/lib/active_record/coders/yaml_column.rb +11 -11
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +553 -321
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +23 -5
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +213 -94
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +59 -28
- data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -75
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +33 -27
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +207 -126
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +369 -199
- data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -78
- data/lib/active_record/connection_adapters/abstract_adapter.rb +363 -202
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +405 -551
- data/lib/active_record/connection_adapters/column.rb +41 -13
- data/lib/active_record/connection_adapters/connection_specification.rb +172 -138
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +11 -4
- data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +143 -49
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -22
- data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +50 -45
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +58 -56
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +12 -13
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +49 -30
- data/lib/active_record/connection_adapters/postgresql/column.rb +22 -7
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +60 -54
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +22 -10
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +6 -5
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -17
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -5
- data/lib/active_record/connection_adapters/postgresql/oid/{json.rb → oid.rb} +6 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +31 -9
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +34 -30
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +9 -4
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +24 -21
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +95 -35
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +147 -105
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +35 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +380 -300
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +26 -25
- data/lib/active_record/connection_adapters/postgresql/utils.rb +10 -6
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +382 -275
- data/lib/active_record/connection_adapters/schema_cache.rb +46 -12
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +13 -8
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +120 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +74 -19
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +3 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +254 -262
- data/lib/active_record/connection_adapters/statement_pool.rb +9 -7
- data/lib/active_record/connection_handling.rb +159 -40
- data/lib/active_record/core.rb +202 -162
- data/lib/active_record/counter_cache.rb +57 -28
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +79 -0
- data/lib/active_record/database_configurations.rb +233 -0
- data/lib/active_record/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +87 -86
- data/lib/active_record/enum.rb +60 -23
- data/lib/active_record/errors.rb +114 -18
- data/lib/active_record/explain.rb +4 -3
- data/lib/active_record/explain_registry.rb +3 -1
- data/lib/active_record/explain_subscriber.rb +9 -4
- data/lib/active_record/fixture_set/file.rb +13 -8
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +153 -0
- data/lib/active_record/fixture_set/table_rows.rb +47 -0
- data/lib/active_record/fixtures.rb +195 -502
- data/lib/active_record/gem_version.rb +4 -2
- data/lib/active_record/inheritance.rb +151 -97
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +116 -25
- data/lib/active_record/internal_metadata.rb +15 -18
- data/lib/active_record/legacy_yaml_adapter.rb +4 -2
- data/lib/active_record/locking/optimistic.rb +78 -87
- data/lib/active_record/locking/pessimistic.rb +18 -6
- data/lib/active_record/log_subscriber.rb +48 -29
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +88 -0
- data/lib/active_record/middleware/database_selector.rb +75 -0
- data/lib/active_record/migration/command_recorder.rb +143 -97
- data/lib/active_record/migration/compatibility.rb +174 -56
- data/lib/active_record/migration/join_table.rb +8 -6
- data/lib/active_record/migration.rb +367 -300
- data/lib/active_record/model_schema.rb +145 -139
- data/lib/active_record/nested_attributes.rb +214 -201
- data/lib/active_record/no_touching.rb +10 -1
- data/lib/active_record/null_relation.rb +13 -34
- data/lib/active_record/persistence.rb +442 -72
- data/lib/active_record/query_cache.rb +15 -14
- data/lib/active_record/querying.rb +36 -23
- data/lib/active_record/railtie.rb +128 -36
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +34 -33
- data/lib/active_record/railties/databases.rake +309 -177
- data/lib/active_record/readonly_attributes.rb +5 -4
- data/lib/active_record/reflection.rb +211 -249
- data/lib/active_record/relation/batches/batch_enumerator.rb +3 -1
- data/lib/active_record/relation/batches.rb +99 -52
- data/lib/active_record/relation/calculations.rb +211 -172
- data/lib/active_record/relation/delegation.rb +67 -65
- data/lib/active_record/relation/finder_methods.rb +208 -247
- data/lib/active_record/relation/from_clause.rb +2 -8
- data/lib/active_record/relation/merger.rb +78 -61
- data/lib/active_record/relation/predicate_builder/array_handler.rb +20 -14
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +4 -3
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +7 -18
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
- data/lib/active_record/relation/predicate_builder.rb +86 -104
- data/lib/active_record/relation/query_attribute.rb +33 -2
- data/lib/active_record/relation/query_methods.rb +458 -329
- data/lib/active_record/relation/record_fetch_warning.rb +5 -3
- data/lib/active_record/relation/spawn_methods.rb +8 -7
- data/lib/active_record/relation/where_clause.rb +111 -95
- data/lib/active_record/relation/where_clause_factory.rb +6 -11
- data/lib/active_record/relation.rb +429 -318
- data/lib/active_record/result.rb +69 -39
- data/lib/active_record/runtime_registry.rb +5 -3
- data/lib/active_record/sanitization.rb +83 -99
- data/lib/active_record/schema.rb +7 -14
- data/lib/active_record/schema_dumper.rb +71 -69
- data/lib/active_record/schema_migration.rb +15 -5
- data/lib/active_record/scoping/default.rb +93 -95
- data/lib/active_record/scoping/named.rb +45 -25
- data/lib/active_record/scoping.rb +20 -19
- data/lib/active_record/secure_token.rb +4 -2
- data/lib/active_record/serialization.rb +2 -0
- data/lib/active_record/statement_cache.rb +63 -28
- data/lib/active_record/store.rb +121 -41
- data/lib/active_record/suppressor.rb +4 -1
- data/lib/active_record/table_metadata.rb +26 -20
- data/lib/active_record/tasks/database_tasks.rb +276 -85
- data/lib/active_record/tasks/mysql_database_tasks.rb +54 -90
- data/lib/active_record/tasks/postgresql_database_tasks.rb +78 -47
- data/lib/active_record/tasks/sqlite_database_tasks.rb +34 -16
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +224 -0
- data/lib/active_record/timestamp.rb +70 -35
- data/lib/active_record/touch_later.rb +7 -4
- data/lib/active_record/transactions.rb +133 -149
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type/adapter_specific_registry.rb +44 -45
- data/lib/active_record/type/date.rb +2 -0
- data/lib/active_record/type/date_time.rb +2 -0
- data/lib/active_record/type/decimal_without_scale.rb +15 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +5 -3
- data/lib/active_record/type/internal/timezone.rb +2 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +16 -8
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +2 -1
- data/lib/active_record/type/type_map.rb +13 -15
- data/lib/active_record/type/unsigned_integer.rb +17 -0
- data/lib/active_record/type.rb +23 -17
- data/lib/active_record/type_caster/connection.rb +17 -12
- data/lib/active_record/type_caster/map.rb +5 -4
- data/lib/active_record/type_caster.rb +4 -2
- data/lib/active_record/validations/absence.rb +2 -0
- data/lib/active_record/validations/associated.rb +3 -1
- data/lib/active_record/validations/length.rb +2 -0
- data/lib/active_record/validations/presence.rb +4 -2
- data/lib/active_record/validations/uniqueness.rb +29 -42
- data/lib/active_record/validations.rb +7 -4
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +36 -22
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/collectors/bind.rb +24 -0
- data/lib/arel/collectors/composite.rb +31 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +20 -0
- data/lib/arel/collectors/substitute_binds.rb +28 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -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/insert_manager.rb +49 -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 +52 -0
- data/lib/arel/nodes/bind_param.rb +36 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +50 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +18 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +8 -0
- data/lib/arel/nodes/in.rb +8 -0
- data/lib/arel/nodes/infix_operation.rb +80 -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 +50 -0
- data/lib/arel/nodes/node_expression.rb +13 -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 +16 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +27 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +45 -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 +41 -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 +68 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +257 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/depth_first.rb +204 -0
- data/lib/arel/visitors/dot.rb +297 -0
- data/lib/arel/visitors/ibm_db.rb +34 -0
- data/lib/arel/visitors/informix.rb +62 -0
- data/lib/arel/visitors/mssql.rb +157 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +66 -0
- data/lib/arel/visitors/postgresql.rb +110 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +889 -0
- data/lib/arel/visitors/visitor.rb +46 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +58 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -35
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +1 -1
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +4 -2
- data/lib/rails/generators/active_record/migration.rb +17 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -29
- data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +10 -1
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- data/lib/rails/generators/active_record.rb +7 -5
- metadata +133 -50
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -17
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -15
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -20
- data/lib/active_record/attribute/user_provided_default.rb +0 -28
- data/lib/active_record/attribute.rb +0 -213
- data/lib/active_record/attribute_mutation_tracker.rb +0 -70
- data/lib/active_record/attribute_set/builder.rb +0 -130
- data/lib/active_record/attribute_set.rb +0 -110
- data/lib/active_record/collection_cache_key.rb +0 -50
- data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +0 -50
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
- data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -57
- data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/string/filters"
|
4
|
+
require "concurrent/map"
|
3
5
|
|
4
6
|
module ActiveRecord
|
5
7
|
# = Active Record Reflection
|
@@ -7,37 +9,41 @@ module ActiveRecord
|
|
7
9
|
extend ActiveSupport::Concern
|
8
10
|
|
9
11
|
included do
|
10
|
-
class_attribute :_reflections, instance_writer: false
|
11
|
-
class_attribute :aggregate_reflections, instance_writer: false
|
12
|
-
self._reflections = {}
|
13
|
-
self.aggregate_reflections = {}
|
12
|
+
class_attribute :_reflections, instance_writer: false, default: {}
|
13
|
+
class_attribute :aggregate_reflections, instance_writer: false, default: {}
|
14
14
|
end
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
HasManyReflection
|
22
|
-
when :has_one
|
23
|
-
HasOneReflection
|
24
|
-
when :belongs_to
|
25
|
-
BelongsToReflection
|
26
|
-
else
|
27
|
-
raise "Unsupported Macro: #{macro}"
|
28
|
-
end
|
29
|
-
|
30
|
-
reflection = klass.new(name, scope, options, ar)
|
31
|
-
options[:through] ? ThroughReflection.new(reflection) : reflection
|
32
|
-
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
|
33
21
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
38
27
|
|
39
|
-
|
40
|
-
|
28
|
+
def add_aggregate_reflection(ar, name, reflection)
|
29
|
+
ar.aggregate_reflections = ar.aggregate_reflections.merge(-name.to_s => reflection)
|
30
|
+
end
|
31
|
+
|
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
|
41
47
|
end
|
42
48
|
|
43
49
|
# \Reflection enables the ability to examine the associations and aggregations of
|
@@ -135,8 +141,8 @@ module ActiveRecord
|
|
135
141
|
# BelongsToReflection
|
136
142
|
# HasAndBelongsToManyReflection
|
137
143
|
# ThroughReflection
|
138
|
-
#
|
139
|
-
#
|
144
|
+
# PolymorphicReflection
|
145
|
+
# RuntimeReflection
|
140
146
|
class AbstractReflection # :nodoc:
|
141
147
|
def through_reflection?
|
142
148
|
false
|
@@ -152,14 +158,6 @@ module ActiveRecord
|
|
152
158
|
klass.new(attributes, &block)
|
153
159
|
end
|
154
160
|
|
155
|
-
def quoted_table_name
|
156
|
-
klass.quoted_table_name
|
157
|
-
end
|
158
|
-
|
159
|
-
def primary_key_type
|
160
|
-
klass.type_for_attribute(klass.primary_key)
|
161
|
-
end
|
162
|
-
|
163
161
|
# Returns the class name for the macro.
|
164
162
|
#
|
165
163
|
# <tt>composed_of :balance, class_name: 'Money'</tt> returns <tt>'Money'</tt>
|
@@ -170,12 +168,52 @@ module ActiveRecord
|
|
170
168
|
|
171
169
|
JoinKeys = Struct.new(:key, :foreign_key) # :nodoc:
|
172
170
|
|
173
|
-
def join_keys
|
174
|
-
|
171
|
+
def join_keys
|
172
|
+
@join_keys ||= get_join_keys(klass)
|
173
|
+
end
|
174
|
+
|
175
|
+
# Returns a list of scopes that should be applied for this Reflection
|
176
|
+
# object when querying the database.
|
177
|
+
def scopes
|
178
|
+
scope ? [scope] : []
|
179
|
+
end
|
180
|
+
|
181
|
+
def join_scope(table, foreign_table, foreign_klass)
|
182
|
+
predicate_builder = predicate_builder(table)
|
183
|
+
scope_chain_items = join_scopes(table, predicate_builder)
|
184
|
+
klass_scope = klass_join_scope(table, predicate_builder)
|
185
|
+
|
186
|
+
key = join_keys.key
|
187
|
+
foreign_key = join_keys.foreign_key
|
188
|
+
|
189
|
+
klass_scope.where!(table[key].eq(foreign_table[foreign_key]))
|
190
|
+
|
191
|
+
if type
|
192
|
+
klass_scope.where!(type => foreign_klass.polymorphic_name)
|
193
|
+
end
|
194
|
+
|
195
|
+
if klass.finder_needs_type_condition?
|
196
|
+
klass_scope.where!(klass.send(:type_condition, table))
|
197
|
+
end
|
198
|
+
|
199
|
+
scope_chain_items.inject(klass_scope, &:merge!)
|
200
|
+
end
|
201
|
+
|
202
|
+
def join_scopes(table, predicate_builder) # :nodoc:
|
203
|
+
if scope
|
204
|
+
[scope_for(build_scope(table, predicate_builder))]
|
205
|
+
else
|
206
|
+
[]
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def klass_join_scope(table, predicate_builder) # :nodoc:
|
211
|
+
relation = build_scope(table, predicate_builder)
|
212
|
+
klass.scope_for_association(relation)
|
175
213
|
end
|
176
214
|
|
177
215
|
def constraints
|
178
|
-
|
216
|
+
chain.flat_map(&:scopes)
|
179
217
|
end
|
180
218
|
|
181
219
|
def counter_cache_column
|
@@ -247,6 +285,40 @@ module ActiveRecord
|
|
247
285
|
def chain
|
248
286
|
collect_join_chain
|
249
287
|
end
|
288
|
+
|
289
|
+
def get_join_keys(association_klass)
|
290
|
+
JoinKeys.new(join_primary_key(association_klass), join_foreign_key)
|
291
|
+
end
|
292
|
+
|
293
|
+
def build_scope(table, predicate_builder = predicate_builder(table))
|
294
|
+
Relation.create(
|
295
|
+
klass,
|
296
|
+
table: table,
|
297
|
+
predicate_builder: predicate_builder
|
298
|
+
)
|
299
|
+
end
|
300
|
+
|
301
|
+
def join_primary_key(*)
|
302
|
+
foreign_key
|
303
|
+
end
|
304
|
+
|
305
|
+
def join_foreign_key
|
306
|
+
active_record_primary_key
|
307
|
+
end
|
308
|
+
|
309
|
+
protected
|
310
|
+
def actual_source_reflection # FIXME: this is a horrible name
|
311
|
+
self
|
312
|
+
end
|
313
|
+
|
314
|
+
private
|
315
|
+
def predicate_builder(table)
|
316
|
+
PredicateBuilder.new(TableMetadata.new(klass, table))
|
317
|
+
end
|
318
|
+
|
319
|
+
def primary_key(klass)
|
320
|
+
klass.primary_key || raise(UnknownPrimaryKey.new(klass))
|
321
|
+
end
|
250
322
|
end
|
251
323
|
|
252
324
|
# Base class for AggregateReflection and AssociationReflection. Objects of
|
@@ -281,7 +353,6 @@ module ActiveRecord
|
|
281
353
|
end
|
282
354
|
|
283
355
|
def autosave=(autosave)
|
284
|
-
@automatic_inverse_of = false
|
285
356
|
@options[:autosave] = autosave
|
286
357
|
parent_reflection = self.parent_reflection
|
287
358
|
if parent_reflection
|
@@ -293,6 +364,17 @@ module ActiveRecord
|
|
293
364
|
#
|
294
365
|
# <tt>composed_of :balance, class_name: 'Money'</tt> returns the Money class
|
295
366
|
# <tt>has_many :clients</tt> returns the Client class
|
367
|
+
#
|
368
|
+
# class Company < ActiveRecord::Base
|
369
|
+
# has_many :clients
|
370
|
+
# end
|
371
|
+
#
|
372
|
+
# Company.reflect_on_association(:clients).klass
|
373
|
+
# # => Client
|
374
|
+
#
|
375
|
+
# <b>Note:</b> Do not call +klass.new+ or +klass.create+ to instantiate
|
376
|
+
# a new association object. Use +build_association+ or +create_association+
|
377
|
+
# instead. This allows plugins to hook into association object creation.
|
296
378
|
def klass
|
297
379
|
@klass ||= compute_class(class_name)
|
298
380
|
end
|
@@ -311,8 +393,8 @@ module ActiveRecord
|
|
311
393
|
active_record == other_aggregation.active_record
|
312
394
|
end
|
313
395
|
|
314
|
-
def scope_for(
|
315
|
-
|
396
|
+
def scope_for(relation, owner = nil)
|
397
|
+
relation.instance_exec(owner, &scope) || relation
|
316
398
|
end
|
317
399
|
|
318
400
|
private
|
@@ -321,8 +403,7 @@ module ActiveRecord
|
|
321
403
|
end
|
322
404
|
end
|
323
405
|
|
324
|
-
|
325
|
-
# Holds all the meta-data about an aggregation as it was specified in the
|
406
|
+
# Holds all the metadata about an aggregation as it was specified in the
|
326
407
|
# Active Record class.
|
327
408
|
class AggregateReflection < MacroReflection #:nodoc:
|
328
409
|
def mapping
|
@@ -331,26 +412,13 @@ module ActiveRecord
|
|
331
412
|
end
|
332
413
|
end
|
333
414
|
|
334
|
-
# Holds all the
|
415
|
+
# Holds all the metadata about an association as it was specified in the
|
335
416
|
# Active Record class.
|
336
417
|
class AssociationReflection < MacroReflection #:nodoc:
|
337
|
-
# Returns the target association's class.
|
338
|
-
#
|
339
|
-
# class Author < ActiveRecord::Base
|
340
|
-
# has_many :books
|
341
|
-
# end
|
342
|
-
#
|
343
|
-
# Author.reflect_on_association(:books).klass
|
344
|
-
# # => Book
|
345
|
-
#
|
346
|
-
# <b>Note:</b> Do not call +klass.new+ or +klass.create+ to instantiate
|
347
|
-
# a new association object. Use +build_association+ or +create_association+
|
348
|
-
# instead. This allows plugins to hook into association object creation.
|
349
|
-
def klass
|
350
|
-
@klass ||= compute_class(class_name)
|
351
|
-
end
|
352
|
-
|
353
418
|
def compute_class(name)
|
419
|
+
if polymorphic?
|
420
|
+
raise ArgumentError, "Polymorphic associations do not support computing the class."
|
421
|
+
end
|
354
422
|
active_record.send(:compute_type, name)
|
355
423
|
end
|
356
424
|
|
@@ -359,22 +427,22 @@ module ActiveRecord
|
|
359
427
|
|
360
428
|
def initialize(name, scope, options, active_record)
|
361
429
|
super
|
362
|
-
@automatic_inverse_of = nil
|
363
430
|
@type = options[:as] && (options[:foreign_type] || "#{options[:as]}_type")
|
364
|
-
@foreign_type = options[:foreign_type] || "#{name}_type"
|
431
|
+
@foreign_type = options[:polymorphic] && (options[:foreign_type] || "#{name}_type")
|
365
432
|
@constructable = calculate_constructable(macro, options)
|
366
|
-
@association_scope_cache =
|
367
|
-
|
433
|
+
@association_scope_cache = Concurrent::Map.new
|
434
|
+
|
435
|
+
if options[:class_name] && options[:class_name].class == Class
|
436
|
+
raise ArgumentError, "A class was passed to `:class_name` but we are expecting a string."
|
437
|
+
end
|
368
438
|
end
|
369
439
|
|
370
|
-
def association_scope_cache(conn, owner)
|
440
|
+
def association_scope_cache(conn, owner, &block)
|
371
441
|
key = conn.prepared_statements
|
372
442
|
if polymorphic?
|
373
443
|
key = [key, owner._read_attribute(@foreign_type)]
|
374
444
|
end
|
375
|
-
@association_scope_cache
|
376
|
-
@association_scope_cache[key] ||= yield
|
377
|
-
}
|
445
|
+
@association_scope_cache.compute_if_absent(key) { StatementCache.create(conn, &block) }
|
378
446
|
end
|
379
447
|
|
380
448
|
def constructable? # :nodoc:
|
@@ -398,10 +466,6 @@ module ActiveRecord
|
|
398
466
|
options[:primary_key] || primary_key(klass || self.klass)
|
399
467
|
end
|
400
468
|
|
401
|
-
def association_primary_key_type
|
402
|
-
klass.type_for_attribute(association_primary_key.to_s)
|
403
|
-
end
|
404
|
-
|
405
469
|
def active_record_primary_key
|
406
470
|
@active_record_primary_key ||= options[:primary_key] || primary_key(active_record)
|
407
471
|
end
|
@@ -413,7 +477,7 @@ module ActiveRecord
|
|
413
477
|
def check_preloadable!
|
414
478
|
return unless scope
|
415
479
|
|
416
|
-
|
480
|
+
unless scope.arity == 0
|
417
481
|
raise ArgumentError, <<-MSG.squish
|
418
482
|
The association scope '#{name}' is instance dependent (the scope
|
419
483
|
block takes an argument). Preloading instance dependent scopes is
|
@@ -424,7 +488,7 @@ module ActiveRecord
|
|
424
488
|
alias :check_eager_loadable! :check_preloadable!
|
425
489
|
|
426
490
|
def join_id_for(owner) # :nodoc:
|
427
|
-
owner[
|
491
|
+
owner[join_foreign_key]
|
428
492
|
end
|
429
493
|
|
430
494
|
def through_reflection
|
@@ -451,12 +515,6 @@ module ActiveRecord
|
|
451
515
|
false
|
452
516
|
end
|
453
517
|
|
454
|
-
# An array of arrays of scopes. Each item in the outside array corresponds to a reflection
|
455
|
-
# in the #chain.
|
456
|
-
def scope_chain
|
457
|
-
scope ? [[scope]] : [[]]
|
458
|
-
end
|
459
|
-
|
460
518
|
def has_scope?
|
461
519
|
scope
|
462
520
|
end
|
@@ -513,7 +571,7 @@ module ActiveRecord
|
|
513
571
|
end
|
514
572
|
|
515
573
|
VALID_AUTOMATIC_INVERSE_MACROS = [:has_many, :has_one, :belongs_to]
|
516
|
-
INVALID_AUTOMATIC_INVERSE_OPTIONS = [:
|
574
|
+
INVALID_AUTOMATIC_INVERSE_OPTIONS = [:through, :foreign_key]
|
517
575
|
|
518
576
|
def add_as_source(seed)
|
519
577
|
seed
|
@@ -531,12 +589,6 @@ module ActiveRecord
|
|
531
589
|
Array(options[:extend])
|
532
590
|
end
|
533
591
|
|
534
|
-
protected
|
535
|
-
|
536
|
-
def actual_source_reflection # FIXME: this is a horrible name
|
537
|
-
self
|
538
|
-
end
|
539
|
-
|
540
592
|
private
|
541
593
|
|
542
594
|
def calculate_constructable(macro, options)
|
@@ -545,18 +597,16 @@ module ActiveRecord
|
|
545
597
|
|
546
598
|
# Attempts to find the inverse association name automatically.
|
547
599
|
# If it cannot find a suitable inverse association name, it returns
|
548
|
-
# nil
|
600
|
+
# +nil+.
|
549
601
|
def inverse_name
|
550
|
-
|
551
|
-
|
552
|
-
nil
|
553
|
-
else
|
554
|
-
@automatic_inverse_of ||= automatic_inverse_of
|
555
|
-
end
|
602
|
+
unless defined?(@inverse_name)
|
603
|
+
@inverse_name = options.fetch(:inverse_of) { automatic_inverse_of }
|
556
604
|
end
|
605
|
+
|
606
|
+
@inverse_name
|
557
607
|
end
|
558
608
|
|
559
|
-
# returns either
|
609
|
+
# returns either +nil+ or the inverse association name that it finds.
|
560
610
|
def automatic_inverse_of
|
561
611
|
if can_find_inverse_of_automatically?(self)
|
562
612
|
inverse_name = ActiveSupport::Inflector.underscore(options[:as] || active_record.name.demodulize).to_sym
|
@@ -573,20 +623,15 @@ module ActiveRecord
|
|
573
623
|
return inverse_name
|
574
624
|
end
|
575
625
|
end
|
576
|
-
|
577
|
-
false
|
578
626
|
end
|
579
627
|
|
580
628
|
# Checks if the inverse reflection that is returned from the
|
581
629
|
# +automatic_inverse_of+ method is a valid reflection. We must
|
582
630
|
# make sure that the reflection's active_record name matches up
|
583
631
|
# with the current reflection's klass name.
|
584
|
-
#
|
585
|
-
# Note: klass will always be valid because when there's a NameError
|
586
|
-
# from calling +klass+, +reflection+ will already be set to false.
|
587
632
|
def valid_inverse_reflection?(reflection)
|
588
633
|
reflection &&
|
589
|
-
klass
|
634
|
+
klass <= reflection.active_record &&
|
590
635
|
can_find_inverse_of_automatically?(reflection)
|
591
636
|
end
|
592
637
|
|
@@ -594,9 +639,8 @@ module ActiveRecord
|
|
594
639
|
# us from being able to guess the inverse automatically. First, the
|
595
640
|
# <tt>inverse_of</tt> option cannot be set to false. Second, we must
|
596
641
|
# have <tt>has_many</tt>, <tt>has_one</tt>, <tt>belongs_to</tt> associations.
|
597
|
-
# Third, we must not have options such as <tt>:
|
598
|
-
#
|
599
|
-
# inverse association.
|
642
|
+
# Third, we must not have options such as <tt>:foreign_key</tt>
|
643
|
+
# which prevent us from correctly guessing the inverse association.
|
600
644
|
#
|
601
645
|
# Anything with a scope can additionally ruin our attempt at finding an
|
602
646
|
# inverse, so we exclude reflections with scopes.
|
@@ -626,10 +670,6 @@ module ActiveRecord
|
|
626
670
|
def derive_join_table
|
627
671
|
ModelSchema.derive_join_table_name active_record.table_name, klass.table_name
|
628
672
|
end
|
629
|
-
|
630
|
-
def primary_key(klass)
|
631
|
-
klass.primary_key || raise(UnknownPrimaryKey.new(klass))
|
632
|
-
end
|
633
673
|
end
|
634
674
|
|
635
675
|
class HasManyReflection < AssociationReflection # :nodoc:
|
@@ -683,16 +723,18 @@ module ActiveRecord
|
|
683
723
|
end
|
684
724
|
end
|
685
725
|
|
686
|
-
def
|
687
|
-
|
688
|
-
JoinKeys.new(key, foreign_key)
|
726
|
+
def join_primary_key(klass = nil)
|
727
|
+
polymorphic? ? association_primary_key(klass) : association_primary_key
|
689
728
|
end
|
690
729
|
|
691
|
-
def
|
692
|
-
|
730
|
+
def join_foreign_key
|
731
|
+
foreign_key
|
693
732
|
end
|
694
733
|
|
695
734
|
private
|
735
|
+
def can_find_inverse_of_automatically?(_)
|
736
|
+
!polymorphic? && super
|
737
|
+
end
|
696
738
|
|
697
739
|
def calculate_constructable(macro, options)
|
698
740
|
!polymorphic?
|
@@ -700,10 +742,6 @@ module ActiveRecord
|
|
700
742
|
end
|
701
743
|
|
702
744
|
class HasAndBelongsToManyReflection < AssociationReflection # :nodoc:
|
703
|
-
def initialize(name, scope, options, active_record)
|
704
|
-
super
|
705
|
-
end
|
706
|
-
|
707
745
|
def macro; :has_and_belongs_to_many; end
|
708
746
|
|
709
747
|
def collection?
|
@@ -711,16 +749,15 @@ module ActiveRecord
|
|
711
749
|
end
|
712
750
|
end
|
713
751
|
|
714
|
-
# Holds all the
|
752
|
+
# Holds all the metadata about a :through association as it was specified
|
715
753
|
# in the Active Record class.
|
716
754
|
class ThroughReflection < AbstractReflection #:nodoc:
|
717
|
-
|
718
|
-
|
719
|
-
:active_record_primary_key, :type, :to => :source_reflection
|
755
|
+
delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for,
|
756
|
+
:active_record_primary_key, :type, :get_join_keys, to: :source_reflection
|
720
757
|
|
721
758
|
def initialize(delegate_reflection)
|
722
759
|
@delegate_reflection = delegate_reflection
|
723
|
-
@klass
|
760
|
+
@klass = delegate_reflection.options[:anonymous_class]
|
724
761
|
@source_reflection_name = delegate_reflection.options[:source]
|
725
762
|
end
|
726
763
|
|
@@ -798,45 +835,12 @@ module ActiveRecord
|
|
798
835
|
through_reflection.clear_association_scope_cache
|
799
836
|
end
|
800
837
|
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
# has_many :articles
|
805
|
-
# has_many :comment_tags, through: :articles
|
806
|
-
# end
|
807
|
-
#
|
808
|
-
# class Article
|
809
|
-
# has_many :comments
|
810
|
-
# has_many :comment_tags, through: :comments, source: :tags
|
811
|
-
# end
|
812
|
-
#
|
813
|
-
# class Comment
|
814
|
-
# has_many :tags
|
815
|
-
# end
|
816
|
-
#
|
817
|
-
# There may be scopes on Person.comment_tags, Article.comment_tags and/or Comment.tags,
|
818
|
-
# but only Comment.tags will be represented in the #chain. So this method creates an array
|
819
|
-
# of scopes corresponding to the chain.
|
820
|
-
def scope_chain
|
821
|
-
@scope_chain ||= begin
|
822
|
-
scope_chain = source_reflection.scope_chain.map(&:dup)
|
823
|
-
|
824
|
-
# Add to it the scope from this reflection (if any)
|
825
|
-
scope_chain.first << scope if scope
|
826
|
-
|
827
|
-
through_scope_chain = through_reflection.scope_chain.map(&:dup)
|
828
|
-
|
829
|
-
if options[:source_type]
|
830
|
-
type = foreign_type
|
831
|
-
source_type = options[:source_type]
|
832
|
-
through_scope_chain.first << lambda { |object|
|
833
|
-
where(type => source_type)
|
834
|
-
}
|
835
|
-
end
|
838
|
+
def scopes
|
839
|
+
source_reflection.scopes + super
|
840
|
+
end
|
836
841
|
|
837
|
-
|
838
|
-
|
839
|
-
end
|
842
|
+
def join_scopes(table, predicate_builder) # :nodoc:
|
843
|
+
source_reflection.join_scopes(table, predicate_builder) + super
|
840
844
|
end
|
841
845
|
|
842
846
|
def has_scope?
|
@@ -845,10 +849,6 @@ module ActiveRecord
|
|
845
849
|
through_reflection.has_scope?
|
846
850
|
end
|
847
851
|
|
848
|
-
def join_keys(association_klass)
|
849
|
-
source_reflection.join_keys(association_klass)
|
850
|
-
end
|
851
|
-
|
852
852
|
# A through association is nested if there would be more than one join table
|
853
853
|
def nested?
|
854
854
|
source_reflection.through_reflection? || through_reflection.through_reflection?
|
@@ -863,10 +863,6 @@ module ActiveRecord
|
|
863
863
|
actual_source_reflection.options[:primary_key] || primary_key(klass || self.klass)
|
864
864
|
end
|
865
865
|
|
866
|
-
def association_primary_key_type
|
867
|
-
klass.type_for_attribute(association_primary_key.to_s)
|
868
|
-
end
|
869
|
-
|
870
866
|
# Gets an array of possible <tt>:through</tt> source reflection names in both singular and plural form.
|
871
867
|
#
|
872
868
|
# class Post < ActiveRecord::Base
|
@@ -891,15 +887,13 @@ module ActiveRecord
|
|
891
887
|
}
|
892
888
|
|
893
889
|
if names.length > 1
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
" #{macro} :#{name}, #{example_options}\n" \
|
902
|
-
" end"
|
890
|
+
raise AmbiguousSourceReflectionForThroughAssociation.new(
|
891
|
+
active_record.name,
|
892
|
+
macro,
|
893
|
+
name,
|
894
|
+
options,
|
895
|
+
source_reflection_names
|
896
|
+
)
|
903
897
|
end
|
904
898
|
|
905
899
|
@source_reflection_name = names.first
|
@@ -913,10 +907,6 @@ module ActiveRecord
|
|
913
907
|
through_reflection.options
|
914
908
|
end
|
915
909
|
|
916
|
-
def join_id_for(owner) # :nodoc:
|
917
|
-
source_reflection.join_id_for(owner)
|
918
|
-
end
|
919
|
-
|
920
910
|
def check_validity!
|
921
911
|
if through_reflection.nil?
|
922
912
|
raise HasManyThroughAssociationNotFoundError.new(active_record.name, self)
|
@@ -946,6 +936,14 @@ module ActiveRecord
|
|
946
936
|
raise HasOneThroughCantAssociateThroughCollection.new(active_record.name, self, through_reflection)
|
947
937
|
end
|
948
938
|
|
939
|
+
if parent_reflection.nil?
|
940
|
+
reflections = active_record.reflections.keys.map(&:to_sym)
|
941
|
+
|
942
|
+
if reflections.index(through_reflection.name) > reflections.index(name)
|
943
|
+
raise HasManyThroughOrderError.new(active_record.name, self, through_reflection)
|
944
|
+
end
|
945
|
+
end
|
946
|
+
|
949
947
|
check_validity_of_inverse!
|
950
948
|
end
|
951
949
|
|
@@ -967,28 +965,25 @@ module ActiveRecord
|
|
967
965
|
collect_join_reflections(seed + [self])
|
968
966
|
end
|
969
967
|
|
970
|
-
def collect_join_reflections(seed)
|
971
|
-
a = source_reflection.add_as_source seed
|
972
|
-
if options[:source_type]
|
973
|
-
through_reflection.add_as_polymorphic_through self, a
|
974
|
-
else
|
975
|
-
through_reflection.add_as_through a
|
976
|
-
end
|
977
|
-
end
|
978
|
-
|
979
968
|
protected
|
980
|
-
|
981
969
|
def actual_source_reflection # FIXME: this is a horrible name
|
982
|
-
source_reflection.
|
970
|
+
source_reflection.actual_source_reflection
|
983
971
|
end
|
984
972
|
|
985
|
-
|
986
|
-
|
973
|
+
private
|
974
|
+
attr_reader :delegate_reflection
|
975
|
+
|
976
|
+
def collect_join_reflections(seed)
|
977
|
+
a = source_reflection.add_as_source seed
|
978
|
+
if options[:source_type]
|
979
|
+
through_reflection.add_as_polymorphic_through self, a
|
980
|
+
else
|
981
|
+
through_reflection.add_as_through a
|
982
|
+
end
|
987
983
|
end
|
988
984
|
|
989
985
|
def inverse_name; delegate_reflection.send(:inverse_name); end
|
990
986
|
|
991
|
-
private
|
992
987
|
def derive_class_name
|
993
988
|
# get the class_name of the belongs_to association of the through reflection
|
994
989
|
options[:source_type] || source_reflection.class_name
|
@@ -998,52 +993,35 @@ module ActiveRecord
|
|
998
993
|
public_instance_methods
|
999
994
|
|
1000
995
|
delegate(*delegate_methods, to: :delegate_reflection)
|
1001
|
-
|
1002
996
|
end
|
1003
997
|
|
1004
|
-
class PolymorphicReflection <
|
998
|
+
class PolymorphicReflection < AbstractReflection # :nodoc:
|
999
|
+
delegate :klass, :scope, :plural_name, :type, :get_join_keys, :scope_for, to: :@reflection
|
1000
|
+
|
1005
1001
|
def initialize(reflection, previous_reflection)
|
1006
1002
|
@reflection = reflection
|
1007
1003
|
@previous_reflection = previous_reflection
|
1008
1004
|
end
|
1009
1005
|
|
1010
|
-
def
|
1011
|
-
@
|
1012
|
-
|
1013
|
-
|
1014
|
-
def scope
|
1015
|
-
@reflection.scope
|
1016
|
-
end
|
1017
|
-
|
1018
|
-
def table_name
|
1019
|
-
@reflection.table_name
|
1020
|
-
end
|
1021
|
-
|
1022
|
-
def plural_name
|
1023
|
-
@reflection.plural_name
|
1024
|
-
end
|
1025
|
-
|
1026
|
-
def join_keys(association_klass)
|
1027
|
-
@reflection.join_keys(association_klass)
|
1028
|
-
end
|
1029
|
-
|
1030
|
-
def type
|
1031
|
-
@reflection.type
|
1006
|
+
def join_scopes(table, predicate_builder) # :nodoc:
|
1007
|
+
scopes = @previous_reflection.join_scopes(table, predicate_builder) + super
|
1008
|
+
scopes << build_scope(table, predicate_builder).instance_exec(nil, &source_type_scope)
|
1032
1009
|
end
|
1033
1010
|
|
1034
1011
|
def constraints
|
1035
|
-
@reflection.constraints + [
|
1012
|
+
@reflection.constraints + [source_type_scope]
|
1036
1013
|
end
|
1037
1014
|
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1015
|
+
private
|
1016
|
+
def source_type_scope
|
1017
|
+
type = @previous_reflection.foreign_type
|
1018
|
+
source_type = @previous_reflection.options[:source_type]
|
1019
|
+
lambda { |object| where(type => source_type) }
|
1020
|
+
end
|
1043
1021
|
end
|
1044
1022
|
|
1045
|
-
class RuntimeReflection <
|
1046
|
-
|
1023
|
+
class RuntimeReflection < AbstractReflection # :nodoc:
|
1024
|
+
delegate :scope, :type, :constraints, :get_join_keys, to: :@reflection
|
1047
1025
|
|
1048
1026
|
def initialize(reflection, association)
|
1049
1027
|
@reflection = reflection
|
@@ -1054,24 +1032,8 @@ module ActiveRecord
|
|
1054
1032
|
@association.klass
|
1055
1033
|
end
|
1056
1034
|
|
1057
|
-
def
|
1058
|
-
klass.
|
1059
|
-
end
|
1060
|
-
|
1061
|
-
def constraints
|
1062
|
-
@reflection.constraints
|
1063
|
-
end
|
1064
|
-
|
1065
|
-
def source_type_info
|
1066
|
-
@reflection.source_type_info
|
1067
|
-
end
|
1068
|
-
|
1069
|
-
def alias_candidate(name)
|
1070
|
-
"#{plural_name}_#{name}_join"
|
1071
|
-
end
|
1072
|
-
|
1073
|
-
def alias_name
|
1074
|
-
Arel::Table.new(table_name)
|
1035
|
+
def aliased_table
|
1036
|
+
@aliased_table ||= Arel::Table.new(table_name, type_caster: klass.type_caster)
|
1075
1037
|
end
|
1076
1038
|
|
1077
1039
|
def all_includes; yield; end
|