activerecord 5.0.7.2 → 6.0.3.4
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 +708 -2040
- 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.rb +37 -22
- 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.rb +1603 -1592
- data/lib/active_record/associations/alias_tracker.rb +24 -34
- data/lib/active_record/associations/association.rb +114 -55
- 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 +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 +86 -254
- data/lib/active_record/associations/collection_proxy.rb +158 -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.rb +143 -176
- data/lib/active_record/associations/join_dependency/join_association.rb +38 -87
- 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/preloader.rb +90 -103
- data/lib/active_record/associations/preloader/association.rb +86 -100
- data/lib/active_record/associations/preloader/through_association.rb +77 -76
- data/lib/active_record/associations/singular_association.rb +12 -45
- data/lib/active_record/associations/through_association.rb +26 -14
- data/lib/active_record/attribute_assignment.rb +54 -61
- data/lib/active_record/attribute_decorators.rb +38 -17
- data/lib/active_record/attribute_methods.rb +66 -106
- 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/attributes.rb +38 -25
- data/lib/active_record/autosave_association.rb +54 -35
- 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 +11 -12
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +552 -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 +119 -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 +228 -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 +367 -202
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +396 -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 +264 -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.rb +24 -21
- 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 +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 -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 +34 -31
- 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/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 +259 -266
- 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 +201 -163
- data/lib/active_record/counter_cache.rb +60 -28
- data/lib/active_record/database_configurations.rb +233 -0
- 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/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +87 -87
- data/lib/active_record/enum.rb +60 -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 +77 -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.rb +74 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +87 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/migration.rb +369 -302
- 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/model_schema.rb +131 -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 -252
- data/lib/active_record/relation.rb +440 -318
- data/lib/active_record/relation/batches.rb +98 -52
- data/lib/active_record/relation/batches/batch_enumerator.rb +3 -1
- data/lib/active_record/relation/calculations.rb +212 -173
- data/lib/active_record/relation/delegation.rb +72 -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 +78 -62
- data/lib/active_record/relation/predicate_builder.rb +83 -105
- 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/query_attribute.rb +33 -2
- data/lib/active_record/relation/query_methods.rb +476 -334
- 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/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.rb +20 -20
- data/lib/active_record/scoping/default.rb +92 -95
- data/lib/active_record/scoping/named.rb +47 -27
- 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 +225 -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.rb +23 -18
- 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 +2 -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_caster.rb +4 -2
- data/lib/active_record/type_caster/connection.rb +17 -12
- data/lib/active_record/type_caster/map.rb +5 -4
- data/lib/active_record/validations.rb +7 -5
- data/lib/active_record/validations/absence.rb +2 -0
- data/lib/active_record/validations/associated.rb +4 -3
- 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/version.rb +3 -1
- data/lib/arel.rb +62 -0
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/attributes/attribute.rb +37 -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.rb +68 -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/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.rb +20 -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/window_predications.rb +9 -0
- data/lib/rails/generators/active_record.rb +7 -5
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -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.rb +17 -3
- 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/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/model/templates/{module.rb → module.rb.tt} +0 -0
- metadata +137 -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.rb +0 -213
- data/lib/active_record/attribute/user_provided_default.rb +0 -28
- data/lib/active_record/attribute_mutation_tracker.rb +0 -70
- data/lib/active_record/attribute_set.rb +0 -110
- data/lib/active_record/attribute_set/builder.rb +0 -132
- 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,22 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ReadonlyAttributes
|
3
5
|
extend ActiveSupport::Concern
|
4
6
|
|
5
7
|
included do
|
6
|
-
class_attribute :_attr_readonly, instance_accessor: false
|
7
|
-
self._attr_readonly = []
|
8
|
+
class_attribute :_attr_readonly, instance_accessor: false, default: []
|
8
9
|
end
|
9
10
|
|
10
11
|
module ClassMethods
|
11
12
|
# Attributes listed as readonly will be used to create a new record but update operations will
|
12
13
|
# ignore these fields.
|
13
14
|
def attr_readonly(*attributes)
|
14
|
-
self._attr_readonly = Set.new(attributes.map(&:to_s)) + (
|
15
|
+
self._attr_readonly = Set.new(attributes.map(&:to_s)) + (_attr_readonly || [])
|
15
16
|
end
|
16
17
|
|
17
18
|
# Returns an array of all the attributes that have been specified as readonly.
|
18
19
|
def readonly_attributes
|
19
|
-
|
20
|
+
_attr_readonly
|
20
21
|
end
|
21
22
|
end
|
22
23
|
end
|
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/string/filters"
|
4
|
+
require "concurrent/map"
|
3
5
|
|
4
6
|
module ActiveRecord
|
5
7
|
# = Active Record Reflection
|
@@ -7,37 +9,41 @@ module ActiveRecord
|
|
7
9
|
extend ActiveSupport::Concern
|
8
10
|
|
9
11
|
included do
|
10
|
-
class_attribute :_reflections, instance_writer: false
|
11
|
-
class_attribute :aggregate_reflections, instance_writer: false
|
12
|
-
self._reflections = {}
|
13
|
-
self.aggregate_reflections = {}
|
12
|
+
class_attribute :_reflections, instance_writer: false, default: {}
|
13
|
+
class_attribute :aggregate_reflections, instance_writer: false, default: {}
|
14
14
|
end
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
HasManyReflection
|
22
|
-
when :has_one
|
23
|
-
HasOneReflection
|
24
|
-
when :belongs_to
|
25
|
-
BelongsToReflection
|
26
|
-
else
|
27
|
-
raise "Unsupported Macro: #{macro}"
|
28
|
-
end
|
29
|
-
|
30
|
-
reflection = klass.new(name, scope, options, ar)
|
31
|
-
options[:through] ? ThroughReflection.new(reflection) : reflection
|
32
|
-
end
|
16
|
+
class << self
|
17
|
+
def create(macro, name, scope, options, ar)
|
18
|
+
reflection = reflection_class_for(macro).new(name, scope, options, ar)
|
19
|
+
options[:through] ? ThroughReflection.new(reflection) : reflection
|
20
|
+
end
|
33
21
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
22
|
+
def add_reflection(ar, name, reflection)
|
23
|
+
ar.clear_reflections_cache
|
24
|
+
name = -name.to_s
|
25
|
+
ar._reflections = ar._reflections.except(name).merge!(name => reflection)
|
26
|
+
end
|
38
27
|
|
39
|
-
|
40
|
-
|
28
|
+
def add_aggregate_reflection(ar, name, reflection)
|
29
|
+
ar.aggregate_reflections = ar.aggregate_reflections.merge(-name.to_s => reflection)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
def reflection_class_for(macro)
|
34
|
+
case macro
|
35
|
+
when :composed_of
|
36
|
+
AggregateReflection
|
37
|
+
when :has_many
|
38
|
+
HasManyReflection
|
39
|
+
when :has_one
|
40
|
+
HasOneReflection
|
41
|
+
when :belongs_to
|
42
|
+
BelongsToReflection
|
43
|
+
else
|
44
|
+
raise "Unsupported Macro: #{macro}"
|
45
|
+
end
|
46
|
+
end
|
41
47
|
end
|
42
48
|
|
43
49
|
# \Reflection enables the ability to examine the associations and aggregations of
|
@@ -135,8 +141,8 @@ module ActiveRecord
|
|
135
141
|
# BelongsToReflection
|
136
142
|
# HasAndBelongsToManyReflection
|
137
143
|
# ThroughReflection
|
138
|
-
#
|
139
|
-
#
|
144
|
+
# PolymorphicReflection
|
145
|
+
# RuntimeReflection
|
140
146
|
class AbstractReflection # :nodoc:
|
141
147
|
def through_reflection?
|
142
148
|
false
|
@@ -152,14 +158,6 @@ module ActiveRecord
|
|
152
158
|
klass.new(attributes, &block)
|
153
159
|
end
|
154
160
|
|
155
|
-
def quoted_table_name
|
156
|
-
klass.quoted_table_name
|
157
|
-
end
|
158
|
-
|
159
|
-
def primary_key_type
|
160
|
-
klass.type_for_attribute(klass.primary_key)
|
161
|
-
end
|
162
|
-
|
163
161
|
# Returns the class name for the macro.
|
164
162
|
#
|
165
163
|
# <tt>composed_of :balance, class_name: 'Money'</tt> returns <tt>'Money'</tt>
|
@@ -170,12 +168,54 @@ module ActiveRecord
|
|
170
168
|
|
171
169
|
JoinKeys = Struct.new(:key, :foreign_key) # :nodoc:
|
172
170
|
|
173
|
-
def join_keys
|
174
|
-
|
171
|
+
def join_keys
|
172
|
+
@join_keys ||= get_join_keys(klass)
|
173
|
+
end
|
174
|
+
|
175
|
+
# Returns a list of scopes that should be applied for this Reflection
|
176
|
+
# object when querying the database.
|
177
|
+
def scopes
|
178
|
+
scope ? [scope] : []
|
179
|
+
end
|
180
|
+
|
181
|
+
def join_scope(table, foreign_table, foreign_klass)
|
182
|
+
predicate_builder = predicate_builder(table)
|
183
|
+
scope_chain_items = join_scopes(table, predicate_builder)
|
184
|
+
klass_scope = klass_join_scope(table, predicate_builder)
|
185
|
+
|
186
|
+
if type
|
187
|
+
klass_scope.where!(type => foreign_klass.polymorphic_name)
|
188
|
+
end
|
189
|
+
|
190
|
+
scope_chain_items.inject(klass_scope, &:merge!)
|
191
|
+
|
192
|
+
key = join_keys.key
|
193
|
+
foreign_key = join_keys.foreign_key
|
194
|
+
|
195
|
+
klass_scope.where!(table[key].eq(foreign_table[foreign_key]))
|
196
|
+
|
197
|
+
if klass.finder_needs_type_condition?
|
198
|
+
klass_scope.where!(klass.send(:type_condition, table))
|
199
|
+
end
|
200
|
+
|
201
|
+
klass_scope
|
202
|
+
end
|
203
|
+
|
204
|
+
def join_scopes(table, predicate_builder) # :nodoc:
|
205
|
+
if scope
|
206
|
+
[scope_for(build_scope(table, predicate_builder))]
|
207
|
+
else
|
208
|
+
[]
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def klass_join_scope(table, predicate_builder) # :nodoc:
|
213
|
+
relation = build_scope(table, predicate_builder)
|
214
|
+
klass.scope_for_association(relation)
|
175
215
|
end
|
176
216
|
|
177
217
|
def constraints
|
178
|
-
|
218
|
+
chain.flat_map(&:scopes)
|
179
219
|
end
|
180
220
|
|
181
221
|
def counter_cache_column
|
@@ -247,6 +287,40 @@ module ActiveRecord
|
|
247
287
|
def chain
|
248
288
|
collect_join_chain
|
249
289
|
end
|
290
|
+
|
291
|
+
def get_join_keys(association_klass)
|
292
|
+
JoinKeys.new(join_primary_key(association_klass), join_foreign_key)
|
293
|
+
end
|
294
|
+
|
295
|
+
def build_scope(table, predicate_builder = predicate_builder(table))
|
296
|
+
Relation.create(
|
297
|
+
klass,
|
298
|
+
table: table,
|
299
|
+
predicate_builder: predicate_builder
|
300
|
+
)
|
301
|
+
end
|
302
|
+
|
303
|
+
def join_primary_key(*)
|
304
|
+
foreign_key
|
305
|
+
end
|
306
|
+
|
307
|
+
def join_foreign_key
|
308
|
+
active_record_primary_key
|
309
|
+
end
|
310
|
+
|
311
|
+
protected
|
312
|
+
def actual_source_reflection # FIXME: this is a horrible name
|
313
|
+
self
|
314
|
+
end
|
315
|
+
|
316
|
+
private
|
317
|
+
def predicate_builder(table)
|
318
|
+
PredicateBuilder.new(TableMetadata.new(klass, table))
|
319
|
+
end
|
320
|
+
|
321
|
+
def primary_key(klass)
|
322
|
+
klass.primary_key || raise(UnknownPrimaryKey.new(klass))
|
323
|
+
end
|
250
324
|
end
|
251
325
|
|
252
326
|
# Base class for AggregateReflection and AssociationReflection. Objects of
|
@@ -281,7 +355,6 @@ module ActiveRecord
|
|
281
355
|
end
|
282
356
|
|
283
357
|
def autosave=(autosave)
|
284
|
-
@automatic_inverse_of = false
|
285
358
|
@options[:autosave] = autosave
|
286
359
|
parent_reflection = self.parent_reflection
|
287
360
|
if parent_reflection
|
@@ -293,6 +366,17 @@ module ActiveRecord
|
|
293
366
|
#
|
294
367
|
# <tt>composed_of :balance, class_name: 'Money'</tt> returns the Money class
|
295
368
|
# <tt>has_many :clients</tt> returns the Client class
|
369
|
+
#
|
370
|
+
# class Company < ActiveRecord::Base
|
371
|
+
# has_many :clients
|
372
|
+
# end
|
373
|
+
#
|
374
|
+
# Company.reflect_on_association(:clients).klass
|
375
|
+
# # => Client
|
376
|
+
#
|
377
|
+
# <b>Note:</b> Do not call +klass.new+ or +klass.create+ to instantiate
|
378
|
+
# a new association object. Use +build_association+ or +create_association+
|
379
|
+
# instead. This allows plugins to hook into association object creation.
|
296
380
|
def klass
|
297
381
|
@klass ||= compute_class(class_name)
|
298
382
|
end
|
@@ -311,8 +395,8 @@ module ActiveRecord
|
|
311
395
|
active_record == other_aggregation.active_record
|
312
396
|
end
|
313
397
|
|
314
|
-
def scope_for(
|
315
|
-
|
398
|
+
def scope_for(relation, owner = nil)
|
399
|
+
relation.instance_exec(owner, &scope) || relation
|
316
400
|
end
|
317
401
|
|
318
402
|
private
|
@@ -321,8 +405,7 @@ module ActiveRecord
|
|
321
405
|
end
|
322
406
|
end
|
323
407
|
|
324
|
-
|
325
|
-
# Holds all the meta-data about an aggregation as it was specified in the
|
408
|
+
# Holds all the metadata about an aggregation as it was specified in the
|
326
409
|
# Active Record class.
|
327
410
|
class AggregateReflection < MacroReflection #:nodoc:
|
328
411
|
def mapping
|
@@ -331,26 +414,13 @@ module ActiveRecord
|
|
331
414
|
end
|
332
415
|
end
|
333
416
|
|
334
|
-
# Holds all the
|
417
|
+
# Holds all the metadata about an association as it was specified in the
|
335
418
|
# Active Record class.
|
336
419
|
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
420
|
def compute_class(name)
|
421
|
+
if polymorphic?
|
422
|
+
raise ArgumentError, "Polymorphic associations do not support computing the class."
|
423
|
+
end
|
354
424
|
active_record.send(:compute_type, name)
|
355
425
|
end
|
356
426
|
|
@@ -359,22 +429,22 @@ module ActiveRecord
|
|
359
429
|
|
360
430
|
def initialize(name, scope, options, active_record)
|
361
431
|
super
|
362
|
-
@automatic_inverse_of = nil
|
363
432
|
@type = options[:as] && (options[:foreign_type] || "#{options[:as]}_type")
|
364
|
-
@foreign_type = options[:foreign_type] || "#{name}_type"
|
433
|
+
@foreign_type = options[:polymorphic] && (options[:foreign_type] || "#{name}_type")
|
365
434
|
@constructable = calculate_constructable(macro, options)
|
366
|
-
@association_scope_cache =
|
367
|
-
|
435
|
+
@association_scope_cache = Concurrent::Map.new
|
436
|
+
|
437
|
+
if options[:class_name] && options[:class_name].class == Class
|
438
|
+
raise ArgumentError, "A class was passed to `:class_name` but we are expecting a string."
|
439
|
+
end
|
368
440
|
end
|
369
441
|
|
370
|
-
def association_scope_cache(conn, owner)
|
442
|
+
def association_scope_cache(conn, owner, &block)
|
371
443
|
key = conn.prepared_statements
|
372
444
|
if polymorphic?
|
373
445
|
key = [key, owner._read_attribute(@foreign_type)]
|
374
446
|
end
|
375
|
-
@association_scope_cache
|
376
|
-
@association_scope_cache[key] ||= yield
|
377
|
-
}
|
447
|
+
@association_scope_cache.compute_if_absent(key) { StatementCache.create(conn, &block) }
|
378
448
|
end
|
379
449
|
|
380
450
|
def constructable? # :nodoc:
|
@@ -398,10 +468,6 @@ module ActiveRecord
|
|
398
468
|
options[:primary_key] || primary_key(klass || self.klass)
|
399
469
|
end
|
400
470
|
|
401
|
-
def association_primary_key_type
|
402
|
-
klass.type_for_attribute(association_primary_key.to_s)
|
403
|
-
end
|
404
|
-
|
405
471
|
def active_record_primary_key
|
406
472
|
@active_record_primary_key ||= options[:primary_key] || primary_key(active_record)
|
407
473
|
end
|
@@ -413,7 +479,7 @@ module ActiveRecord
|
|
413
479
|
def check_preloadable!
|
414
480
|
return unless scope
|
415
481
|
|
416
|
-
|
482
|
+
unless scope.arity == 0
|
417
483
|
raise ArgumentError, <<-MSG.squish
|
418
484
|
The association scope '#{name}' is instance dependent (the scope
|
419
485
|
block takes an argument). Preloading instance dependent scopes is
|
@@ -424,7 +490,7 @@ module ActiveRecord
|
|
424
490
|
alias :check_eager_loadable! :check_preloadable!
|
425
491
|
|
426
492
|
def join_id_for(owner) # :nodoc:
|
427
|
-
owner[
|
493
|
+
owner[join_foreign_key]
|
428
494
|
end
|
429
495
|
|
430
496
|
def through_reflection
|
@@ -451,12 +517,6 @@ module ActiveRecord
|
|
451
517
|
false
|
452
518
|
end
|
453
519
|
|
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
520
|
def has_scope?
|
461
521
|
scope
|
462
522
|
end
|
@@ -513,7 +573,7 @@ module ActiveRecord
|
|
513
573
|
end
|
514
574
|
|
515
575
|
VALID_AUTOMATIC_INVERSE_MACROS = [:has_many, :has_one, :belongs_to]
|
516
|
-
INVALID_AUTOMATIC_INVERSE_OPTIONS = [:
|
576
|
+
INVALID_AUTOMATIC_INVERSE_OPTIONS = [:through, :foreign_key]
|
517
577
|
|
518
578
|
def add_as_source(seed)
|
519
579
|
seed
|
@@ -531,32 +591,23 @@ module ActiveRecord
|
|
531
591
|
Array(options[:extend])
|
532
592
|
end
|
533
593
|
|
534
|
-
protected
|
535
|
-
|
536
|
-
def actual_source_reflection # FIXME: this is a horrible name
|
537
|
-
self
|
538
|
-
end
|
539
|
-
|
540
594
|
private
|
541
|
-
|
542
595
|
def calculate_constructable(macro, options)
|
543
596
|
true
|
544
597
|
end
|
545
598
|
|
546
599
|
# Attempts to find the inverse association name automatically.
|
547
600
|
# If it cannot find a suitable inverse association name, it returns
|
548
|
-
# nil
|
601
|
+
# +nil+.
|
549
602
|
def inverse_name
|
550
|
-
|
551
|
-
|
552
|
-
nil
|
553
|
-
else
|
554
|
-
@automatic_inverse_of ||= automatic_inverse_of
|
555
|
-
end
|
603
|
+
unless defined?(@inverse_name)
|
604
|
+
@inverse_name = options.fetch(:inverse_of) { automatic_inverse_of }
|
556
605
|
end
|
606
|
+
|
607
|
+
@inverse_name
|
557
608
|
end
|
558
609
|
|
559
|
-
# returns either
|
610
|
+
# returns either +nil+ or the inverse association name that it finds.
|
560
611
|
def automatic_inverse_of
|
561
612
|
if can_find_inverse_of_automatically?(self)
|
562
613
|
inverse_name = ActiveSupport::Inflector.underscore(options[:as] || active_record.name.demodulize).to_sym
|
@@ -570,23 +621,18 @@ module ActiveRecord
|
|
570
621
|
end
|
571
622
|
|
572
623
|
if valid_inverse_reflection?(reflection)
|
573
|
-
|
624
|
+
inverse_name
|
574
625
|
end
|
575
626
|
end
|
576
|
-
|
577
|
-
false
|
578
627
|
end
|
579
628
|
|
580
629
|
# Checks if the inverse reflection that is returned from the
|
581
630
|
# +automatic_inverse_of+ method is a valid reflection. We must
|
582
631
|
# make sure that the reflection's active_record name matches up
|
583
632
|
# 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
633
|
def valid_inverse_reflection?(reflection)
|
588
634
|
reflection &&
|
589
|
-
klass
|
635
|
+
klass <= reflection.active_record &&
|
590
636
|
can_find_inverse_of_automatically?(reflection)
|
591
637
|
end
|
592
638
|
|
@@ -594,9 +640,8 @@ module ActiveRecord
|
|
594
640
|
# us from being able to guess the inverse automatically. First, the
|
595
641
|
# <tt>inverse_of</tt> option cannot be set to false. Second, we must
|
596
642
|
# 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.
|
643
|
+
# Third, we must not have options such as <tt>:foreign_key</tt>
|
644
|
+
# which prevent us from correctly guessing the inverse association.
|
600
645
|
#
|
601
646
|
# Anything with a scope can additionally ruin our attempt at finding an
|
602
647
|
# inverse, so we exclude reflections with scopes.
|
@@ -626,10 +671,6 @@ module ActiveRecord
|
|
626
671
|
def derive_join_table
|
627
672
|
ModelSchema.derive_join_table_name active_record.table_name, klass.table_name
|
628
673
|
end
|
629
|
-
|
630
|
-
def primary_key(klass)
|
631
|
-
klass.primary_key || raise(UnknownPrimaryKey.new(klass))
|
632
|
-
end
|
633
674
|
end
|
634
675
|
|
635
676
|
class HasManyReflection < AssociationReflection # :nodoc:
|
@@ -664,7 +705,6 @@ module ActiveRecord
|
|
664
705
|
end
|
665
706
|
|
666
707
|
private
|
667
|
-
|
668
708
|
def calculate_constructable(macro, options)
|
669
709
|
!options[:through]
|
670
710
|
end
|
@@ -683,16 +723,18 @@ module ActiveRecord
|
|
683
723
|
end
|
684
724
|
end
|
685
725
|
|
686
|
-
def
|
687
|
-
|
688
|
-
JoinKeys.new(key, foreign_key)
|
726
|
+
def join_primary_key(klass = nil)
|
727
|
+
polymorphic? ? association_primary_key(klass) : association_primary_key
|
689
728
|
end
|
690
729
|
|
691
|
-
def
|
692
|
-
|
730
|
+
def join_foreign_key
|
731
|
+
foreign_key
|
693
732
|
end
|
694
733
|
|
695
734
|
private
|
735
|
+
def can_find_inverse_of_automatically?(_)
|
736
|
+
!polymorphic? && super
|
737
|
+
end
|
696
738
|
|
697
739
|
def calculate_constructable(macro, options)
|
698
740
|
!polymorphic?
|
@@ -700,10 +742,6 @@ module ActiveRecord
|
|
700
742
|
end
|
701
743
|
|
702
744
|
class HasAndBelongsToManyReflection < AssociationReflection # :nodoc:
|
703
|
-
def initialize(name, scope, options, active_record)
|
704
|
-
super
|
705
|
-
end
|
706
|
-
|
707
745
|
def macro; :has_and_belongs_to_many; end
|
708
746
|
|
709
747
|
def collection?
|
@@ -711,16 +749,15 @@ module ActiveRecord
|
|
711
749
|
end
|
712
750
|
end
|
713
751
|
|
714
|
-
# Holds all the
|
752
|
+
# Holds all the metadata about a :through association as it was specified
|
715
753
|
# in the Active Record class.
|
716
754
|
class ThroughReflection < AbstractReflection #:nodoc:
|
717
|
-
|
718
|
-
|
719
|
-
:active_record_primary_key, :type, :to => :source_reflection
|
755
|
+
delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for,
|
756
|
+
:active_record_primary_key, :type, :get_join_keys, to: :source_reflection
|
720
757
|
|
721
758
|
def initialize(delegate_reflection)
|
722
759
|
@delegate_reflection = delegate_reflection
|
723
|
-
@klass
|
760
|
+
@klass = delegate_reflection.options[:anonymous_class]
|
724
761
|
@source_reflection_name = delegate_reflection.options[:source]
|
725
762
|
end
|
726
763
|
|
@@ -798,45 +835,12 @@ module ActiveRecord
|
|
798
835
|
through_reflection.clear_association_scope_cache
|
799
836
|
end
|
800
837
|
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
# has_many :articles
|
805
|
-
# has_many :comment_tags, through: :articles
|
806
|
-
# end
|
807
|
-
#
|
808
|
-
# class Article
|
809
|
-
# has_many :comments
|
810
|
-
# has_many :comment_tags, through: :comments, source: :tags
|
811
|
-
# end
|
812
|
-
#
|
813
|
-
# class Comment
|
814
|
-
# has_many :tags
|
815
|
-
# end
|
816
|
-
#
|
817
|
-
# There may be scopes on Person.comment_tags, Article.comment_tags and/or Comment.tags,
|
818
|
-
# but only Comment.tags will be represented in the #chain. So this method creates an array
|
819
|
-
# of scopes corresponding to the chain.
|
820
|
-
def scope_chain
|
821
|
-
@scope_chain ||= begin
|
822
|
-
scope_chain = source_reflection.scope_chain.map(&:dup)
|
823
|
-
|
824
|
-
# Add to it the scope from this reflection (if any)
|
825
|
-
scope_chain.first << scope if scope
|
826
|
-
|
827
|
-
through_scope_chain = through_reflection.scope_chain.map(&:dup)
|
828
|
-
|
829
|
-
if options[:source_type]
|
830
|
-
type = foreign_type
|
831
|
-
source_type = options[:source_type]
|
832
|
-
through_scope_chain.first << lambda { |object|
|
833
|
-
where(type => source_type)
|
834
|
-
}
|
835
|
-
end
|
838
|
+
def scopes
|
839
|
+
source_reflection.scopes + super
|
840
|
+
end
|
836
841
|
|
837
|
-
|
838
|
-
|
839
|
-
end
|
842
|
+
def join_scopes(table, predicate_builder) # :nodoc:
|
843
|
+
source_reflection.join_scopes(table, predicate_builder) + super
|
840
844
|
end
|
841
845
|
|
842
846
|
def has_scope?
|
@@ -845,10 +849,6 @@ module ActiveRecord
|
|
845
849
|
through_reflection.has_scope?
|
846
850
|
end
|
847
851
|
|
848
|
-
def join_keys(association_klass)
|
849
|
-
source_reflection.join_keys(association_klass)
|
850
|
-
end
|
851
|
-
|
852
852
|
# A through association is nested if there would be more than one join table
|
853
853
|
def nested?
|
854
854
|
source_reflection.through_reflection? || through_reflection.through_reflection?
|
@@ -863,10 +863,6 @@ module ActiveRecord
|
|
863
863
|
actual_source_reflection.options[:primary_key] || primary_key(klass || self.klass)
|
864
864
|
end
|
865
865
|
|
866
|
-
def association_primary_key_type
|
867
|
-
klass.type_for_attribute(association_primary_key.to_s)
|
868
|
-
end
|
869
|
-
|
870
866
|
# Gets an array of possible <tt>:through</tt> source reflection names in both singular and plural form.
|
871
867
|
#
|
872
868
|
# class Post < ActiveRecord::Base
|
@@ -891,15 +887,13 @@ module ActiveRecord
|
|
891
887
|
}
|
892
888
|
|
893
889
|
if names.length > 1
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
" #{macro} :#{name}, #{example_options}\n" \
|
902
|
-
" end"
|
890
|
+
raise AmbiguousSourceReflectionForThroughAssociation.new(
|
891
|
+
active_record.name,
|
892
|
+
macro,
|
893
|
+
name,
|
894
|
+
options,
|
895
|
+
source_reflection_names
|
896
|
+
)
|
903
897
|
end
|
904
898
|
|
905
899
|
@source_reflection_name = names.first
|
@@ -913,10 +907,6 @@ module ActiveRecord
|
|
913
907
|
through_reflection.options
|
914
908
|
end
|
915
909
|
|
916
|
-
def join_id_for(owner) # :nodoc:
|
917
|
-
source_reflection.join_id_for(owner)
|
918
|
-
end
|
919
|
-
|
920
910
|
def check_validity!
|
921
911
|
if through_reflection.nil?
|
922
912
|
raise HasManyThroughAssociationNotFoundError.new(active_record.name, self)
|
@@ -946,6 +936,14 @@ module ActiveRecord
|
|
946
936
|
raise HasOneThroughCantAssociateThroughCollection.new(active_record.name, self, through_reflection)
|
947
937
|
end
|
948
938
|
|
939
|
+
if parent_reflection.nil?
|
940
|
+
reflections = active_record.reflections.keys.map(&:to_sym)
|
941
|
+
|
942
|
+
if reflections.index(through_reflection.name) > reflections.index(name)
|
943
|
+
raise HasManyThroughOrderError.new(active_record.name, self, through_reflection)
|
944
|
+
end
|
945
|
+
end
|
946
|
+
|
949
947
|
check_validity_of_inverse!
|
950
948
|
end
|
951
949
|
|
@@ -967,28 +965,25 @@ module ActiveRecord
|
|
967
965
|
collect_join_reflections(seed + [self])
|
968
966
|
end
|
969
967
|
|
970
|
-
def collect_join_reflections(seed)
|
971
|
-
a = source_reflection.add_as_source seed
|
972
|
-
if options[:source_type]
|
973
|
-
through_reflection.add_as_polymorphic_through self, a
|
974
|
-
else
|
975
|
-
through_reflection.add_as_through a
|
976
|
-
end
|
977
|
-
end
|
978
|
-
|
979
968
|
protected
|
980
|
-
|
981
969
|
def actual_source_reflection # FIXME: this is a horrible name
|
982
|
-
source_reflection.
|
970
|
+
source_reflection.actual_source_reflection
|
983
971
|
end
|
984
972
|
|
985
|
-
|
986
|
-
|
973
|
+
private
|
974
|
+
attr_reader :delegate_reflection
|
975
|
+
|
976
|
+
def collect_join_reflections(seed)
|
977
|
+
a = source_reflection.add_as_source seed
|
978
|
+
if options[:source_type]
|
979
|
+
through_reflection.add_as_polymorphic_through self, a
|
980
|
+
else
|
981
|
+
through_reflection.add_as_through a
|
982
|
+
end
|
987
983
|
end
|
988
984
|
|
989
985
|
def inverse_name; delegate_reflection.send(:inverse_name); end
|
990
986
|
|
991
|
-
private
|
992
987
|
def derive_class_name
|
993
988
|
# get the class_name of the belongs_to association of the through reflection
|
994
989
|
options[:source_type] || source_reflection.class_name
|
@@ -998,52 +993,35 @@ module ActiveRecord
|
|
998
993
|
public_instance_methods
|
999
994
|
|
1000
995
|
delegate(*delegate_methods, to: :delegate_reflection)
|
1001
|
-
|
1002
996
|
end
|
1003
997
|
|
1004
|
-
class PolymorphicReflection <
|
998
|
+
class PolymorphicReflection < AbstractReflection # :nodoc:
|
999
|
+
delegate :klass, :scope, :plural_name, :type, :get_join_keys, :scope_for, to: :@reflection
|
1000
|
+
|
1005
1001
|
def initialize(reflection, previous_reflection)
|
1006
1002
|
@reflection = reflection
|
1007
1003
|
@previous_reflection = previous_reflection
|
1008
1004
|
end
|
1009
1005
|
|
1010
|
-
def
|
1011
|
-
@
|
1012
|
-
|
1013
|
-
|
1014
|
-
def scope
|
1015
|
-
@reflection.scope
|
1016
|
-
end
|
1017
|
-
|
1018
|
-
def table_name
|
1019
|
-
@reflection.table_name
|
1020
|
-
end
|
1021
|
-
|
1022
|
-
def plural_name
|
1023
|
-
@reflection.plural_name
|
1024
|
-
end
|
1025
|
-
|
1026
|
-
def join_keys(association_klass)
|
1027
|
-
@reflection.join_keys(association_klass)
|
1028
|
-
end
|
1029
|
-
|
1030
|
-
def type
|
1031
|
-
@reflection.type
|
1006
|
+
def join_scopes(table, predicate_builder) # :nodoc:
|
1007
|
+
scopes = @previous_reflection.join_scopes(table, predicate_builder) + super
|
1008
|
+
scopes << build_scope(table, predicate_builder).instance_exec(nil, &source_type_scope)
|
1032
1009
|
end
|
1033
1010
|
|
1034
1011
|
def constraints
|
1035
|
-
@reflection.constraints + [
|
1012
|
+
@reflection.constraints + [source_type_scope]
|
1036
1013
|
end
|
1037
1014
|
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1015
|
+
private
|
1016
|
+
def source_type_scope
|
1017
|
+
type = @previous_reflection.foreign_type
|
1018
|
+
source_type = @previous_reflection.options[:source_type]
|
1019
|
+
lambda { |object| where(type => source_type) }
|
1020
|
+
end
|
1043
1021
|
end
|
1044
1022
|
|
1045
|
-
class RuntimeReflection <
|
1046
|
-
|
1023
|
+
class RuntimeReflection < AbstractReflection # :nodoc:
|
1024
|
+
delegate :scope, :type, :constraints, :get_join_keys, to: :@reflection
|
1047
1025
|
|
1048
1026
|
def initialize(reflection, association)
|
1049
1027
|
@reflection = reflection
|
@@ -1054,24 +1032,8 @@ module ActiveRecord
|
|
1054
1032
|
@association.klass
|
1055
1033
|
end
|
1056
1034
|
|
1057
|
-
def
|
1058
|
-
klass.
|
1059
|
-
end
|
1060
|
-
|
1061
|
-
def constraints
|
1062
|
-
@reflection.constraints
|
1063
|
-
end
|
1064
|
-
|
1065
|
-
def source_type_info
|
1066
|
-
@reflection.source_type_info
|
1067
|
-
end
|
1068
|
-
|
1069
|
-
def alias_candidate(name)
|
1070
|
-
"#{plural_name}_#{name}_join"
|
1071
|
-
end
|
1072
|
-
|
1073
|
-
def alias_name
|
1074
|
-
Arel::Table.new(table_name)
|
1035
|
+
def aliased_table
|
1036
|
+
@aliased_table ||= Arel::Table.new(table_name, type_caster: klass.type_caster)
|
1075
1037
|
end
|
1076
1038
|
|
1077
1039
|
def all_includes; yield; end
|