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,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,10 +65,12 @@ 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
|
|
72
|
+
attr_reader :aliases
|
73
|
+
|
83
74
|
private
|
84
75
|
|
85
76
|
def truncate(name)
|
@@ -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,29 +17,38 @@ 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!
|
26
44
|
|
27
45
|
@owner, @reflection = owner, reflection
|
46
|
+
@_scope = nil
|
28
47
|
|
29
48
|
reset
|
30
49
|
reset_scope
|
31
50
|
end
|
32
51
|
|
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
52
|
# Resets the \loaded flag to +false+ and sets the \target to +nil+.
|
42
53
|
def reset
|
43
54
|
@loaded = false
|
@@ -47,7 +58,9 @@ module ActiveRecord
|
|
47
58
|
end
|
48
59
|
|
49
60
|
# Reloads the \target and returns +self+ on success.
|
50
|
-
|
61
|
+
# The QueryCache is cleared if +force+ is true.
|
62
|
+
def reload(force = false)
|
63
|
+
klass.connection.clear_query_cache if force && klass
|
51
64
|
reset
|
52
65
|
reset_scope
|
53
66
|
load_target
|
@@ -73,7 +86,7 @@ module ActiveRecord
|
|
73
86
|
#
|
74
87
|
# Note that if the target has not been loaded, it is not considered stale.
|
75
88
|
def stale_target?
|
76
|
-
|
89
|
+
!@inversed && loaded? && @stale_state != stale_state
|
77
90
|
end
|
78
91
|
|
79
92
|
# Sets the target of this association to <tt>\target</tt>, and the \loaded flag to +true+.
|
@@ -83,19 +96,7 @@ module ActiveRecord
|
|
83
96
|
end
|
84
97
|
|
85
98
|
def scope
|
86
|
-
target_scope.merge!(association_scope)
|
87
|
-
end
|
88
|
-
|
89
|
-
# The scope for this association.
|
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
|
-
end
|
99
|
+
@_scope&.spawn || target_scope.merge!(association_scope)
|
99
100
|
end
|
100
101
|
|
101
102
|
def reset_scope
|
@@ -104,31 +105,43 @@ module ActiveRecord
|
|
104
105
|
|
105
106
|
# Set the inverse association, if possible
|
106
107
|
def set_inverse_instance(record)
|
107
|
-
if
|
108
|
-
inverse
|
109
|
-
|
110
|
-
|
108
|
+
if inverse = inverse_association_for(record)
|
109
|
+
inverse.inversed_from(owner)
|
110
|
+
end
|
111
|
+
record
|
112
|
+
end
|
113
|
+
|
114
|
+
def set_inverse_instance_from_queries(record)
|
115
|
+
if inverse = inverse_association_for(record)
|
116
|
+
inverse.inversed_from_queries(owner)
|
111
117
|
end
|
112
118
|
record
|
113
119
|
end
|
114
120
|
|
121
|
+
# Remove the inverse association, if possible
|
122
|
+
def remove_inverse_instance(record)
|
123
|
+
if inverse = inverse_association_for(record)
|
124
|
+
inverse.inversed_from(nil)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def inversed_from(record)
|
129
|
+
self.target = record
|
130
|
+
@inversed = !!record
|
131
|
+
end
|
132
|
+
alias :inversed_from_queries :inversed_from
|
133
|
+
|
115
134
|
# Returns the class of the target. belongs_to polymorphic overrides this to look at the
|
116
135
|
# polymorphic_type field on the owner.
|
117
136
|
def klass
|
118
137
|
reflection.klass
|
119
138
|
end
|
120
139
|
|
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
140
|
def extensions
|
128
141
|
extensions = klass.default_extensions | reflection.extensions
|
129
142
|
|
130
|
-
if
|
131
|
-
extensions |= klass.unscoped
|
143
|
+
if reflection.scope
|
144
|
+
extensions |= reflection.scope_for(klass.unscoped, owner).extensions
|
132
145
|
end
|
133
146
|
|
134
147
|
extensions
|
@@ -153,17 +166,9 @@ module ActiveRecord
|
|
153
166
|
reset
|
154
167
|
end
|
155
168
|
|
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
|
169
|
+
# We can't dump @reflection and @through_reflection since it contains the scope proc
|
165
170
|
def marshal_dump
|
166
|
-
ivars = (instance_variables - [:@reflection]).map { |name| [name, instance_variable_get(name)] }
|
171
|
+
ivars = (instance_variables - [:@reflection, :@through_reflection]).map { |name| [name, instance_variable_get(name)] }
|
167
172
|
[@reflection.name, ivars]
|
168
173
|
end
|
169
174
|
|
@@ -176,14 +181,64 @@ module ActiveRecord
|
|
176
181
|
def initialize_attributes(record, except_from_scope_attributes = nil) #:nodoc:
|
177
182
|
except_from_scope_attributes ||= {}
|
178
183
|
skip_assign = [reflection.foreign_key, reflection.type].compact
|
179
|
-
assigned_keys = record.
|
184
|
+
assigned_keys = record.changed_attribute_names_to_save
|
180
185
|
assigned_keys += except_from_scope_attributes.keys.map(&:to_s)
|
181
|
-
attributes =
|
182
|
-
record.
|
186
|
+
attributes = scope_for_create.except!(*(assigned_keys - skip_assign))
|
187
|
+
record.send(:_assign_attributes, attributes) if attributes.any?
|
183
188
|
set_inverse_instance(record)
|
184
189
|
end
|
185
190
|
|
191
|
+
def create(attributes = {}, &block)
|
192
|
+
_create_record(attributes, &block)
|
193
|
+
end
|
194
|
+
|
195
|
+
def create!(attributes = {}, &block)
|
196
|
+
_create_record(attributes, true, &block)
|
197
|
+
end
|
198
|
+
|
199
|
+
def scoping(relation, &block)
|
200
|
+
@_scope = relation
|
201
|
+
relation.scoping(&block)
|
202
|
+
ensure
|
203
|
+
@_scope = nil
|
204
|
+
end
|
205
|
+
|
186
206
|
private
|
207
|
+
def find_target
|
208
|
+
scope = self.scope
|
209
|
+
return scope.to_a if skip_statement_cache?(scope)
|
210
|
+
|
211
|
+
conn = klass.connection
|
212
|
+
sc = reflection.association_scope_cache(conn, owner) do |params|
|
213
|
+
as = AssociationScope.create { params.bind }
|
214
|
+
target_scope.merge!(as.scope(self))
|
215
|
+
end
|
216
|
+
|
217
|
+
binds = AssociationScope.get_bind_values(owner, reflection.chain)
|
218
|
+
sc.execute(binds, conn) { |record| set_inverse_instance(record) } || []
|
219
|
+
end
|
220
|
+
|
221
|
+
# The scope for this association.
|
222
|
+
#
|
223
|
+
# Note that the association_scope is merged into the target_scope only when the
|
224
|
+
# scope method is called. This is because at that point the call may be surrounded
|
225
|
+
# by scope.scoping { ... } or unscoped { ... } etc, which affects the scope which
|
226
|
+
# actually gets built.
|
227
|
+
def association_scope
|
228
|
+
if klass
|
229
|
+
@association_scope ||= AssociationScope.scope(self)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
# Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the
|
234
|
+
# through association's scope)
|
235
|
+
def target_scope
|
236
|
+
AssociationRelation.create(klass, self).merge!(klass.scope_for_association)
|
237
|
+
end
|
238
|
+
|
239
|
+
def scope_for_create
|
240
|
+
scope.scope_for_create
|
241
|
+
end
|
187
242
|
|
188
243
|
def find_target?
|
189
244
|
!loaded? && (!owner.new_record? || foreign_key_present?) && klass
|
@@ -195,8 +250,8 @@ module ActiveRecord
|
|
195
250
|
if (reflection.has_one? || reflection.collection?) && !options[:through]
|
196
251
|
attributes[reflection.foreign_key] = owner[reflection.active_record_primary_key]
|
197
252
|
|
198
|
-
if reflection.
|
199
|
-
attributes[reflection.type] = owner.class.
|
253
|
+
if reflection.type
|
254
|
+
attributes[reflection.type] = owner.class.polymorphic_name
|
200
255
|
end
|
201
256
|
end
|
202
257
|
|
@@ -227,12 +282,19 @@ module ActiveRecord
|
|
227
282
|
unless record.is_a?(reflection.klass)
|
228
283
|
fresh_class = reflection.class_name.safe_constantize
|
229
284
|
unless fresh_class && record.is_a?(fresh_class)
|
230
|
-
message = "#{reflection.class_name}(##{reflection.klass.object_id}) expected,
|
285
|
+
message = "#{reflection.class_name}(##{reflection.klass.object_id}) expected, "\
|
286
|
+
"got #{record.inspect} which is an instance of #{record.class}(##{record.class.object_id})"
|
231
287
|
raise ActiveRecord::AssociationTypeMismatch, message
|
232
288
|
end
|
233
289
|
end
|
234
290
|
end
|
235
291
|
|
292
|
+
def inverse_association_for(record)
|
293
|
+
if invertible_for?(record)
|
294
|
+
record.association(inverse_reflection_for(record).name)
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
236
298
|
# Can be redefined by subclasses, notably polymorphic belongs_to
|
237
299
|
# The record parameter is necessary to support polymorphic inverses as we must check for
|
238
300
|
# the association in the specific class of the record.
|
@@ -255,18 +317,19 @@ module ActiveRecord
|
|
255
317
|
# so that when stale_state is different from the value stored on the last find_target,
|
256
318
|
# the target is stale.
|
257
319
|
#
|
258
|
-
# This is only relevant to certain associations, which is why it returns nil by default.
|
320
|
+
# This is only relevant to certain associations, which is why it returns +nil+ by default.
|
259
321
|
def stale_state
|
260
322
|
end
|
261
323
|
|
262
324
|
def build_record(attributes)
|
263
325
|
reflection.build_association(attributes) do |record|
|
264
326
|
initialize_attributes(record, attributes)
|
327
|
+
yield(record) if block_given?
|
265
328
|
end
|
266
329
|
end
|
267
330
|
|
268
331
|
# Returns true if statement cache should be skipped on the association reader.
|
269
|
-
def skip_statement_cache?
|
332
|
+
def skip_statement_cache?(scope)
|
270
333
|
reflection.has_scope? ||
|
271
334
|
scope.eager_loading? ||
|
272
335
|
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,130 @@ 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))
|
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
120
|
|
121
|
-
|
122
|
-
|
123
|
-
table = owner_reflection.alias_name
|
124
|
-
scope = last_chain_scope(scope, table, owner_reflection, owner, association_klass)
|
121
|
+
def add_constraints(scope, owner, chain)
|
122
|
+
scope = last_chain_scope(scope, chain.last, owner)
|
125
123
|
|
126
|
-
|
127
|
-
|
128
|
-
break unless reflection
|
129
|
-
table = reflection.alias_name
|
130
|
-
|
131
|
-
unless reflection == chain_tail
|
132
|
-
next_reflection = reflection.next
|
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
|
-
|
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)
|
141
134
|
|
142
|
-
|
143
|
-
|
144
|
-
|
135
|
+
if scope_chain_item == chain_head.scope
|
136
|
+
scope.merge! item.except(:where, :includes, :unscope, :order)
|
137
|
+
end
|
145
138
|
|
146
|
-
|
147
|
-
|
148
|
-
|
139
|
+
reflection.all_includes do
|
140
|
+
scope.includes! item.includes_values
|
141
|
+
end
|
149
142
|
|
150
|
-
|
151
|
-
|
152
|
-
|
143
|
+
scope.unscope!(*item.unscope_values)
|
144
|
+
scope.where_clause += item.where_clause
|
145
|
+
scope.order_values = item.order_values | scope.order_values
|
146
|
+
end
|
153
147
|
end
|
154
148
|
|
155
|
-
|
149
|
+
scope
|
156
150
|
end
|
157
151
|
|
158
|
-
scope
|
159
|
-
|
152
|
+
def apply_scope(scope, table, key, value)
|
153
|
+
if scope.table == table
|
154
|
+
scope.where!(key => value)
|
155
|
+
else
|
156
|
+
scope.where!(table.name => { key => value })
|
157
|
+
end
|
158
|
+
end
|
160
159
|
|
161
|
-
|
162
|
-
|
163
|
-
|
160
|
+
def eval_scope(reflection, scope, owner)
|
161
|
+
relation = reflection.build_scope(reflection.aliased_table)
|
162
|
+
relation.instance_exec(owner, &scope) || relation
|
163
|
+
end
|
164
164
|
end
|
165
165
|
end
|
166
166
|
end
|