activerecord 5.0.7.2 → 6.1.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 +829 -2015
- data/MIT-LICENSE +3 -1
- data/README.rdoc +11 -9
- data/examples/performance.rb +31 -29
- data/examples/simple.rb +5 -3
- data/lib/active_record.rb +37 -29
- data/lib/active_record/aggregations.rb +249 -247
- data/lib/active_record/association_relation.rb +30 -18
- data/lib/active_record/associations.rb +1714 -1596
- data/lib/active_record/associations/alias_tracker.rb +36 -42
- data/lib/active_record/associations/association.rb +143 -68
- data/lib/active_record/associations/association_scope.rb +98 -94
- data/lib/active_record/associations/belongs_to_association.rb +76 -46
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
- data/lib/active_record/associations/builder/association.rb +27 -28
- data/lib/active_record/associations/builder/belongs_to.rb +52 -60
- data/lib/active_record/associations/builder/collection_association.rb +12 -22
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +40 -62
- data/lib/active_record/associations/builder/has_many.rb +10 -2
- data/lib/active_record/associations/builder/has_one.rb +35 -2
- data/lib/active_record/associations/builder/singular_association.rb +5 -1
- data/lib/active_record/associations/collection_association.rb +104 -259
- data/lib/active_record/associations/collection_proxy.rb +169 -125
- data/lib/active_record/associations/foreign_association.rb +22 -0
- data/lib/active_record/associations/has_many_association.rb +46 -31
- data/lib/active_record/associations/has_many_through_association.rb +66 -46
- data/lib/active_record/associations/has_one_association.rb +71 -52
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency.rb +169 -180
- data/lib/active_record/associations/join_dependency/join_association.rb +53 -79
- 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/preloader.rb +97 -104
- data/lib/active_record/associations/preloader/association.rb +109 -97
- 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 +27 -15
- data/lib/active_record/attribute_assignment.rb +55 -60
- data/lib/active_record/attribute_methods.rb +111 -141
- data/lib/active_record/attribute_methods/before_type_cast.rb +17 -9
- data/lib/active_record/attribute_methods/dirty.rb +172 -112
- data/lib/active_record/attribute_methods/primary_key.rb +88 -91
- data/lib/active_record/attribute_methods/query.rb +6 -8
- data/lib/active_record/attribute_methods/read.rb +18 -50
- data/lib/active_record/attribute_methods/serialization.rb +38 -10
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +38 -66
- data/lib/active_record/attribute_methods/write.rb +25 -32
- data/lib/active_record/attributes.rb +69 -31
- data/lib/active_record/autosave_association.rb +102 -66
- data/lib/active_record/base.rb +16 -25
- data/lib/active_record/callbacks.rb +202 -43
- 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.rb +50 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +661 -375
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +14 -38
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +269 -105
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +54 -35
- data/lib/active_record/connection_adapters/abstract/quoting.rb +137 -93
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +155 -113
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +328 -162
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +591 -259
- data/lib/active_record/connection_adapters/abstract/transaction.rb +229 -91
- data/lib/active_record/connection_adapters/abstract_adapter.rb +392 -244
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +457 -582
- data/lib/active_record/connection_adapters/column.rb +55 -13
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +135 -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 +79 -49
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +66 -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 +20 -12
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +74 -37
- data/lib/active_record/connection_adapters/pool_config.rb +63 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +39 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +70 -101
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +26 -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 +6 -6
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +14 -4
- 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/interval.rb +49 -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/macaddr.rb +25 -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 +18 -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 +98 -38
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +21 -27
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -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 +426 -324
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +32 -23
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -6
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +418 -293
- data/lib/active_record/connection_adapters/schema_cache.rb +135 -18
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +22 -7
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -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 +5 -6
- 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 +170 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +282 -290
- data/lib/active_record/connection_adapters/statement_pool.rb +9 -8
- data/lib/active_record/connection_handling.rb +287 -45
- data/lib/active_record/core.rb +385 -181
- data/lib/active_record/counter_cache.rb +60 -28
- data/lib/active_record/database_configurations.rb +272 -0
- data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
- data/lib/active_record/database_configurations/database_config.rb +80 -0
- data/lib/active_record/database_configurations/hash_config.rb +96 -0
- data/lib/active_record/database_configurations/url_config.rb +53 -0
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/dynamic_matchers.rb +87 -87
- data/lib/active_record/enum.rb +122 -47
- data/lib/active_record/errors.rb +153 -22
- data/lib/active_record/explain.rb +13 -8
- 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 +20 -22
- data/lib/active_record/fixture_set/model_metadata.rb +32 -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 +246 -507
- data/lib/active_record/gem_version.rb +6 -4
- data/lib/active_record/inheritance.rb +168 -95
- data/lib/active_record/insert_all.rb +208 -0
- data/lib/active_record/integration.rb +114 -25
- data/lib/active_record/internal_metadata.rb +30 -24
- data/lib/active_record/legacy_yaml_adapter.rb +11 -5
- data/lib/active_record/locking/optimistic.rb +81 -85
- data/lib/active_record/locking/pessimistic.rb +22 -6
- data/lib/active_record/log_subscriber.rb +68 -31
- data/lib/active_record/middleware/database_selector.rb +77 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/migration.rb +439 -342
- data/lib/active_record/migration/command_recorder.rb +152 -98
- data/lib/active_record/migration/compatibility.rb +229 -60
- data/lib/active_record/migration/join_table.rb +8 -7
- data/lib/active_record/model_schema.rb +230 -122
- data/lib/active_record/nested_attributes.rb +213 -203
- data/lib/active_record/no_touching.rb +11 -2
- data/lib/active_record/null_relation.rb +12 -34
- data/lib/active_record/persistence.rb +471 -97
- data/lib/active_record/query_cache.rb +23 -12
- data/lib/active_record/querying.rb +43 -25
- data/lib/active_record/railtie.rb +155 -43
- 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 +507 -195
- data/lib/active_record/readonly_attributes.rb +9 -4
- data/lib/active_record/reflection.rb +245 -269
- data/lib/active_record/relation.rb +475 -324
- data/lib/active_record/relation/batches.rb +125 -72
- data/lib/active_record/relation/batches/batch_enumerator.rb +28 -10
- data/lib/active_record/relation/calculations.rb +267 -171
- data/lib/active_record/relation/delegation.rb +73 -69
- data/lib/active_record/relation/finder_methods.rb +238 -248
- data/lib/active_record/relation/from_clause.rb +7 -9
- data/lib/active_record/relation/merger.rb +95 -77
- data/lib/active_record/relation/predicate_builder.rb +109 -110
- data/lib/active_record/relation/predicate_builder/array_handler.rb +22 -17
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +55 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +7 -18
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
- data/lib/active_record/relation/query_attribute.rb +33 -2
- data/lib/active_record/relation/query_methods.rb +654 -374
- data/lib/active_record/relation/record_fetch_warning.rb +8 -6
- data/lib/active_record/relation/spawn_methods.rb +15 -14
- data/lib/active_record/relation/where_clause.rb +171 -109
- data/lib/active_record/result.rb +88 -51
- data/lib/active_record/runtime_registry.rb +5 -3
- data/lib/active_record/sanitization.rb +73 -100
- data/lib/active_record/schema.rb +7 -14
- data/lib/active_record/schema_dumper.rb +101 -69
- data/lib/active_record/schema_migration.rb +16 -12
- data/lib/active_record/scoping.rb +20 -20
- data/lib/active_record/scoping/default.rb +92 -95
- data/lib/active_record/scoping/named.rb +39 -30
- data/lib/active_record/secure_token.rb +19 -9
- data/lib/active_record/serialization.rb +7 -3
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +80 -29
- data/lib/active_record/store.rb +122 -42
- data/lib/active_record/suppressor.rb +6 -3
- data/lib/active_record/table_metadata.rb +51 -39
- data/lib/active_record/tasks/database_tasks.rb +332 -115
- data/lib/active_record/tasks/mysql_database_tasks.rb +66 -104
- data/lib/active_record/tasks/postgresql_database_tasks.rb +84 -56
- data/lib/active_record/tasks/sqlite_database_tasks.rb +40 -19
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +246 -0
- data/lib/active_record/timestamp.rb +70 -38
- data/lib/active_record/touch_later.rb +26 -24
- data/lib/active_record/transactions.rb +121 -184
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type.rb +29 -17
- 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 +20 -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_caster.rb +4 -2
- data/lib/active_record/type_caster/connection.rb +17 -13
- data/lib/active_record/type_caster/map.rb +10 -6
- data/lib/active_record/validations.rb +8 -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/numericality.rb +35 -0
- data/lib/active_record/validations/presence.rb +4 -2
- data/lib/active_record/validations/uniqueness.rb +52 -45
- data/lib/active_record/version.rb +3 -1
- data/lib/arel.rb +54 -0
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +41 -0
- data/lib/arel/collectors/bind.rb +29 -0
- data/lib/arel/collectors/composite.rb +39 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +27 -0
- data/lib/arel/collectors/substitute_binds.rb +35 -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 +70 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +126 -0
- data/lib/arel/nodes/bind_param.rb +44 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +62 -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 +15 -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 +11 -0
- data/lib/arel/nodes/homogeneous_in.rb +72 -0
- data/lib/arel/nodes/in.rb +15 -0
- data/lib/arel/nodes/infix_operation.rb +92 -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 +51 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/ordering.rb +27 -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 +19 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +31 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -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 +250 -0
- data/lib/arel/select_manager.rb +270 -0
- data/lib/arel/table.rb +118 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors.rb +13 -0
- data/lib/arel/visitors/dot.rb +308 -0
- data/lib/arel/visitors/mysql.rb +93 -0
- data/lib/arel/visitors/postgresql.rb +120 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +899 -0
- data/lib/arel/visitors/visitor.rb +45 -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 +22 -3
- data/lib/rails/generators/active_record/migration/migration_generator.rb +38 -35
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +3 -1
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +7 -5
- data/lib/rails/generators/active_record/model/model_generator.rb +41 -25
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- 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 +141 -57
- 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_decorators.rb +0 -67
- 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/connection_specification.rb +0 -263
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -22
- 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/base_handler.rb +0 -17
- 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/relation/where_clause_factory.rb +0 -38
- data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -1,22 +1,27 @@
|
|
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
|
21
|
+
end
|
22
|
+
|
23
|
+
def readonly_attribute?(name) # :nodoc:
|
24
|
+
_attr_readonly.include?(name)
|
20
25
|
end
|
21
26
|
end
|
22
27
|
end
|
@@ -1,5 +1,6 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/string/filters"
|
3
4
|
|
4
5
|
module ActiveRecord
|
5
6
|
# = Active Record Reflection
|
@@ -7,37 +8,41 @@ module ActiveRecord
|
|
7
8
|
extend ActiveSupport::Concern
|
8
9
|
|
9
10
|
included do
|
10
|
-
class_attribute :_reflections, instance_writer: false
|
11
|
-
class_attribute :aggregate_reflections, instance_writer: false
|
12
|
-
self._reflections = {}
|
13
|
-
self.aggregate_reflections = {}
|
11
|
+
class_attribute :_reflections, instance_writer: false, default: {}
|
12
|
+
class_attribute :aggregate_reflections, instance_writer: false, default: {}
|
14
13
|
end
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
HasManyReflection
|
22
|
-
when :has_one
|
23
|
-
HasOneReflection
|
24
|
-
when :belongs_to
|
25
|
-
BelongsToReflection
|
26
|
-
else
|
27
|
-
raise "Unsupported Macro: #{macro}"
|
28
|
-
end
|
29
|
-
|
30
|
-
reflection = klass.new(name, scope, options, ar)
|
31
|
-
options[:through] ? ThroughReflection.new(reflection) : reflection
|
32
|
-
end
|
15
|
+
class << self
|
16
|
+
def create(macro, name, scope, options, ar)
|
17
|
+
reflection = reflection_class_for(macro).new(name, scope, options, ar)
|
18
|
+
options[:through] ? ThroughReflection.new(reflection) : reflection
|
19
|
+
end
|
33
20
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
21
|
+
def add_reflection(ar, name, reflection)
|
22
|
+
ar.clear_reflections_cache
|
23
|
+
name = -name.to_s
|
24
|
+
ar._reflections = ar._reflections.except(name).merge!(name => reflection)
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_aggregate_reflection(ar, name, reflection)
|
28
|
+
ar.aggregate_reflections = ar.aggregate_reflections.merge(-name.to_s => reflection)
|
29
|
+
end
|
38
30
|
|
39
|
-
|
40
|
-
|
31
|
+
private
|
32
|
+
def reflection_class_for(macro)
|
33
|
+
case macro
|
34
|
+
when :composed_of
|
35
|
+
AggregateReflection
|
36
|
+
when :has_many
|
37
|
+
HasManyReflection
|
38
|
+
when :has_one
|
39
|
+
HasOneReflection
|
40
|
+
when :belongs_to
|
41
|
+
BelongsToReflection
|
42
|
+
else
|
43
|
+
raise "Unsupported Macro: #{macro}"
|
44
|
+
end
|
45
|
+
end
|
41
46
|
end
|
42
47
|
|
43
48
|
# \Reflection enables the ability to examine the associations and aggregations of
|
@@ -135,8 +140,8 @@ module ActiveRecord
|
|
135
140
|
# BelongsToReflection
|
136
141
|
# HasAndBelongsToManyReflection
|
137
142
|
# ThroughReflection
|
138
|
-
#
|
139
|
-
#
|
143
|
+
# PolymorphicReflection
|
144
|
+
# RuntimeReflection
|
140
145
|
class AbstractReflection # :nodoc:
|
141
146
|
def through_reflection?
|
142
147
|
false
|
@@ -152,41 +157,69 @@ module ActiveRecord
|
|
152
157
|
klass.new(attributes, &block)
|
153
158
|
end
|
154
159
|
|
155
|
-
def quoted_table_name
|
156
|
-
klass.quoted_table_name
|
157
|
-
end
|
158
|
-
|
159
|
-
def primary_key_type
|
160
|
-
klass.type_for_attribute(klass.primary_key)
|
161
|
-
end
|
162
|
-
|
163
160
|
# Returns the class name for the macro.
|
164
161
|
#
|
165
162
|
# <tt>composed_of :balance, class_name: 'Money'</tt> returns <tt>'Money'</tt>
|
166
163
|
# <tt>has_many :clients</tt> returns <tt>'Client'</tt>
|
167
164
|
def class_name
|
168
|
-
@class_name ||= (options[:class_name] || derive_class_name)
|
165
|
+
@class_name ||= -(options[:class_name]&.to_s || derive_class_name)
|
169
166
|
end
|
170
167
|
|
171
|
-
|
168
|
+
# Returns a list of scopes that should be applied for this Reflection
|
169
|
+
# object when querying the database.
|
170
|
+
def scopes
|
171
|
+
scope ? [scope] : []
|
172
|
+
end
|
173
|
+
|
174
|
+
def join_scope(table, foreign_table, foreign_klass)
|
175
|
+
predicate_builder = predicate_builder(table)
|
176
|
+
scope_chain_items = join_scopes(table, predicate_builder)
|
177
|
+
klass_scope = klass_join_scope(table, predicate_builder)
|
172
178
|
|
173
|
-
|
174
|
-
|
179
|
+
if type
|
180
|
+
klass_scope.where!(type => foreign_klass.polymorphic_name)
|
181
|
+
end
|
182
|
+
|
183
|
+
scope_chain_items.inject(klass_scope, &:merge!)
|
184
|
+
|
185
|
+
primary_key = join_primary_key
|
186
|
+
foreign_key = join_foreign_key
|
187
|
+
|
188
|
+
klass_scope.where!(table[primary_key].eq(foreign_table[foreign_key]))
|
189
|
+
|
190
|
+
if klass.finder_needs_type_condition?
|
191
|
+
klass_scope.where!(klass.send(:type_condition, table))
|
192
|
+
end
|
193
|
+
|
194
|
+
klass_scope
|
195
|
+
end
|
196
|
+
|
197
|
+
def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc:
|
198
|
+
if scope
|
199
|
+
[scope_for(build_scope(table, predicate_builder, klass))]
|
200
|
+
else
|
201
|
+
[]
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def klass_join_scope(table, predicate_builder) # :nodoc:
|
206
|
+
relation = build_scope(table, predicate_builder)
|
207
|
+
klass.scope_for_association(relation)
|
175
208
|
end
|
176
209
|
|
177
210
|
def constraints
|
178
|
-
|
211
|
+
chain.flat_map(&:scopes)
|
179
212
|
end
|
180
213
|
|
181
214
|
def counter_cache_column
|
182
|
-
if belongs_to?
|
215
|
+
@counter_cache_column ||= if belongs_to?
|
183
216
|
if options[:counter_cache] == true
|
184
|
-
"#{active_record.name.demodulize.underscore.pluralize}_count"
|
217
|
+
-"#{active_record.name.demodulize.underscore.pluralize}_count"
|
185
218
|
elsif options[:counter_cache]
|
186
|
-
options[:counter_cache].to_s
|
219
|
+
-options[:counter_cache].to_s
|
187
220
|
end
|
188
221
|
else
|
189
|
-
options[:counter_cache]
|
222
|
+
-(options[:counter_cache]&.to_s || "#{name}_count")
|
190
223
|
end
|
191
224
|
end
|
192
225
|
|
@@ -233,7 +266,7 @@ module ActiveRecord
|
|
233
266
|
def has_cached_counter?
|
234
267
|
options[:counter_cache] ||
|
235
268
|
inverse_which_updates_counter_cache && inverse_which_updates_counter_cache.options[:counter_cache] &&
|
236
|
-
|
269
|
+
active_record.has_attribute?(counter_cache_column)
|
237
270
|
end
|
238
271
|
|
239
272
|
def counter_must_be_updated_by_has_many?
|
@@ -247,6 +280,32 @@ module ActiveRecord
|
|
247
280
|
def chain
|
248
281
|
collect_join_chain
|
249
282
|
end
|
283
|
+
|
284
|
+
def build_scope(table, predicate_builder = predicate_builder(table), klass = self.klass)
|
285
|
+
Relation.create(
|
286
|
+
klass,
|
287
|
+
table: table,
|
288
|
+
predicate_builder: predicate_builder
|
289
|
+
)
|
290
|
+
end
|
291
|
+
|
292
|
+
def strict_loading?
|
293
|
+
options[:strict_loading]
|
294
|
+
end
|
295
|
+
|
296
|
+
protected
|
297
|
+
def actual_source_reflection # FIXME: this is a horrible name
|
298
|
+
self
|
299
|
+
end
|
300
|
+
|
301
|
+
private
|
302
|
+
def predicate_builder(table)
|
303
|
+
PredicateBuilder.new(TableMetadata.new(klass, table))
|
304
|
+
end
|
305
|
+
|
306
|
+
def primary_key(klass)
|
307
|
+
klass.primary_key || raise(UnknownPrimaryKey.new(klass))
|
308
|
+
end
|
250
309
|
end
|
251
310
|
|
252
311
|
# Base class for AggregateReflection and AssociationReflection. Objects of
|
@@ -281,7 +340,6 @@ module ActiveRecord
|
|
281
340
|
end
|
282
341
|
|
283
342
|
def autosave=(autosave)
|
284
|
-
@automatic_inverse_of = false
|
285
343
|
@options[:autosave] = autosave
|
286
344
|
parent_reflection = self.parent_reflection
|
287
345
|
if parent_reflection
|
@@ -293,6 +351,17 @@ module ActiveRecord
|
|
293
351
|
#
|
294
352
|
# <tt>composed_of :balance, class_name: 'Money'</tt> returns the Money class
|
295
353
|
# <tt>has_many :clients</tt> returns the Client class
|
354
|
+
#
|
355
|
+
# class Company < ActiveRecord::Base
|
356
|
+
# has_many :clients
|
357
|
+
# end
|
358
|
+
#
|
359
|
+
# Company.reflect_on_association(:clients).klass
|
360
|
+
# # => Client
|
361
|
+
#
|
362
|
+
# <b>Note:</b> Do not call +klass.new+ or +klass.create+ to instantiate
|
363
|
+
# a new association object. Use +build_association+ or +create_association+
|
364
|
+
# instead. This allows plugins to hook into association object creation.
|
296
365
|
def klass
|
297
366
|
@klass ||= compute_class(class_name)
|
298
367
|
end
|
@@ -311,8 +380,8 @@ module ActiveRecord
|
|
311
380
|
active_record == other_aggregation.active_record
|
312
381
|
end
|
313
382
|
|
314
|
-
def scope_for(
|
315
|
-
|
383
|
+
def scope_for(relation, owner = nil)
|
384
|
+
relation.instance_exec(owner, &scope) || relation
|
316
385
|
end
|
317
386
|
|
318
387
|
private
|
@@ -321,8 +390,7 @@ module ActiveRecord
|
|
321
390
|
end
|
322
391
|
end
|
323
392
|
|
324
|
-
|
325
|
-
# Holds all the meta-data about an aggregation as it was specified in the
|
393
|
+
# Holds all the metadata about an aggregation as it was specified in the
|
326
394
|
# Active Record class.
|
327
395
|
class AggregateReflection < MacroReflection #:nodoc:
|
328
396
|
def mapping
|
@@ -331,26 +399,13 @@ module ActiveRecord
|
|
331
399
|
end
|
332
400
|
end
|
333
401
|
|
334
|
-
# Holds all the
|
402
|
+
# Holds all the metadata about an association as it was specified in the
|
335
403
|
# Active Record class.
|
336
404
|
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
405
|
def compute_class(name)
|
406
|
+
if polymorphic?
|
407
|
+
raise ArgumentError, "Polymorphic associations do not support computing the class."
|
408
|
+
end
|
354
409
|
active_record.send(:compute_type, name)
|
355
410
|
end
|
356
411
|
|
@@ -359,22 +414,21 @@ module ActiveRecord
|
|
359
414
|
|
360
415
|
def initialize(name, scope, options, active_record)
|
361
416
|
super
|
362
|
-
@
|
363
|
-
@
|
364
|
-
@foreign_type = options[:foreign_type] || "#{name}_type"
|
417
|
+
@type = -(options[:foreign_type]&.to_s || "#{options[:as]}_type") if options[:as]
|
418
|
+
@foreign_type = -(options[:foreign_type]&.to_s || "#{name}_type") if options[:polymorphic]
|
365
419
|
@constructable = calculate_constructable(macro, options)
|
366
|
-
|
367
|
-
|
420
|
+
|
421
|
+
if options[:class_name] && options[:class_name].class == Class
|
422
|
+
raise ArgumentError, "A class was passed to `:class_name` but we are expecting a string."
|
423
|
+
end
|
368
424
|
end
|
369
425
|
|
370
|
-
def association_scope_cache(
|
371
|
-
key =
|
426
|
+
def association_scope_cache(klass, owner, &block)
|
427
|
+
key = self
|
372
428
|
if polymorphic?
|
373
429
|
key = [key, owner._read_attribute(@foreign_type)]
|
374
430
|
end
|
375
|
-
|
376
|
-
@association_scope_cache[key] ||= yield
|
377
|
-
}
|
431
|
+
klass.cached_find_by_statement(key, &block)
|
378
432
|
end
|
379
433
|
|
380
434
|
def constructable? # :nodoc:
|
@@ -382,28 +436,31 @@ module ActiveRecord
|
|
382
436
|
end
|
383
437
|
|
384
438
|
def join_table
|
385
|
-
@join_table ||= options[:join_table] || derive_join_table
|
439
|
+
@join_table ||= -(options[:join_table]&.to_s || derive_join_table)
|
386
440
|
end
|
387
441
|
|
388
442
|
def foreign_key
|
389
|
-
@foreign_key ||= options[:foreign_key] || derive_foreign_key
|
443
|
+
@foreign_key ||= -(options[:foreign_key]&.to_s || derive_foreign_key)
|
390
444
|
end
|
391
445
|
|
392
446
|
def association_foreign_key
|
393
|
-
@association_foreign_key ||= options[:association_foreign_key] || class_name.foreign_key
|
447
|
+
@association_foreign_key ||= -(options[:association_foreign_key]&.to_s || class_name.foreign_key)
|
394
448
|
end
|
395
449
|
|
396
|
-
# klass option is necessary to support loading polymorphic associations
|
397
450
|
def association_primary_key(klass = nil)
|
398
|
-
|
451
|
+
primary_key(klass || self.klass)
|
399
452
|
end
|
400
453
|
|
401
|
-
def
|
402
|
-
|
454
|
+
def active_record_primary_key
|
455
|
+
@active_record_primary_key ||= -(options[:primary_key]&.to_s || primary_key(active_record))
|
403
456
|
end
|
404
457
|
|
405
|
-
def
|
406
|
-
|
458
|
+
def join_primary_key(klass = nil)
|
459
|
+
foreign_key
|
460
|
+
end
|
461
|
+
|
462
|
+
def join_foreign_key
|
463
|
+
active_record_primary_key
|
407
464
|
end
|
408
465
|
|
409
466
|
def check_validity!
|
@@ -413,7 +470,7 @@ module ActiveRecord
|
|
413
470
|
def check_preloadable!
|
414
471
|
return unless scope
|
415
472
|
|
416
|
-
|
473
|
+
unless scope.arity == 0
|
417
474
|
raise ArgumentError, <<-MSG.squish
|
418
475
|
The association scope '#{name}' is instance dependent (the scope
|
419
476
|
block takes an argument). Preloading instance dependent scopes is
|
@@ -424,7 +481,7 @@ module ActiveRecord
|
|
424
481
|
alias :check_eager_loadable! :check_preloadable!
|
425
482
|
|
426
483
|
def join_id_for(owner) # :nodoc:
|
427
|
-
owner[
|
484
|
+
owner[join_foreign_key]
|
428
485
|
end
|
429
486
|
|
430
487
|
def through_reflection
|
@@ -444,19 +501,13 @@ module ActiveRecord
|
|
444
501
|
# This is for clearing cache on the reflection. Useful for tests that need to compare
|
445
502
|
# SQL queries on associations.
|
446
503
|
def clear_association_scope_cache # :nodoc:
|
447
|
-
|
504
|
+
klass.initialize_find_by_cache
|
448
505
|
end
|
449
506
|
|
450
507
|
def nested?
|
451
508
|
false
|
452
509
|
end
|
453
510
|
|
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
511
|
def has_scope?
|
461
512
|
scope
|
462
513
|
end
|
@@ -513,7 +564,7 @@ module ActiveRecord
|
|
513
564
|
end
|
514
565
|
|
515
566
|
VALID_AUTOMATIC_INVERSE_MACROS = [:has_many, :has_one, :belongs_to]
|
516
|
-
INVALID_AUTOMATIC_INVERSE_OPTIONS = [:
|
567
|
+
INVALID_AUTOMATIC_INVERSE_OPTIONS = [:through, :foreign_key]
|
517
568
|
|
518
569
|
def add_as_source(seed)
|
519
570
|
seed
|
@@ -531,32 +582,23 @@ module ActiveRecord
|
|
531
582
|
Array(options[:extend])
|
532
583
|
end
|
533
584
|
|
534
|
-
protected
|
535
|
-
|
536
|
-
def actual_source_reflection # FIXME: this is a horrible name
|
537
|
-
self
|
538
|
-
end
|
539
|
-
|
540
585
|
private
|
541
|
-
|
542
586
|
def calculate_constructable(macro, options)
|
543
587
|
true
|
544
588
|
end
|
545
589
|
|
546
590
|
# Attempts to find the inverse association name automatically.
|
547
591
|
# If it cannot find a suitable inverse association name, it returns
|
548
|
-
# nil
|
592
|
+
# +nil+.
|
549
593
|
def inverse_name
|
550
|
-
|
551
|
-
|
552
|
-
nil
|
553
|
-
else
|
554
|
-
@automatic_inverse_of ||= automatic_inverse_of
|
555
|
-
end
|
594
|
+
unless defined?(@inverse_name)
|
595
|
+
@inverse_name = options.fetch(:inverse_of) { automatic_inverse_of }
|
556
596
|
end
|
597
|
+
|
598
|
+
@inverse_name
|
557
599
|
end
|
558
600
|
|
559
|
-
# returns either
|
601
|
+
# returns either +nil+ or the inverse association name that it finds.
|
560
602
|
def automatic_inverse_of
|
561
603
|
if can_find_inverse_of_automatically?(self)
|
562
604
|
inverse_name = ActiveSupport::Inflector.underscore(options[:as] || active_record.name.demodulize).to_sym
|
@@ -570,23 +612,19 @@ module ActiveRecord
|
|
570
612
|
end
|
571
613
|
|
572
614
|
if valid_inverse_reflection?(reflection)
|
573
|
-
|
615
|
+
inverse_name
|
574
616
|
end
|
575
617
|
end
|
576
|
-
|
577
|
-
false
|
578
618
|
end
|
579
619
|
|
580
620
|
# Checks if the inverse reflection that is returned from the
|
581
621
|
# +automatic_inverse_of+ method is a valid reflection. We must
|
582
622
|
# make sure that the reflection's active_record name matches up
|
583
623
|
# 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
624
|
def valid_inverse_reflection?(reflection)
|
588
625
|
reflection &&
|
589
|
-
|
626
|
+
foreign_key == reflection.foreign_key &&
|
627
|
+
klass <= reflection.active_record &&
|
590
628
|
can_find_inverse_of_automatically?(reflection)
|
591
629
|
end
|
592
630
|
|
@@ -594,9 +632,8 @@ module ActiveRecord
|
|
594
632
|
# us from being able to guess the inverse automatically. First, the
|
595
633
|
# <tt>inverse_of</tt> option cannot be set to false. Second, we must
|
596
634
|
# 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.
|
635
|
+
# Third, we must not have options such as <tt>:foreign_key</tt>
|
636
|
+
# which prevent us from correctly guessing the inverse association.
|
600
637
|
#
|
601
638
|
# Anything with a scope can additionally ruin our attempt at finding an
|
602
639
|
# inverse, so we exclude reflections with scopes.
|
@@ -626,10 +663,6 @@ module ActiveRecord
|
|
626
663
|
def derive_join_table
|
627
664
|
ModelSchema.derive_join_table_name active_record.table_name, klass.table_name
|
628
665
|
end
|
629
|
-
|
630
|
-
def primary_key(klass)
|
631
|
-
klass.primary_key || raise(UnknownPrimaryKey.new(klass))
|
632
|
-
end
|
633
666
|
end
|
634
667
|
|
635
668
|
class HasManyReflection < AssociationReflection # :nodoc:
|
@@ -644,10 +677,6 @@ module ActiveRecord
|
|
644
677
|
Associations::HasManyAssociation
|
645
678
|
end
|
646
679
|
end
|
647
|
-
|
648
|
-
def association_primary_key(klass = nil)
|
649
|
-
primary_key(klass || self.klass)
|
650
|
-
end
|
651
680
|
end
|
652
681
|
|
653
682
|
class HasOneReflection < AssociationReflection # :nodoc:
|
@@ -664,7 +693,6 @@ module ActiveRecord
|
|
664
693
|
end
|
665
694
|
|
666
695
|
private
|
667
|
-
|
668
696
|
def calculate_constructable(macro, options)
|
669
697
|
!options[:through]
|
670
698
|
end
|
@@ -683,16 +711,31 @@ module ActiveRecord
|
|
683
711
|
end
|
684
712
|
end
|
685
713
|
|
686
|
-
|
687
|
-
|
688
|
-
|
714
|
+
# klass option is necessary to support loading polymorphic associations
|
715
|
+
def association_primary_key(klass = nil)
|
716
|
+
if primary_key = options[:primary_key]
|
717
|
+
@association_primary_key ||= -primary_key.to_s
|
718
|
+
else
|
719
|
+
primary_key(klass || self.klass)
|
720
|
+
end
|
689
721
|
end
|
690
722
|
|
691
|
-
def
|
692
|
-
|
723
|
+
def join_primary_key(klass = nil)
|
724
|
+
polymorphic? ? association_primary_key(klass) : association_primary_key
|
725
|
+
end
|
726
|
+
|
727
|
+
def join_foreign_key
|
728
|
+
foreign_key
|
729
|
+
end
|
730
|
+
|
731
|
+
def join_foreign_type
|
732
|
+
foreign_type
|
693
733
|
end
|
694
734
|
|
695
735
|
private
|
736
|
+
def can_find_inverse_of_automatically?(_)
|
737
|
+
!polymorphic? && super
|
738
|
+
end
|
696
739
|
|
697
740
|
def calculate_constructable(macro, options)
|
698
741
|
!polymorphic?
|
@@ -700,10 +743,6 @@ module ActiveRecord
|
|
700
743
|
end
|
701
744
|
|
702
745
|
class HasAndBelongsToManyReflection < AssociationReflection # :nodoc:
|
703
|
-
def initialize(name, scope, options, active_record)
|
704
|
-
super
|
705
|
-
end
|
706
|
-
|
707
746
|
def macro; :has_and_belongs_to_many; end
|
708
747
|
|
709
748
|
def collection?
|
@@ -711,16 +750,15 @@ module ActiveRecord
|
|
711
750
|
end
|
712
751
|
end
|
713
752
|
|
714
|
-
# Holds all the
|
753
|
+
# Holds all the metadata about a :through association as it was specified
|
715
754
|
# in the Active Record class.
|
716
755
|
class ThroughReflection < AbstractReflection #:nodoc:
|
717
|
-
|
718
|
-
|
719
|
-
:active_record_primary_key, :type, :to => :source_reflection
|
756
|
+
delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for, :type,
|
757
|
+
:active_record_primary_key, :join_foreign_key, to: :source_reflection
|
720
758
|
|
721
759
|
def initialize(delegate_reflection)
|
722
760
|
@delegate_reflection = delegate_reflection
|
723
|
-
@klass
|
761
|
+
@klass = delegate_reflection.options[:anonymous_class]
|
724
762
|
@source_reflection_name = delegate_reflection.options[:source]
|
725
763
|
end
|
726
764
|
|
@@ -798,45 +836,12 @@ module ActiveRecord
|
|
798
836
|
through_reflection.clear_association_scope_cache
|
799
837
|
end
|
800
838
|
|
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
|
839
|
+
def scopes
|
840
|
+
source_reflection.scopes + super
|
841
|
+
end
|
836
842
|
|
837
|
-
|
838
|
-
|
839
|
-
end
|
843
|
+
def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc:
|
844
|
+
source_reflection.join_scopes(table, predicate_builder, klass) + super
|
840
845
|
end
|
841
846
|
|
842
847
|
def has_scope?
|
@@ -845,10 +850,6 @@ module ActiveRecord
|
|
845
850
|
through_reflection.has_scope?
|
846
851
|
end
|
847
852
|
|
848
|
-
def join_keys(association_klass)
|
849
|
-
source_reflection.join_keys(association_klass)
|
850
|
-
end
|
851
|
-
|
852
853
|
# A through association is nested if there would be more than one join table
|
853
854
|
def nested?
|
854
855
|
source_reflection.through_reflection? || through_reflection.through_reflection?
|
@@ -860,11 +861,15 @@ module ActiveRecord
|
|
860
861
|
def association_primary_key(klass = nil)
|
861
862
|
# Get the "actual" source reflection if the immediate source reflection has a
|
862
863
|
# source reflection itself
|
863
|
-
actual_source_reflection.options[:primary_key]
|
864
|
+
if primary_key = actual_source_reflection.options[:primary_key]
|
865
|
+
@association_primary_key ||= -primary_key.to_s
|
866
|
+
else
|
867
|
+
primary_key(klass || self.klass)
|
868
|
+
end
|
864
869
|
end
|
865
870
|
|
866
|
-
def
|
867
|
-
|
871
|
+
def join_primary_key(klass = self.klass)
|
872
|
+
source_reflection.join_primary_key(klass)
|
868
873
|
end
|
869
874
|
|
870
875
|
# Gets an array of possible <tt>:through</tt> source reflection names in both singular and plural form.
|
@@ -891,15 +896,13 @@ module ActiveRecord
|
|
891
896
|
}
|
892
897
|
|
893
898
|
if names.length > 1
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
" #{macro} :#{name}, #{example_options}\n" \
|
902
|
-
" end"
|
899
|
+
raise AmbiguousSourceReflectionForThroughAssociation.new(
|
900
|
+
active_record.name,
|
901
|
+
macro,
|
902
|
+
name,
|
903
|
+
options,
|
904
|
+
source_reflection_names
|
905
|
+
)
|
903
906
|
end
|
904
907
|
|
905
908
|
@source_reflection_name = names.first
|
@@ -913,13 +916,9 @@ module ActiveRecord
|
|
913
916
|
through_reflection.options
|
914
917
|
end
|
915
918
|
|
916
|
-
def join_id_for(owner) # :nodoc:
|
917
|
-
source_reflection.join_id_for(owner)
|
918
|
-
end
|
919
|
-
|
920
919
|
def check_validity!
|
921
920
|
if through_reflection.nil?
|
922
|
-
raise HasManyThroughAssociationNotFoundError.new(active_record
|
921
|
+
raise HasManyThroughAssociationNotFoundError.new(active_record, self)
|
923
922
|
end
|
924
923
|
|
925
924
|
if through_reflection.polymorphic?
|
@@ -946,6 +945,14 @@ module ActiveRecord
|
|
946
945
|
raise HasOneThroughCantAssociateThroughCollection.new(active_record.name, self, through_reflection)
|
947
946
|
end
|
948
947
|
|
948
|
+
if parent_reflection.nil?
|
949
|
+
reflections = active_record.reflections.keys.map(&:to_sym)
|
950
|
+
|
951
|
+
if reflections.index(through_reflection.name) > reflections.index(name)
|
952
|
+
raise HasManyThroughOrderError.new(active_record.name, self, through_reflection)
|
953
|
+
end
|
954
|
+
end
|
955
|
+
|
949
956
|
check_validity_of_inverse!
|
950
957
|
end
|
951
958
|
|
@@ -967,28 +974,25 @@ module ActiveRecord
|
|
967
974
|
collect_join_reflections(seed + [self])
|
968
975
|
end
|
969
976
|
|
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
977
|
protected
|
980
|
-
|
981
978
|
def actual_source_reflection # FIXME: this is a horrible name
|
982
|
-
source_reflection.
|
979
|
+
source_reflection.actual_source_reflection
|
983
980
|
end
|
984
981
|
|
985
|
-
|
986
|
-
|
982
|
+
private
|
983
|
+
attr_reader :delegate_reflection
|
984
|
+
|
985
|
+
def collect_join_reflections(seed)
|
986
|
+
a = source_reflection.add_as_source seed
|
987
|
+
if options[:source_type]
|
988
|
+
through_reflection.add_as_polymorphic_through self, a
|
989
|
+
else
|
990
|
+
through_reflection.add_as_through a
|
991
|
+
end
|
987
992
|
end
|
988
993
|
|
989
994
|
def inverse_name; delegate_reflection.send(:inverse_name); end
|
990
995
|
|
991
|
-
private
|
992
996
|
def derive_class_name
|
993
997
|
# get the class_name of the belongs_to association of the through reflection
|
994
998
|
options[:source_type] || source_reflection.class_name
|
@@ -998,52 +1002,36 @@ module ActiveRecord
|
|
998
1002
|
public_instance_methods
|
999
1003
|
|
1000
1004
|
delegate(*delegate_methods, to: :delegate_reflection)
|
1001
|
-
|
1002
1005
|
end
|
1003
1006
|
|
1004
|
-
class PolymorphicReflection <
|
1007
|
+
class PolymorphicReflection < AbstractReflection # :nodoc:
|
1008
|
+
delegate :klass, :scope, :plural_name, :type, :join_primary_key, :join_foreign_key,
|
1009
|
+
:name, :scope_for, to: :@reflection
|
1010
|
+
|
1005
1011
|
def initialize(reflection, previous_reflection)
|
1006
1012
|
@reflection = reflection
|
1007
1013
|
@previous_reflection = previous_reflection
|
1008
1014
|
end
|
1009
1015
|
|
1010
|
-
def klass
|
1011
|
-
@
|
1012
|
-
|
1013
|
-
|
1014
|
-
def scope
|
1015
|
-
@reflection.scope
|
1016
|
-
end
|
1017
|
-
|
1018
|
-
def table_name
|
1019
|
-
@reflection.table_name
|
1020
|
-
end
|
1021
|
-
|
1022
|
-
def plural_name
|
1023
|
-
@reflection.plural_name
|
1024
|
-
end
|
1025
|
-
|
1026
|
-
def join_keys(association_klass)
|
1027
|
-
@reflection.join_keys(association_klass)
|
1028
|
-
end
|
1029
|
-
|
1030
|
-
def type
|
1031
|
-
@reflection.type
|
1016
|
+
def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc:
|
1017
|
+
scopes = @previous_reflection.join_scopes(table, predicate_builder) + super
|
1018
|
+
scopes << build_scope(table, predicate_builder, klass).instance_exec(nil, &source_type_scope)
|
1032
1019
|
end
|
1033
1020
|
|
1034
1021
|
def constraints
|
1035
|
-
@reflection.constraints + [
|
1022
|
+
@reflection.constraints + [source_type_scope]
|
1036
1023
|
end
|
1037
1024
|
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1025
|
+
private
|
1026
|
+
def source_type_scope
|
1027
|
+
type = @previous_reflection.foreign_type
|
1028
|
+
source_type = @previous_reflection.options[:source_type]
|
1029
|
+
lambda { |object| where(type => source_type) }
|
1030
|
+
end
|
1043
1031
|
end
|
1044
1032
|
|
1045
|
-
class RuntimeReflection <
|
1046
|
-
|
1033
|
+
class RuntimeReflection < AbstractReflection # :nodoc:
|
1034
|
+
delegate :scope, :type, :constraints, :join_foreign_key, to: :@reflection
|
1047
1035
|
|
1048
1036
|
def initialize(reflection, association)
|
1049
1037
|
@reflection = reflection
|
@@ -1054,24 +1042,12 @@ module ActiveRecord
|
|
1054
1042
|
@association.klass
|
1055
1043
|
end
|
1056
1044
|
|
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"
|
1045
|
+
def aliased_table
|
1046
|
+
klass.arel_table
|
1071
1047
|
end
|
1072
1048
|
|
1073
|
-
def
|
1074
|
-
|
1049
|
+
def join_primary_key(klass = self.klass)
|
1050
|
+
@reflection.join_primary_key(klass)
|
1075
1051
|
end
|
1076
1052
|
|
1077
1053
|
def all_includes; yield; end
|