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