activerecord 5.0.7.2 → 6.0.6.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 +4 -4
- data/CHANGELOG.md +844 -1944
- data/MIT-LICENSE +3 -1
- data/README.rdoc +9 -7
- data/examples/performance.rb +31 -29
- data/examples/simple.rb +5 -3
- data/lib/active_record/advisory_lock_base.rb +18 -0
- data/lib/active_record/aggregations.rb +249 -247
- data/lib/active_record/association_relation.rb +18 -14
- data/lib/active_record/associations/alias_tracker.rb +24 -34
- data/lib/active_record/associations/association.rb +113 -55
- data/lib/active_record/associations/association_scope.rb +102 -96
- 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 +41 -62
- 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 +93 -254
- data/lib/active_record/associations/collection_proxy.rb +159 -122
- data/lib/active_record/associations/foreign_association.rb +9 -0
- data/lib/active_record/associations/has_many_association.rb +23 -30
- 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 +43 -85
- data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
- data/lib/active_record/associations/join_dependency.rb +152 -177
- data/lib/active_record/associations/preloader/association.rb +101 -97
- data/lib/active_record/associations/preloader/through_association.rb +77 -76
- data/lib/active_record/associations/preloader.rb +94 -103
- data/lib/active_record/associations/singular_association.rb +12 -45
- data/lib/active_record/associations/through_association.rb +27 -15
- data/lib/active_record/associations.rb +1603 -1592
- data/lib/active_record/attribute_assignment.rb +54 -61
- data/lib/active_record/attribute_decorators.rb +38 -17
- data/lib/active_record/attribute_methods/before_type_cast.rb +12 -8
- data/lib/active_record/attribute_methods/dirty.rb +179 -109
- data/lib/active_record/attribute_methods/primary_key.rb +85 -92
- data/lib/active_record/attribute_methods/query.rb +4 -3
- data/lib/active_record/attribute_methods/read.rb +20 -49
- data/lib/active_record/attribute_methods/serialization.rb +29 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -66
- data/lib/active_record/attribute_methods/write.rb +34 -33
- data/lib/active_record/attribute_methods.rb +66 -106
- data/lib/active_record/attributes.rb +38 -25
- data/lib/active_record/autosave_association.rb +58 -39
- data/lib/active_record/base.rb +27 -24
- data/lib/active_record/callbacks.rb +64 -35
- data/lib/active_record/coders/json.rb +2 -0
- data/lib/active_record/coders/yaml_column.rb +34 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +558 -323
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +23 -5
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +215 -94
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +59 -35
- data/lib/active_record/connection_adapters/abstract/quoting.rb +128 -75
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +33 -28
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +233 -147
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +400 -213
- data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -79
- data/lib/active_record/connection_adapters/abstract_adapter.rb +373 -202
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +401 -562
- data/lib/active_record/connection_adapters/column.rb +41 -13
- data/lib/active_record/connection_adapters/connection_specification.rb +172 -139
- 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 +137 -49
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -23
- data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -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 +268 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +12 -13
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +48 -30
- data/lib/active_record/connection_adapters/postgresql/column.rb +19 -31
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -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 -11
- 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 +12 -2
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -4
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -18
- 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 +44 -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 +30 -9
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -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 +8 -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 +20 -26
- 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 +34 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +378 -308
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +26 -25
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -6
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +383 -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 +119 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +72 -18
- 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 +261 -267
- data/lib/active_record/connection_adapters/statement_pool.rb +9 -8
- data/lib/active_record/connection_handling.rb +143 -40
- data/lib/active_record/core.rb +207 -160
- data/lib/active_record/counter_cache.rb +60 -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 +78 -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 -87
- data/lib/active_record/enum.rb +67 -23
- data/lib/active_record/errors.rb +114 -18
- data/lib/active_record/explain.rb +4 -4
- 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 +152 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +194 -504
- data/lib/active_record/gem_version.rb +5 -3
- data/lib/active_record/inheritance.rb +150 -99
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +116 -25
- data/lib/active_record/internal_metadata.rb +16 -19
- data/lib/active_record/legacy_yaml_adapter.rb +4 -2
- data/lib/active_record/locking/optimistic.rb +85 -86
- 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 +87 -0
- data/lib/active_record/middleware/database_selector.rb +74 -0
- data/lib/active_record/migration/command_recorder.rb +134 -100
- data/lib/active_record/migration/compatibility.rb +174 -56
- data/lib/active_record/migration/join_table.rb +8 -7
- data/lib/active_record/migration.rb +369 -302
- data/lib/active_record/model_schema.rb +160 -127
- data/lib/active_record/nested_attributes.rb +213 -202
- data/lib/active_record/no_touching.rb +12 -3
- data/lib/active_record/null_relation.rb +12 -34
- data/lib/active_record/persistence.rb +446 -77
- data/lib/active_record/query_cache.rb +13 -12
- data/lib/active_record/querying.rb +37 -24
- 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 +312 -177
- data/lib/active_record/readonly_attributes.rb +5 -4
- data/lib/active_record/reflection.rb +214 -254
- data/lib/active_record/relation/batches/batch_enumerator.rb +3 -1
- data/lib/active_record/relation/batches.rb +98 -52
- data/lib/active_record/relation/calculations.rb +212 -173
- data/lib/active_record/relation/delegation.rb +73 -69
- data/lib/active_record/relation/finder_methods.rb +207 -247
- data/lib/active_record/relation/from_clause.rb +6 -8
- data/lib/active_record/relation/merger.rb +82 -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 +83 -105
- data/lib/active_record/relation/query_attribute.rb +33 -2
- data/lib/active_record/relation/query_methods.rb +488 -332
- data/lib/active_record/relation/record_fetch_warning.rb +5 -3
- data/lib/active_record/relation/spawn_methods.rb +8 -8
- data/lib/active_record/relation/where_clause.rb +111 -96
- data/lib/active_record/relation/where_clause_factory.rb +6 -11
- data/lib/active_record/relation.rb +443 -318
- data/lib/active_record/result.rb +69 -40
- 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 +16 -6
- data/lib/active_record/scoping/default.rb +92 -95
- data/lib/active_record/scoping/named.rb +51 -26
- data/lib/active_record/scoping.rb +20 -20
- 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 +6 -3
- data/lib/active_record/table_metadata.rb +39 -18
- data/lib/active_record/tasks/database_tasks.rb +271 -81
- data/lib/active_record/tasks/mysql_database_tasks.rb +54 -91
- data/lib/active_record/tasks/postgresql_database_tasks.rb +77 -47
- data/lib/active_record/tasks/sqlite_database_tasks.rb +33 -16
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +243 -0
- data/lib/active_record/timestamp.rb +70 -36
- data/lib/active_record/touch_later.rb +8 -6
- data/lib/active_record/transactions.rb +141 -157
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type/adapter_specific_registry.rb +44 -48
- 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 -4
- 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 -9
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +12 -1
- data/lib/active_record/type/type_map.rb +14 -17
- data/lib/active_record/type/unsigned_integer.rb +16 -0
- data/lib/active_record/type.rb +23 -18
- 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 -2
- 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 -5
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +37 -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 +256 -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 +203 -0
- data/lib/arel/visitors/dot.rb +296 -0
- data/lib/arel/visitors/ibm_db.rb +34 -0
- data/lib/arel/visitors/informix.rb +62 -0
- data/lib/arel/visitors/mssql.rb +156 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +158 -0
- data/lib/arel/visitors/oracle12.rb +65 -0
- data/lib/arel/visitors/postgresql.rb +109 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +888 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors/where_sql.rb +22 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +62 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -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 -3
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -30
- data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +10 -1
- data/lib/rails/generators/active_record.rb +7 -5
- metadata +138 -52
- 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 -132
- 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
- /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/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -1,5 +1,6 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/string/filters"
|
3
4
|
|
4
5
|
module ActiveRecord
|
5
6
|
# = Active Record Reflection
|
@@ -7,37 +8,41 @@ module ActiveRecord
|
|
7
8
|
extend ActiveSupport::Concern
|
8
9
|
|
9
10
|
included do
|
10
|
-
class_attribute :_reflections, instance_writer: false
|
11
|
-
class_attribute :aggregate_reflections, instance_writer: false
|
12
|
-
self._reflections = {}
|
13
|
-
self.aggregate_reflections = {}
|
11
|
+
class_attribute :_reflections, instance_writer: false, default: {}
|
12
|
+
class_attribute :aggregate_reflections, instance_writer: false, default: {}
|
14
13
|
end
|
15
14
|
|
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
|
15
|
+
class << self
|
16
|
+
def create(macro, name, scope, options, ar)
|
17
|
+
reflection = reflection_class_for(macro).new(name, scope, options, ar)
|
18
|
+
options[:through] ? ThroughReflection.new(reflection) : reflection
|
19
|
+
end
|
33
20
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
21
|
+
def add_reflection(ar, name, reflection)
|
22
|
+
ar.clear_reflections_cache
|
23
|
+
name = -name.to_s
|
24
|
+
ar._reflections = ar._reflections.except(name).merge!(name => reflection)
|
25
|
+
end
|
38
26
|
|
39
|
-
|
40
|
-
|
27
|
+
def add_aggregate_reflection(ar, name, reflection)
|
28
|
+
ar.aggregate_reflections = ar.aggregate_reflections.merge(-name.to_s => reflection)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def reflection_class_for(macro)
|
33
|
+
case macro
|
34
|
+
when :composed_of
|
35
|
+
AggregateReflection
|
36
|
+
when :has_many
|
37
|
+
HasManyReflection
|
38
|
+
when :has_one
|
39
|
+
HasOneReflection
|
40
|
+
when :belongs_to
|
41
|
+
BelongsToReflection
|
42
|
+
else
|
43
|
+
raise "Unsupported Macro: #{macro}"
|
44
|
+
end
|
45
|
+
end
|
41
46
|
end
|
42
47
|
|
43
48
|
# \Reflection enables the ability to examine the associations and aggregations of
|
@@ -135,8 +140,8 @@ module ActiveRecord
|
|
135
140
|
# BelongsToReflection
|
136
141
|
# HasAndBelongsToManyReflection
|
137
142
|
# ThroughReflection
|
138
|
-
#
|
139
|
-
#
|
143
|
+
# PolymorphicReflection
|
144
|
+
# RuntimeReflection
|
140
145
|
class AbstractReflection # :nodoc:
|
141
146
|
def through_reflection?
|
142
147
|
false
|
@@ -152,14 +157,6 @@ module ActiveRecord
|
|
152
157
|
klass.new(attributes, &block)
|
153
158
|
end
|
154
159
|
|
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
160
|
# Returns the class name for the macro.
|
164
161
|
#
|
165
162
|
# <tt>composed_of :balance, class_name: 'Money'</tt> returns <tt>'Money'</tt>
|
@@ -170,12 +167,54 @@ module ActiveRecord
|
|
170
167
|
|
171
168
|
JoinKeys = Struct.new(:key, :foreign_key) # :nodoc:
|
172
169
|
|
173
|
-
def join_keys
|
174
|
-
|
170
|
+
def join_keys
|
171
|
+
@join_keys ||= get_join_keys(klass)
|
172
|
+
end
|
173
|
+
|
174
|
+
# Returns a list of scopes that should be applied for this Reflection
|
175
|
+
# object when querying the database.
|
176
|
+
def scopes
|
177
|
+
scope ? [scope] : []
|
178
|
+
end
|
179
|
+
|
180
|
+
def join_scope(table, foreign_table, foreign_klass)
|
181
|
+
predicate_builder = predicate_builder(table)
|
182
|
+
scope_chain_items = join_scopes(table, predicate_builder)
|
183
|
+
klass_scope = klass_join_scope(table, predicate_builder)
|
184
|
+
|
185
|
+
if type
|
186
|
+
klass_scope.where!(type => foreign_klass.polymorphic_name)
|
187
|
+
end
|
188
|
+
|
189
|
+
scope_chain_items.inject(klass_scope, &:merge!)
|
190
|
+
|
191
|
+
key = join_keys.key
|
192
|
+
foreign_key = join_keys.foreign_key
|
193
|
+
|
194
|
+
klass_scope.where!(table[key].eq(foreign_table[foreign_key]))
|
195
|
+
|
196
|
+
if klass.finder_needs_type_condition?
|
197
|
+
klass_scope.where!(klass.send(:type_condition, table))
|
198
|
+
end
|
199
|
+
|
200
|
+
klass_scope
|
201
|
+
end
|
202
|
+
|
203
|
+
def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc:
|
204
|
+
if scope
|
205
|
+
[scope_for(build_scope(table, predicate_builder, klass))]
|
206
|
+
else
|
207
|
+
[]
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def klass_join_scope(table, predicate_builder) # :nodoc:
|
212
|
+
relation = build_scope(table, predicate_builder)
|
213
|
+
klass.scope_for_association(relation)
|
175
214
|
end
|
176
215
|
|
177
216
|
def constraints
|
178
|
-
|
217
|
+
chain.flat_map(&:scopes)
|
179
218
|
end
|
180
219
|
|
181
220
|
def counter_cache_column
|
@@ -247,6 +286,40 @@ module ActiveRecord
|
|
247
286
|
def chain
|
248
287
|
collect_join_chain
|
249
288
|
end
|
289
|
+
|
290
|
+
def get_join_keys(association_klass)
|
291
|
+
JoinKeys.new(join_primary_key(association_klass), join_foreign_key)
|
292
|
+
end
|
293
|
+
|
294
|
+
def build_scope(table, predicate_builder = predicate_builder(table), klass = self.klass)
|
295
|
+
Relation.create(
|
296
|
+
klass,
|
297
|
+
table: table,
|
298
|
+
predicate_builder: predicate_builder
|
299
|
+
)
|
300
|
+
end
|
301
|
+
|
302
|
+
def join_primary_key(*)
|
303
|
+
foreign_key
|
304
|
+
end
|
305
|
+
|
306
|
+
def join_foreign_key
|
307
|
+
active_record_primary_key
|
308
|
+
end
|
309
|
+
|
310
|
+
protected
|
311
|
+
def actual_source_reflection # FIXME: this is a horrible name
|
312
|
+
self
|
313
|
+
end
|
314
|
+
|
315
|
+
private
|
316
|
+
def predicate_builder(table)
|
317
|
+
PredicateBuilder.new(TableMetadata.new(klass, table))
|
318
|
+
end
|
319
|
+
|
320
|
+
def primary_key(klass)
|
321
|
+
klass.primary_key || raise(UnknownPrimaryKey.new(klass))
|
322
|
+
end
|
250
323
|
end
|
251
324
|
|
252
325
|
# Base class for AggregateReflection and AssociationReflection. Objects of
|
@@ -281,7 +354,6 @@ module ActiveRecord
|
|
281
354
|
end
|
282
355
|
|
283
356
|
def autosave=(autosave)
|
284
|
-
@automatic_inverse_of = false
|
285
357
|
@options[:autosave] = autosave
|
286
358
|
parent_reflection = self.parent_reflection
|
287
359
|
if parent_reflection
|
@@ -293,6 +365,17 @@ module ActiveRecord
|
|
293
365
|
#
|
294
366
|
# <tt>composed_of :balance, class_name: 'Money'</tt> returns the Money class
|
295
367
|
# <tt>has_many :clients</tt> returns the Client class
|
368
|
+
#
|
369
|
+
# class Company < ActiveRecord::Base
|
370
|
+
# has_many :clients
|
371
|
+
# end
|
372
|
+
#
|
373
|
+
# Company.reflect_on_association(:clients).klass
|
374
|
+
# # => Client
|
375
|
+
#
|
376
|
+
# <b>Note:</b> Do not call +klass.new+ or +klass.create+ to instantiate
|
377
|
+
# a new association object. Use +build_association+ or +create_association+
|
378
|
+
# instead. This allows plugins to hook into association object creation.
|
296
379
|
def klass
|
297
380
|
@klass ||= compute_class(class_name)
|
298
381
|
end
|
@@ -311,8 +394,8 @@ module ActiveRecord
|
|
311
394
|
active_record == other_aggregation.active_record
|
312
395
|
end
|
313
396
|
|
314
|
-
def scope_for(
|
315
|
-
|
397
|
+
def scope_for(relation, owner = nil)
|
398
|
+
relation.instance_exec(owner, &scope) || relation
|
316
399
|
end
|
317
400
|
|
318
401
|
private
|
@@ -321,8 +404,7 @@ module ActiveRecord
|
|
321
404
|
end
|
322
405
|
end
|
323
406
|
|
324
|
-
|
325
|
-
# Holds all the meta-data about an aggregation as it was specified in the
|
407
|
+
# Holds all the metadata about an aggregation as it was specified in the
|
326
408
|
# Active Record class.
|
327
409
|
class AggregateReflection < MacroReflection #:nodoc:
|
328
410
|
def mapping
|
@@ -331,26 +413,13 @@ module ActiveRecord
|
|
331
413
|
end
|
332
414
|
end
|
333
415
|
|
334
|
-
# Holds all the
|
416
|
+
# Holds all the metadata about an association as it was specified in the
|
335
417
|
# Active Record class.
|
336
418
|
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
419
|
def compute_class(name)
|
420
|
+
if polymorphic?
|
421
|
+
raise ArgumentError, "Polymorphic associations do not support computing the class."
|
422
|
+
end
|
354
423
|
active_record.send(:compute_type, name)
|
355
424
|
end
|
356
425
|
|
@@ -359,22 +428,21 @@ module ActiveRecord
|
|
359
428
|
|
360
429
|
def initialize(name, scope, options, active_record)
|
361
430
|
super
|
362
|
-
@automatic_inverse_of = nil
|
363
431
|
@type = options[:as] && (options[:foreign_type] || "#{options[:as]}_type")
|
364
|
-
@foreign_type = options[:foreign_type] || "#{name}_type"
|
432
|
+
@foreign_type = options[:polymorphic] && (options[:foreign_type] || "#{name}_type")
|
365
433
|
@constructable = calculate_constructable(macro, options)
|
366
|
-
|
367
|
-
|
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(
|
371
|
-
key =
|
440
|
+
def association_scope_cache(klass, owner, &block)
|
441
|
+
key = self
|
372
442
|
if polymorphic?
|
373
443
|
key = [key, owner._read_attribute(@foreign_type)]
|
374
444
|
end
|
375
|
-
|
376
|
-
@association_scope_cache[key] ||= yield
|
377
|
-
}
|
445
|
+
klass.cached_find_by_statement(key, &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
|
@@ -444,19 +508,13 @@ module ActiveRecord
|
|
444
508
|
# This is for clearing cache on the reflection. Useful for tests that need to compare
|
445
509
|
# SQL queries on associations.
|
446
510
|
def clear_association_scope_cache # :nodoc:
|
447
|
-
|
511
|
+
klass.initialize_find_by_cache
|
448
512
|
end
|
449
513
|
|
450
514
|
def nested?
|
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,32 +589,23 @@ 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
|
-
|
542
593
|
def calculate_constructable(macro, options)
|
543
594
|
true
|
544
595
|
end
|
545
596
|
|
546
597
|
# Attempts to find the inverse association name automatically.
|
547
598
|
# If it cannot find a suitable inverse association name, it returns
|
548
|
-
# nil
|
599
|
+
# +nil+.
|
549
600
|
def inverse_name
|
550
|
-
|
551
|
-
|
552
|
-
nil
|
553
|
-
else
|
554
|
-
@automatic_inverse_of ||= automatic_inverse_of
|
555
|
-
end
|
601
|
+
unless defined?(@inverse_name)
|
602
|
+
@inverse_name = options.fetch(:inverse_of) { automatic_inverse_of }
|
556
603
|
end
|
604
|
+
|
605
|
+
@inverse_name
|
557
606
|
end
|
558
607
|
|
559
|
-
# returns either
|
608
|
+
# returns either +nil+ or the inverse association name that it finds.
|
560
609
|
def automatic_inverse_of
|
561
610
|
if can_find_inverse_of_automatically?(self)
|
562
611
|
inverse_name = ActiveSupport::Inflector.underscore(options[:as] || active_record.name.demodulize).to_sym
|
@@ -570,23 +619,18 @@ module ActiveRecord
|
|
570
619
|
end
|
571
620
|
|
572
621
|
if valid_inverse_reflection?(reflection)
|
573
|
-
|
622
|
+
inverse_name
|
574
623
|
end
|
575
624
|
end
|
576
|
-
|
577
|
-
false
|
578
625
|
end
|
579
626
|
|
580
627
|
# Checks if the inverse reflection that is returned from the
|
581
628
|
# +automatic_inverse_of+ method is a valid reflection. We must
|
582
629
|
# make sure that the reflection's active_record name matches up
|
583
630
|
# 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
631
|
def valid_inverse_reflection?(reflection)
|
588
632
|
reflection &&
|
589
|
-
klass
|
633
|
+
klass <= reflection.active_record &&
|
590
634
|
can_find_inverse_of_automatically?(reflection)
|
591
635
|
end
|
592
636
|
|
@@ -594,9 +638,8 @@ module ActiveRecord
|
|
594
638
|
# us from being able to guess the inverse automatically. First, the
|
595
639
|
# <tt>inverse_of</tt> option cannot be set to false. Second, we must
|
596
640
|
# 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.
|
641
|
+
# Third, we must not have options such as <tt>:foreign_key</tt>
|
642
|
+
# which prevent us from correctly guessing the inverse association.
|
600
643
|
#
|
601
644
|
# Anything with a scope can additionally ruin our attempt at finding an
|
602
645
|
# inverse, so we exclude reflections with scopes.
|
@@ -626,10 +669,6 @@ module ActiveRecord
|
|
626
669
|
def derive_join_table
|
627
670
|
ModelSchema.derive_join_table_name active_record.table_name, klass.table_name
|
628
671
|
end
|
629
|
-
|
630
|
-
def primary_key(klass)
|
631
|
-
klass.primary_key || raise(UnknownPrimaryKey.new(klass))
|
632
|
-
end
|
633
672
|
end
|
634
673
|
|
635
674
|
class HasManyReflection < AssociationReflection # :nodoc:
|
@@ -664,7 +703,6 @@ module ActiveRecord
|
|
664
703
|
end
|
665
704
|
|
666
705
|
private
|
667
|
-
|
668
706
|
def calculate_constructable(macro, options)
|
669
707
|
!options[:through]
|
670
708
|
end
|
@@ -683,16 +721,18 @@ module ActiveRecord
|
|
683
721
|
end
|
684
722
|
end
|
685
723
|
|
686
|
-
def
|
687
|
-
|
688
|
-
JoinKeys.new(key, foreign_key)
|
724
|
+
def join_primary_key(klass = nil)
|
725
|
+
polymorphic? ? association_primary_key(klass) : association_primary_key
|
689
726
|
end
|
690
727
|
|
691
|
-
def
|
692
|
-
|
728
|
+
def join_foreign_key
|
729
|
+
foreign_key
|
693
730
|
end
|
694
731
|
|
695
732
|
private
|
733
|
+
def can_find_inverse_of_automatically?(_)
|
734
|
+
!polymorphic? && super
|
735
|
+
end
|
696
736
|
|
697
737
|
def calculate_constructable(macro, options)
|
698
738
|
!polymorphic?
|
@@ -700,10 +740,6 @@ module ActiveRecord
|
|
700
740
|
end
|
701
741
|
|
702
742
|
class HasAndBelongsToManyReflection < AssociationReflection # :nodoc:
|
703
|
-
def initialize(name, scope, options, active_record)
|
704
|
-
super
|
705
|
-
end
|
706
|
-
|
707
743
|
def macro; :has_and_belongs_to_many; end
|
708
744
|
|
709
745
|
def collection?
|
@@ -711,16 +747,15 @@ module ActiveRecord
|
|
711
747
|
end
|
712
748
|
end
|
713
749
|
|
714
|
-
# Holds all the
|
750
|
+
# Holds all the metadata about a :through association as it was specified
|
715
751
|
# in the Active Record class.
|
716
752
|
class ThroughReflection < AbstractReflection #:nodoc:
|
717
|
-
|
718
|
-
|
719
|
-
:active_record_primary_key, :type, :to => :source_reflection
|
753
|
+
delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for,
|
754
|
+
:active_record_primary_key, :type, :get_join_keys, to: :source_reflection
|
720
755
|
|
721
756
|
def initialize(delegate_reflection)
|
722
757
|
@delegate_reflection = delegate_reflection
|
723
|
-
@klass
|
758
|
+
@klass = delegate_reflection.options[:anonymous_class]
|
724
759
|
@source_reflection_name = delegate_reflection.options[:source]
|
725
760
|
end
|
726
761
|
|
@@ -798,45 +833,12 @@ module ActiveRecord
|
|
798
833
|
through_reflection.clear_association_scope_cache
|
799
834
|
end
|
800
835
|
|
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
|
836
|
+
def scopes
|
837
|
+
source_reflection.scopes + super
|
838
|
+
end
|
836
839
|
|
837
|
-
|
838
|
-
|
839
|
-
end
|
840
|
+
def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc:
|
841
|
+
source_reflection.join_scopes(table, predicate_builder, klass) + super
|
840
842
|
end
|
841
843
|
|
842
844
|
def has_scope?
|
@@ -845,10 +847,6 @@ module ActiveRecord
|
|
845
847
|
through_reflection.has_scope?
|
846
848
|
end
|
847
849
|
|
848
|
-
def join_keys(association_klass)
|
849
|
-
source_reflection.join_keys(association_klass)
|
850
|
-
end
|
851
|
-
|
852
850
|
# A through association is nested if there would be more than one join table
|
853
851
|
def nested?
|
854
852
|
source_reflection.through_reflection? || through_reflection.through_reflection?
|
@@ -863,10 +861,6 @@ module ActiveRecord
|
|
863
861
|
actual_source_reflection.options[:primary_key] || primary_key(klass || self.klass)
|
864
862
|
end
|
865
863
|
|
866
|
-
def association_primary_key_type
|
867
|
-
klass.type_for_attribute(association_primary_key.to_s)
|
868
|
-
end
|
869
|
-
|
870
864
|
# Gets an array of possible <tt>:through</tt> source reflection names in both singular and plural form.
|
871
865
|
#
|
872
866
|
# class Post < ActiveRecord::Base
|
@@ -891,15 +885,13 @@ module ActiveRecord
|
|
891
885
|
}
|
892
886
|
|
893
887
|
if names.length > 1
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
" #{macro} :#{name}, #{example_options}\n" \
|
902
|
-
" end"
|
888
|
+
raise AmbiguousSourceReflectionForThroughAssociation.new(
|
889
|
+
active_record.name,
|
890
|
+
macro,
|
891
|
+
name,
|
892
|
+
options,
|
893
|
+
source_reflection_names
|
894
|
+
)
|
903
895
|
end
|
904
896
|
|
905
897
|
@source_reflection_name = names.first
|
@@ -913,10 +905,6 @@ module ActiveRecord
|
|
913
905
|
through_reflection.options
|
914
906
|
end
|
915
907
|
|
916
|
-
def join_id_for(owner) # :nodoc:
|
917
|
-
source_reflection.join_id_for(owner)
|
918
|
-
end
|
919
|
-
|
920
908
|
def check_validity!
|
921
909
|
if through_reflection.nil?
|
922
910
|
raise HasManyThroughAssociationNotFoundError.new(active_record.name, self)
|
@@ -946,6 +934,14 @@ module ActiveRecord
|
|
946
934
|
raise HasOneThroughCantAssociateThroughCollection.new(active_record.name, self, through_reflection)
|
947
935
|
end
|
948
936
|
|
937
|
+
if parent_reflection.nil?
|
938
|
+
reflections = active_record.reflections.keys.map(&:to_sym)
|
939
|
+
|
940
|
+
if reflections.index(through_reflection.name) > reflections.index(name)
|
941
|
+
raise HasManyThroughOrderError.new(active_record.name, self, through_reflection)
|
942
|
+
end
|
943
|
+
end
|
944
|
+
|
949
945
|
check_validity_of_inverse!
|
950
946
|
end
|
951
947
|
|
@@ -967,28 +963,25 @@ module ActiveRecord
|
|
967
963
|
collect_join_reflections(seed + [self])
|
968
964
|
end
|
969
965
|
|
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
966
|
protected
|
980
|
-
|
981
967
|
def actual_source_reflection # FIXME: this is a horrible name
|
982
|
-
source_reflection.
|
968
|
+
source_reflection.actual_source_reflection
|
983
969
|
end
|
984
970
|
|
985
|
-
|
986
|
-
|
971
|
+
private
|
972
|
+
attr_reader :delegate_reflection
|
973
|
+
|
974
|
+
def collect_join_reflections(seed)
|
975
|
+
a = source_reflection.add_as_source seed
|
976
|
+
if options[:source_type]
|
977
|
+
through_reflection.add_as_polymorphic_through self, a
|
978
|
+
else
|
979
|
+
through_reflection.add_as_through a
|
980
|
+
end
|
987
981
|
end
|
988
982
|
|
989
983
|
def inverse_name; delegate_reflection.send(:inverse_name); end
|
990
984
|
|
991
|
-
private
|
992
985
|
def derive_class_name
|
993
986
|
# get the class_name of the belongs_to association of the through reflection
|
994
987
|
options[:source_type] || source_reflection.class_name
|
@@ -998,52 +991,35 @@ module ActiveRecord
|
|
998
991
|
public_instance_methods
|
999
992
|
|
1000
993
|
delegate(*delegate_methods, to: :delegate_reflection)
|
1001
|
-
|
1002
994
|
end
|
1003
995
|
|
1004
|
-
class PolymorphicReflection <
|
996
|
+
class PolymorphicReflection < AbstractReflection # :nodoc:
|
997
|
+
delegate :klass, :scope, :plural_name, :type, :get_join_keys, :scope_for, to: :@reflection
|
998
|
+
|
1005
999
|
def initialize(reflection, previous_reflection)
|
1006
1000
|
@reflection = reflection
|
1007
1001
|
@previous_reflection = previous_reflection
|
1008
1002
|
end
|
1009
1003
|
|
1010
|
-
def klass
|
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
|
1004
|
+
def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc:
|
1005
|
+
scopes = @previous_reflection.join_scopes(table, predicate_builder) + super
|
1006
|
+
scopes << build_scope(table, predicate_builder, klass).instance_exec(nil, &source_type_scope)
|
1032
1007
|
end
|
1033
1008
|
|
1034
1009
|
def constraints
|
1035
|
-
@reflection.constraints + [
|
1010
|
+
@reflection.constraints + [source_type_scope]
|
1036
1011
|
end
|
1037
1012
|
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1013
|
+
private
|
1014
|
+
def source_type_scope
|
1015
|
+
type = @previous_reflection.foreign_type
|
1016
|
+
source_type = @previous_reflection.options[:source_type]
|
1017
|
+
lambda { |object| where(type => source_type) }
|
1018
|
+
end
|
1043
1019
|
end
|
1044
1020
|
|
1045
|
-
class RuntimeReflection <
|
1046
|
-
|
1021
|
+
class RuntimeReflection < AbstractReflection # :nodoc:
|
1022
|
+
delegate :scope, :type, :constraints, :get_join_keys, to: :@reflection
|
1047
1023
|
|
1048
1024
|
def initialize(reflection, association)
|
1049
1025
|
@reflection = reflection
|
@@ -1054,24 +1030,8 @@ module ActiveRecord
|
|
1054
1030
|
@association.klass
|
1055
1031
|
end
|
1056
1032
|
|
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)
|
1033
|
+
def aliased_table
|
1034
|
+
@aliased_table ||= Arel::Table.new(table_name, type_caster: klass.type_caster)
|
1075
1035
|
end
|
1076
1036
|
|
1077
1037
|
def all_includes; yield; end
|