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,51 +1,41 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/string/conversions"
|
2
4
|
|
3
5
|
module ActiveRecord
|
4
6
|
module Associations
|
5
7
|
# Keeps track of table aliases for ActiveRecord::Associations::JoinDependency
|
6
8
|
class AliasTracker # :nodoc:
|
7
|
-
|
8
|
-
|
9
|
-
def self.create(connection, initial_table, type_caster)
|
10
|
-
aliases = Hash.new(0)
|
11
|
-
aliases[initial_table] = 1
|
12
|
-
new connection, aliases, type_caster
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.create_with_joins(connection, initial_table, joins, type_caster)
|
9
|
+
def self.create(connection, initial_table, joins)
|
16
10
|
if joins.empty?
|
17
|
-
|
11
|
+
aliases = Hash.new(0)
|
18
12
|
else
|
19
13
|
aliases = Hash.new { |h, k|
|
20
14
|
h[k] = initial_count_for(connection, k, joins)
|
21
15
|
}
|
22
|
-
aliases[initial_table] = 1
|
23
|
-
new connection, aliases, type_caster
|
24
16
|
end
|
17
|
+
aliases[initial_table] = 1
|
18
|
+
new(connection, aliases)
|
25
19
|
end
|
26
20
|
|
27
21
|
def self.initial_count_for(connection, name, table_joins)
|
28
|
-
|
29
|
-
quoted_name = connection.quote_table_name(name).downcase
|
22
|
+
quoted_name = nil
|
30
23
|
|
31
24
|
counts = table_joins.map do |join|
|
32
25
|
if join.is_a?(Arel::Nodes::StringJoin)
|
26
|
+
# quoted_name should be case ignored as some database adapters (Oracle) return quoted name in uppercase
|
27
|
+
quoted_name ||= connection.quote_table_name(name)
|
28
|
+
|
33
29
|
# Table names + table aliases
|
34
|
-
join.left.
|
35
|
-
/
|
30
|
+
join.left.scan(
|
31
|
+
/JOIN(?:\s+\w+)?\s+(?:\S+\s+)?(?:#{quoted_name}|#{name})\sON/i
|
36
32
|
).size
|
37
|
-
elsif join.
|
38
|
-
join.left.
|
33
|
+
elsif join.is_a?(Arel::Nodes::Join)
|
34
|
+
join.left.name == name ? 1 : 0
|
35
|
+
elsif join.is_a?(Hash)
|
36
|
+
join[name]
|
39
37
|
else
|
40
|
-
|
41
|
-
#
|
42
|
-
# activerecord/test/cases/associations/cascaded_eager_loading_test.rb:37
|
43
|
-
# with :posts
|
44
|
-
#
|
45
|
-
# activerecord/test/cases/associations/eager_test.rb:1133
|
46
|
-
# with :comments
|
47
|
-
#
|
48
|
-
0
|
38
|
+
raise ArgumentError, "joins list should be initialized by list of Arel::Nodes::Join"
|
49
39
|
end
|
50
40
|
end
|
51
41
|
|
@@ -53,17 +43,16 @@ module ActiveRecord
|
|
53
43
|
end
|
54
44
|
|
55
45
|
# table_joins is an array of arel joins which might conflict with the aliases we assign here
|
56
|
-
def initialize(connection, aliases
|
46
|
+
def initialize(connection, aliases)
|
57
47
|
@aliases = aliases
|
58
48
|
@connection = connection
|
59
|
-
@type_caster = type_caster
|
60
49
|
end
|
61
50
|
|
62
|
-
def aliased_table_for(table_name, aliased_name)
|
51
|
+
def aliased_table_for(table_name, aliased_name, type_caster)
|
63
52
|
if aliases[table_name].zero?
|
64
53
|
# If it's zero, we can have our table_name
|
65
54
|
aliases[table_name] = 1
|
66
|
-
Arel::Table.new(table_name, type_caster:
|
55
|
+
Arel::Table.new(table_name, type_caster: type_caster)
|
67
56
|
else
|
68
57
|
# Otherwise, we need to use an alias
|
69
58
|
aliased_name = @connection.table_alias_for(aliased_name)
|
@@ -76,12 +65,13 @@ module ActiveRecord
|
|
76
65
|
else
|
77
66
|
aliased_name
|
78
67
|
end
|
79
|
-
Arel::Table.new(table_name, type_caster:
|
68
|
+
Arel::Table.new(table_name, type_caster: type_caster).alias(table_alias)
|
80
69
|
end
|
81
70
|
end
|
82
71
|
|
83
|
-
|
72
|
+
attr_reader :aliases
|
84
73
|
|
74
|
+
private
|
85
75
|
def truncate(name)
|
86
76
|
name.slice(0, @connection.table_alias_length - 2)
|
87
77
|
end
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/array/wrap"
|
2
4
|
|
3
5
|
module ActiveRecord
|
4
6
|
module Associations
|
@@ -15,11 +17,27 @@ module ActiveRecord
|
|
15
17
|
# CollectionAssociation
|
16
18
|
# HasManyAssociation + ForeignAssociation
|
17
19
|
# HasManyThroughAssociation + ThroughAssociation
|
20
|
+
#
|
21
|
+
# Associations in Active Record are middlemen between the object that
|
22
|
+
# holds the association, known as the <tt>owner</tt>, and the associated
|
23
|
+
# result set, known as the <tt>target</tt>. Association metadata is available in
|
24
|
+
# <tt>reflection</tt>, which is an instance of <tt>ActiveRecord::Reflection::AssociationReflection</tt>.
|
25
|
+
#
|
26
|
+
# For example, given
|
27
|
+
#
|
28
|
+
# class Blog < ActiveRecord::Base
|
29
|
+
# has_many :posts
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# blog = Blog.first
|
33
|
+
#
|
34
|
+
# The association of <tt>blog.posts</tt> has the object +blog+ as its
|
35
|
+
# <tt>owner</tt>, the collection of its posts as <tt>target</tt>, and
|
36
|
+
# the <tt>reflection</tt> object represents a <tt>:has_many</tt> macro.
|
18
37
|
class Association #:nodoc:
|
19
38
|
attr_reader :owner, :target, :reflection
|
20
|
-
attr_accessor :inversed
|
21
39
|
|
22
|
-
delegate :options, :
|
40
|
+
delegate :options, to: :reflection
|
23
41
|
|
24
42
|
def initialize(owner, reflection)
|
25
43
|
reflection.check_validity!
|
@@ -30,14 +48,6 @@ module ActiveRecord
|
|
30
48
|
reset_scope
|
31
49
|
end
|
32
50
|
|
33
|
-
# Returns the name of the table of the associated class:
|
34
|
-
#
|
35
|
-
# post.comments.aliased_table_name # => "comments"
|
36
|
-
#
|
37
|
-
def aliased_table_name
|
38
|
-
klass.table_name
|
39
|
-
end
|
40
|
-
|
41
51
|
# Resets the \loaded flag to +false+ and sets the \target to +nil+.
|
42
52
|
def reset
|
43
53
|
@loaded = false
|
@@ -47,7 +57,9 @@ module ActiveRecord
|
|
47
57
|
end
|
48
58
|
|
49
59
|
# Reloads the \target and returns +self+ on success.
|
50
|
-
|
60
|
+
# The QueryCache is cleared if +force+ is true.
|
61
|
+
def reload(force = false)
|
62
|
+
klass.connection.clear_query_cache if force && klass
|
51
63
|
reset
|
52
64
|
reset_scope
|
53
65
|
load_target
|
@@ -73,7 +85,7 @@ module ActiveRecord
|
|
73
85
|
#
|
74
86
|
# Note that if the target has not been loaded, it is not considered stale.
|
75
87
|
def stale_target?
|
76
|
-
|
88
|
+
!@inversed && loaded? && @stale_state != stale_state
|
77
89
|
end
|
78
90
|
|
79
91
|
# Sets the target of this association to <tt>\target</tt>, and the \loaded flag to +true+.
|
@@ -83,18 +95,10 @@ module ActiveRecord
|
|
83
95
|
end
|
84
96
|
|
85
97
|
def scope
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
#
|
91
|
-
# Note that the association_scope is merged into the target_scope only when the
|
92
|
-
# scope method is called. This is because at that point the call may be surrounded
|
93
|
-
# by scope.scoping { ... } or with_scope { ... } etc, which affects the scope which
|
94
|
-
# actually gets built.
|
95
|
-
def association_scope
|
96
|
-
if klass
|
97
|
-
@association_scope ||= AssociationScope.scope(self, klass.connection)
|
98
|
+
if (scope = klass.current_scope) && scope.try(:proxy_association) == self
|
99
|
+
scope.spawn
|
100
|
+
else
|
101
|
+
target_scope.merge!(association_scope)
|
98
102
|
end
|
99
103
|
end
|
100
104
|
|
@@ -104,31 +108,43 @@ module ActiveRecord
|
|
104
108
|
|
105
109
|
# Set the inverse association, if possible
|
106
110
|
def set_inverse_instance(record)
|
107
|
-
if
|
108
|
-
inverse
|
109
|
-
|
110
|
-
|
111
|
+
if inverse = inverse_association_for(record)
|
112
|
+
inverse.inversed_from(owner)
|
113
|
+
end
|
114
|
+
record
|
115
|
+
end
|
116
|
+
|
117
|
+
def set_inverse_instance_from_queries(record)
|
118
|
+
if inverse = inverse_association_for(record)
|
119
|
+
inverse.inversed_from_queries(owner)
|
111
120
|
end
|
112
121
|
record
|
113
122
|
end
|
114
123
|
|
124
|
+
# Remove the inverse association, if possible
|
125
|
+
def remove_inverse_instance(record)
|
126
|
+
if inverse = inverse_association_for(record)
|
127
|
+
inverse.inversed_from(nil)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def inversed_from(record)
|
132
|
+
self.target = record
|
133
|
+
@inversed = !!record
|
134
|
+
end
|
135
|
+
alias :inversed_from_queries :inversed_from
|
136
|
+
|
115
137
|
# Returns the class of the target. belongs_to polymorphic overrides this to look at the
|
116
138
|
# polymorphic_type field on the owner.
|
117
139
|
def klass
|
118
140
|
reflection.klass
|
119
141
|
end
|
120
142
|
|
121
|
-
# Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the
|
122
|
-
# through association's scope)
|
123
|
-
def target_scope
|
124
|
-
AssociationRelation.create(klass, klass.arel_table, klass.predicate_builder, self).merge!(klass.all)
|
125
|
-
end
|
126
|
-
|
127
143
|
def extensions
|
128
144
|
extensions = klass.default_extensions | reflection.extensions
|
129
145
|
|
130
|
-
if
|
131
|
-
extensions |= klass.unscoped
|
146
|
+
if reflection.scope
|
147
|
+
extensions |= reflection.scope_for(klass.unscoped, owner).extensions
|
132
148
|
end
|
133
149
|
|
134
150
|
extensions
|
@@ -153,17 +169,9 @@ module ActiveRecord
|
|
153
169
|
reset
|
154
170
|
end
|
155
171
|
|
156
|
-
|
157
|
-
if sql.respond_to?(:to_proc)
|
158
|
-
owner.instance_exec(record, &sql)
|
159
|
-
else
|
160
|
-
sql
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
# We can't dump @reflection since it contains the scope proc
|
172
|
+
# We can't dump @reflection and @through_reflection since it contains the scope proc
|
165
173
|
def marshal_dump
|
166
|
-
ivars = (instance_variables - [:@reflection]).map { |name| [name, instance_variable_get(name)] }
|
174
|
+
ivars = (instance_variables - [:@reflection, :@through_reflection]).map { |name| [name, instance_variable_get(name)] }
|
167
175
|
[@reflection.name, ivars]
|
168
176
|
end
|
169
177
|
|
@@ -176,14 +184,56 @@ module ActiveRecord
|
|
176
184
|
def initialize_attributes(record, except_from_scope_attributes = nil) #:nodoc:
|
177
185
|
except_from_scope_attributes ||= {}
|
178
186
|
skip_assign = [reflection.foreign_key, reflection.type].compact
|
179
|
-
assigned_keys = record.
|
187
|
+
assigned_keys = record.changed_attribute_names_to_save
|
180
188
|
assigned_keys += except_from_scope_attributes.keys.map(&:to_s)
|
181
|
-
attributes =
|
182
|
-
record.
|
189
|
+
attributes = scope_for_create.except!(*(assigned_keys - skip_assign))
|
190
|
+
record.send(:_assign_attributes, attributes) if attributes.any?
|
183
191
|
set_inverse_instance(record)
|
184
192
|
end
|
185
193
|
|
194
|
+
def create(attributes = {}, &block)
|
195
|
+
_create_record(attributes, &block)
|
196
|
+
end
|
197
|
+
|
198
|
+
def create!(attributes = {}, &block)
|
199
|
+
_create_record(attributes, true, &block)
|
200
|
+
end
|
201
|
+
|
186
202
|
private
|
203
|
+
def find_target
|
204
|
+
scope = self.scope
|
205
|
+
return scope.to_a if skip_statement_cache?(scope)
|
206
|
+
|
207
|
+
sc = reflection.association_scope_cache(klass, owner) do |params|
|
208
|
+
as = AssociationScope.create { params.bind }
|
209
|
+
target_scope.merge!(as.scope(self))
|
210
|
+
end
|
211
|
+
|
212
|
+
binds = AssociationScope.get_bind_values(owner, reflection.chain)
|
213
|
+
sc.execute(binds, klass.connection) { |record| set_inverse_instance(record) } || []
|
214
|
+
end
|
215
|
+
|
216
|
+
# The scope for this association.
|
217
|
+
#
|
218
|
+
# Note that the association_scope is merged into the target_scope only when the
|
219
|
+
# scope method is called. This is because at that point the call may be surrounded
|
220
|
+
# by scope.scoping { ... } or unscoped { ... } etc, which affects the scope which
|
221
|
+
# actually gets built.
|
222
|
+
def association_scope
|
223
|
+
if klass
|
224
|
+
@association_scope ||= AssociationScope.scope(self)
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
# Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the
|
229
|
+
# through association's scope)
|
230
|
+
def target_scope
|
231
|
+
AssociationRelation.create(klass, self).merge!(klass.scope_for_association)
|
232
|
+
end
|
233
|
+
|
234
|
+
def scope_for_create
|
235
|
+
scope.scope_for_create
|
236
|
+
end
|
187
237
|
|
188
238
|
def find_target?
|
189
239
|
!loaded? && (!owner.new_record? || foreign_key_present?) && klass
|
@@ -195,8 +245,8 @@ module ActiveRecord
|
|
195
245
|
if (reflection.has_one? || reflection.collection?) && !options[:through]
|
196
246
|
attributes[reflection.foreign_key] = owner[reflection.active_record_primary_key]
|
197
247
|
|
198
|
-
if reflection.
|
199
|
-
attributes[reflection.type] = owner.class.
|
248
|
+
if reflection.type
|
249
|
+
attributes[reflection.type] = owner.class.polymorphic_name
|
200
250
|
end
|
201
251
|
end
|
202
252
|
|
@@ -227,12 +277,19 @@ module ActiveRecord
|
|
227
277
|
unless record.is_a?(reflection.klass)
|
228
278
|
fresh_class = reflection.class_name.safe_constantize
|
229
279
|
unless fresh_class && record.is_a?(fresh_class)
|
230
|
-
message = "#{reflection.class_name}(##{reflection.klass.object_id}) expected,
|
280
|
+
message = "#{reflection.class_name}(##{reflection.klass.object_id}) expected, "\
|
281
|
+
"got #{record.inspect} which is an instance of #{record.class}(##{record.class.object_id})"
|
231
282
|
raise ActiveRecord::AssociationTypeMismatch, message
|
232
283
|
end
|
233
284
|
end
|
234
285
|
end
|
235
286
|
|
287
|
+
def inverse_association_for(record)
|
288
|
+
if invertible_for?(record)
|
289
|
+
record.association(inverse_reflection_for(record).name)
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
236
293
|
# Can be redefined by subclasses, notably polymorphic belongs_to
|
237
294
|
# The record parameter is necessary to support polymorphic inverses as we must check for
|
238
295
|
# the association in the specific class of the record.
|
@@ -255,18 +312,19 @@ module ActiveRecord
|
|
255
312
|
# so that when stale_state is different from the value stored on the last find_target,
|
256
313
|
# the target is stale.
|
257
314
|
#
|
258
|
-
# This is only relevant to certain associations, which is why it returns nil by default.
|
315
|
+
# This is only relevant to certain associations, which is why it returns +nil+ by default.
|
259
316
|
def stale_state
|
260
317
|
end
|
261
318
|
|
262
319
|
def build_record(attributes)
|
263
320
|
reflection.build_association(attributes) do |record|
|
264
321
|
initialize_attributes(record, attributes)
|
322
|
+
yield(record) if block_given?
|
265
323
|
end
|
266
324
|
end
|
267
325
|
|
268
326
|
# Returns true if statement cache should be skipped on the association reader.
|
269
|
-
def skip_statement_cache?
|
327
|
+
def skip_statement_cache?(scope)
|
270
328
|
reflection.has_scope? ||
|
271
329
|
scope.eager_loading? ||
|
272
330
|
klass.scope_attributes? ||
|
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Associations
|
3
5
|
class AssociationScope #:nodoc:
|
4
|
-
def self.scope(association
|
5
|
-
INSTANCE.scope(association
|
6
|
+
def self.scope(association)
|
7
|
+
INSTANCE.scope(association)
|
6
8
|
end
|
7
9
|
|
8
10
|
def self.create(&block)
|
@@ -16,20 +18,17 @@ module ActiveRecord
|
|
16
18
|
|
17
19
|
INSTANCE = create
|
18
20
|
|
19
|
-
def scope(association
|
21
|
+
def scope(association)
|
20
22
|
klass = association.klass
|
21
23
|
reflection = association.reflection
|
22
24
|
scope = klass.unscoped
|
23
25
|
owner = association.owner
|
24
|
-
|
25
|
-
chain_head, chain_tail = get_chain(reflection, association, alias_tracker)
|
26
|
+
chain = get_chain(reflection, association, scope.alias_tracker)
|
26
27
|
|
27
28
|
scope.extending! reflection.extensions
|
28
|
-
add_constraints(scope, owner,
|
29
|
-
|
30
|
-
|
31
|
-
def join_type
|
32
|
-
Arel::Nodes::InnerJoin
|
29
|
+
scope = add_constraints(scope, owner, chain)
|
30
|
+
scope.limit!(1) unless reflection.collection?
|
31
|
+
scope
|
33
32
|
end
|
34
33
|
|
35
34
|
def self.get_bind_values(owner, chain)
|
@@ -38,129 +37,136 @@ module ActiveRecord
|
|
38
37
|
|
39
38
|
binds << last_reflection.join_id_for(owner)
|
40
39
|
if last_reflection.type
|
41
|
-
binds << owner.class.
|
40
|
+
binds << owner.class.polymorphic_name
|
42
41
|
end
|
43
42
|
|
44
43
|
chain.each_cons(2).each do |reflection, next_reflection|
|
45
44
|
if reflection.type
|
46
|
-
binds << next_reflection.klass.
|
45
|
+
binds << next_reflection.klass.polymorphic_name
|
47
46
|
end
|
48
47
|
end
|
49
48
|
binds
|
50
49
|
end
|
51
50
|
|
52
|
-
|
51
|
+
private
|
52
|
+
attr_reader :value_transformation
|
53
53
|
|
54
|
-
|
54
|
+
def join(table, constraint)
|
55
|
+
table.create_join(table, table.create_on(constraint), Arel::Nodes::LeadingJoin)
|
56
|
+
end
|
55
57
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
58
|
+
def last_chain_scope(scope, reflection, owner)
|
59
|
+
join_keys = reflection.join_keys
|
60
|
+
key = join_keys.key
|
61
|
+
foreign_key = join_keys.foreign_key
|
60
62
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
foreign_key = join_keys.foreign_key
|
63
|
+
table = reflection.aliased_table
|
64
|
+
value = transform_value(owner[foreign_key])
|
65
|
+
scope = apply_scope(scope, table, key, value)
|
65
66
|
|
66
|
-
|
67
|
-
|
67
|
+
if reflection.type
|
68
|
+
polymorphic_type = transform_value(owner.class.polymorphic_name)
|
69
|
+
scope = apply_scope(scope, table, reflection.type, polymorphic_type)
|
70
|
+
end
|
68
71
|
|
69
|
-
|
70
|
-
polymorphic_type = transform_value(owner.class.base_class.name)
|
71
|
-
scope = scope.where(table.name => { reflection.type => polymorphic_type })
|
72
|
+
scope
|
72
73
|
end
|
73
74
|
|
74
|
-
|
75
|
-
|
75
|
+
def transform_value(value)
|
76
|
+
value_transformation.call(value)
|
77
|
+
end
|
76
78
|
|
77
|
-
|
78
|
-
|
79
|
-
|
79
|
+
def next_chain_scope(scope, reflection, next_reflection)
|
80
|
+
join_keys = reflection.join_keys
|
81
|
+
key = join_keys.key
|
82
|
+
foreign_key = join_keys.foreign_key
|
80
83
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
foreign_key = join_keys.foreign_key
|
84
|
+
table = reflection.aliased_table
|
85
|
+
foreign_table = next_reflection.aliased_table
|
86
|
+
constraint = table[key].eq(foreign_table[foreign_key])
|
85
87
|
|
86
|
-
|
88
|
+
if reflection.type
|
89
|
+
value = transform_value(next_reflection.klass.polymorphic_name)
|
90
|
+
scope = apply_scope(scope, table, reflection.type, value)
|
91
|
+
end
|
87
92
|
|
88
|
-
|
89
|
-
value = transform_value(next_reflection.klass.base_class.name)
|
90
|
-
scope = scope.where(table.name => { reflection.type => value })
|
93
|
+
scope.joins!(join(foreign_table, constraint))
|
91
94
|
end
|
92
95
|
|
93
|
-
|
94
|
-
|
96
|
+
class ReflectionProxy < SimpleDelegator # :nodoc:
|
97
|
+
attr_reader :aliased_table
|
95
98
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
+
def initialize(reflection, aliased_table)
|
100
|
+
super(reflection)
|
101
|
+
@aliased_table = aliased_table
|
102
|
+
end
|
99
103
|
|
100
|
-
|
101
|
-
super(reflection)
|
102
|
-
@alias_name = alias_name
|
104
|
+
def all_includes; nil; end
|
103
105
|
end
|
104
106
|
|
105
|
-
def
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
107
|
+
def get_chain(reflection, association, tracker)
|
108
|
+
name = reflection.name
|
109
|
+
chain = [Reflection::RuntimeReflection.new(reflection, association)]
|
110
|
+
reflection.chain.drop(1).each do |refl|
|
111
|
+
aliased_table = tracker.aliased_table_for(
|
112
|
+
refl.table_name,
|
113
|
+
refl.alias_candidate(name),
|
114
|
+
refl.klass.type_caster
|
115
|
+
)
|
116
|
+
chain << ReflectionProxy.new(refl, aliased_table)
|
117
|
+
end
|
118
|
+
chain
|
117
119
|
end
|
118
|
-
[runtime_reflection, previous_reflection]
|
119
|
-
end
|
120
|
-
|
121
|
-
def add_constraints(scope, owner, association_klass, refl, chain_head, chain_tail)
|
122
|
-
owner_reflection = chain_tail
|
123
|
-
table = owner_reflection.alias_name
|
124
|
-
scope = last_chain_scope(scope, table, owner_reflection, owner, association_klass)
|
125
120
|
|
126
|
-
|
127
|
-
|
128
|
-
break unless reflection
|
129
|
-
table = reflection.alias_name
|
121
|
+
def add_constraints(scope, owner, chain)
|
122
|
+
scope = last_chain_scope(scope, chain.last, owner)
|
130
123
|
|
131
|
-
|
132
|
-
|
133
|
-
foreign_table = next_reflection.alias_name
|
134
|
-
scope = next_chain_scope(scope, table, reflection, association_klass, foreign_table, next_reflection)
|
124
|
+
chain.each_cons(2) do |reflection, next_reflection|
|
125
|
+
scope = next_chain_scope(scope, reflection, next_reflection)
|
135
126
|
end
|
136
127
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
128
|
+
chain_head = chain.first
|
129
|
+
chain.reverse_each do |reflection|
|
130
|
+
# Exclude the scope of the association itself, because that
|
131
|
+
# was already merged in the #scope method.
|
132
|
+
reflection.constraints.each do |scope_chain_item|
|
133
|
+
item = eval_scope(reflection, scope_chain_item, owner)
|
134
|
+
|
135
|
+
if scope_chain_item == chain_head.scope
|
136
|
+
scope.merge! item.except(:where, :includes, :unscope, :order)
|
137
|
+
elsif !item.references_values.empty?
|
138
|
+
join_dependency = item.construct_join_dependency(
|
139
|
+
item.eager_load_values | item.includes_values, Arel::Nodes::OuterJoin
|
140
|
+
)
|
141
|
+
scope.joins!(*item.joins_values, join_dependency)
|
142
|
+
scope.left_outer_joins!(*item.left_outer_joins_values)
|
143
|
+
end
|
144
|
+
|
145
|
+
reflection.all_includes do
|
146
|
+
scope.includes! item.includes_values
|
147
|
+
end
|
148
|
+
|
149
|
+
scope.unscope!(*item.unscope_values)
|
150
|
+
scope.where_clause += item.where_clause
|
151
|
+
scope.order_values = item.order_values | scope.order_values
|
148
152
|
end
|
149
|
-
|
150
|
-
scope.unscope!(*item.unscope_values)
|
151
|
-
scope.where_clause += item.where_clause
|
152
|
-
scope.order_values |= item.order_values
|
153
153
|
end
|
154
154
|
|
155
|
-
|
155
|
+
scope
|
156
156
|
end
|
157
157
|
|
158
|
-
scope
|
159
|
-
|
158
|
+
def apply_scope(scope, table, key, value)
|
159
|
+
if scope.table == table
|
160
|
+
scope.where!(key => value)
|
161
|
+
else
|
162
|
+
scope.where!(table.name => { key => value })
|
163
|
+
end
|
164
|
+
end
|
160
165
|
|
161
|
-
|
162
|
-
|
163
|
-
|
166
|
+
def eval_scope(reflection, scope, owner)
|
167
|
+
relation = reflection.build_scope(reflection.aliased_table)
|
168
|
+
relation.instance_exec(owner, &scope) || relation
|
169
|
+
end
|
164
170
|
end
|
165
171
|
end
|
166
172
|
end
|