activerecord 5.2.8 → 7.0.2
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 +1393 -587
- data/MIT-LICENSE +3 -1
- data/README.rdoc +7 -5
- data/examples/performance.rb +1 -1
- data/lib/active_record/aggregations.rb +10 -9
- data/lib/active_record/association_relation.rb +22 -12
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +122 -47
- data/lib/active_record/associations/association_scope.rb +24 -24
- data/lib/active_record/associations/belongs_to_association.rb +67 -49
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +16 -7
- data/lib/active_record/associations/builder/association.rb +52 -23
- data/lib/active_record/associations/builder/belongs_to.rb +44 -61
- data/lib/active_record/associations/builder/collection_association.rb +17 -19
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -41
- data/lib/active_record/associations/builder/has_many.rb +10 -3
- data/lib/active_record/associations/builder/has_one.rb +35 -3
- data/lib/active_record/associations/builder/singular_association.rb +5 -3
- data/lib/active_record/associations/collection_association.rb +59 -50
- data/lib/active_record/associations/collection_proxy.rb +32 -23
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/foreign_association.rb +20 -0
- data/lib/active_record/associations/has_many_association.rb +27 -14
- data/lib/active_record/associations/has_many_through_association.rb +26 -19
- data/lib/active_record/associations/has_one_association.rb +52 -37
- data/lib/active_record/associations/has_one_through_association.rb +6 -6
- data/lib/active_record/associations/join_dependency/join_association.rb +44 -22
- data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
- data/lib/active_record/associations/join_dependency.rb +97 -62
- data/lib/active_record/associations/preloader/association.rb +220 -60
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +147 -0
- data/lib/active_record/associations/preloader/through_association.rb +85 -40
- data/lib/active_record/associations/preloader.rb +44 -105
- data/lib/active_record/associations/singular_association.rb +9 -17
- data/lib/active_record/associations/through_association.rb +4 -4
- data/lib/active_record/associations.rb +207 -66
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +17 -19
- data/lib/active_record/attribute_methods/before_type_cast.rb +19 -8
- data/lib/active_record/attribute_methods/dirty.rb +141 -47
- data/lib/active_record/attribute_methods/primary_key.rb +22 -27
- data/lib/active_record/attribute_methods/query.rb +6 -10
- data/lib/active_record/attribute_methods/read.rb +15 -55
- data/lib/active_record/attribute_methods/serialization.rb +77 -18
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +16 -18
- data/lib/active_record/attribute_methods/write.rb +18 -37
- data/lib/active_record/attribute_methods.rb +90 -153
- data/lib/active_record/attributes.rb +38 -12
- data/lib/active_record/autosave_association.rb +50 -50
- data/lib/active_record/base.rb +23 -18
- data/lib/active_record/callbacks.rb +159 -44
- data/lib/active_record/coders/yaml_column.rb +12 -3
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +292 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +209 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +76 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +92 -464
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -51
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +209 -164
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +38 -22
- data/lib/active_record/connection_adapters/abstract/quoting.rb +103 -82
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +140 -110
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -94
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +16 -5
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +456 -159
- data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -78
- data/lib/active_record/connection_adapters/abstract_adapter.rb +367 -162
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +311 -327
- data/lib/active_record/connection_adapters/column.rb +33 -11
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +113 -45
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +71 -5
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +34 -10
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +48 -32
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +25 -8
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +143 -19
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +63 -22
- data/lib/active_record/connection_adapters/pool_config.rb +73 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +53 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +56 -63
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +10 -2
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +15 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +54 -16
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +26 -12
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +15 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +4 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +89 -52
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +34 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +39 -4
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +128 -91
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +25 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +149 -113
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +31 -26
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +386 -182
- data/lib/active_record/connection_adapters/schema_cache.rb +161 -22
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +17 -6
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +152 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +65 -18
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +92 -26
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +251 -204
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_adapters.rb +53 -0
- data/lib/active_record/connection_handling.rb +292 -38
- data/lib/active_record/core.rb +385 -158
- data/lib/active_record/counter_cache.rb +8 -30
- data/lib/active_record/database_configurations/connection_url_resolver.rb +100 -0
- data/lib/active_record/database_configurations/database_config.rb +83 -0
- data/lib/active_record/database_configurations/hash_config.rb +154 -0
- data/lib/active_record/database_configurations/url_config.rb +53 -0
- data/lib/active_record/database_configurations.rb +256 -0
- data/lib/active_record/delegated_type.rb +250 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +4 -5
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +98 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +44 -0
- data/lib/active_record/encryption/configurable.rb +61 -0
- data/lib/active_record/encryption/context.rb +35 -0
- data/lib/active_record/encryption/contexts.rb +72 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +12 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +208 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +140 -0
- data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
- data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
- data/lib/active_record/encryption/encryptor.rb +155 -0
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
- data/lib/active_record/encryption/errors.rb +15 -0
- data/lib/active_record/encryption/extended_deterministic_queries.rb +160 -0
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
- data/lib/active_record/encryption/key.rb +28 -0
- data/lib/active_record/encryption/key_generator.rb +42 -0
- data/lib/active_record/encryption/key_provider.rb +46 -0
- data/lib/active_record/encryption/message.rb +33 -0
- data/lib/active_record/encryption/message_serializer.rb +90 -0
- data/lib/active_record/encryption/null_encryptor.rb +21 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
- data/lib/active_record/encryption/scheme.rb +99 -0
- data/lib/active_record/encryption.rb +55 -0
- data/lib/active_record/enum.rb +130 -51
- data/lib/active_record/errors.rb +129 -23
- data/lib/active_record/explain.rb +10 -6
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +22 -15
- 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 +187 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +206 -490
- data/lib/active_record/future_result.rb +139 -0
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +104 -37
- data/lib/active_record/insert_all.rb +278 -0
- data/lib/active_record/integration.rb +69 -18
- data/lib/active_record/internal_metadata.rb +24 -9
- data/lib/active_record/legacy_yaml_adapter.rb +3 -36
- data/lib/active_record/locking/optimistic.rb +41 -26
- data/lib/active_record/locking/pessimistic.rb +18 -8
- data/lib/active_record/log_subscriber.rb +46 -35
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +88 -0
- data/lib/active_record/middleware/database_selector.rb +82 -0
- data/lib/active_record/middleware/shard_selector.rb +60 -0
- data/lib/active_record/migration/command_recorder.rb +96 -44
- data/lib/active_record/migration/compatibility.rb +246 -64
- data/lib/active_record/migration/join_table.rb +1 -2
- data/lib/active_record/migration.rb +266 -187
- data/lib/active_record/model_schema.rb +165 -52
- data/lib/active_record/nested_attributes.rb +17 -19
- data/lib/active_record/no_touching.rb +11 -4
- data/lib/active_record/null_relation.rb +2 -7
- data/lib/active_record/persistence.rb +467 -92
- data/lib/active_record/query_cache.rb +21 -4
- data/lib/active_record/query_logs.rb +138 -0
- data/lib/active_record/querying.rb +51 -24
- data/lib/active_record/railtie.rb +224 -57
- data/lib/active_record/railties/console_sandbox.rb +2 -4
- data/lib/active_record/railties/controller_runtime.rb +31 -36
- data/lib/active_record/railties/databases.rake +369 -101
- data/lib/active_record/readonly_attributes.rb +15 -0
- data/lib/active_record/reflection.rb +170 -137
- data/lib/active_record/relation/batches/batch_enumerator.rb +44 -14
- data/lib/active_record/relation/batches.rb +46 -37
- data/lib/active_record/relation/calculations.rb +168 -96
- data/lib/active_record/relation/delegation.rb +37 -52
- data/lib/active_record/relation/finder_methods.rb +79 -58
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +50 -51
- data/lib/active_record/relation/predicate_builder/array_handler.rb +13 -13
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +5 -9
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +11 -10
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +58 -46
- data/lib/active_record/relation/query_attribute.rb +9 -10
- data/lib/active_record/relation/query_methods.rb +685 -208
- data/lib/active_record/relation/record_fetch_warning.rb +9 -11
- data/lib/active_record/relation/spawn_methods.rb +10 -10
- data/lib/active_record/relation/where_clause.rb +108 -64
- data/lib/active_record/relation.rb +515 -151
- data/lib/active_record/result.rb +78 -42
- data/lib/active_record/runtime_registry.rb +9 -13
- data/lib/active_record/sanitization.rb +29 -44
- data/lib/active_record/schema.rb +37 -31
- data/lib/active_record/schema_dumper.rb +74 -23
- data/lib/active_record/schema_migration.rb +7 -9
- data/lib/active_record/scoping/default.rb +62 -17
- data/lib/active_record/scoping/named.rb +17 -32
- data/lib/active_record/scoping.rb +70 -41
- data/lib/active_record/secure_token.rb +16 -8
- data/lib/active_record/serialization.rb +6 -4
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +49 -6
- data/lib/active_record/store.rb +88 -9
- data/lib/active_record/suppressor.rb +13 -17
- data/lib/active_record/table_metadata.rb +42 -43
- data/lib/active_record/tasks/database_tasks.rb +352 -94
- data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
- data/lib/active_record/tasks/postgresql_database_tasks.rb +41 -39
- data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -17
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +287 -0
- data/lib/active_record/timestamp.rb +44 -34
- data/lib/active_record/touch_later.rb +23 -22
- data/lib/active_record/transactions.rb +67 -128
- data/lib/active_record/translation.rb +3 -3
- data/lib/active_record/type/adapter_specific_registry.rb +34 -19
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -2
- data/lib/active_record/type/internal/timezone.rb +2 -2
- data/lib/active_record/type/serialized.rb +7 -4
- data/lib/active_record/type/time.rb +10 -0
- data/lib/active_record/type/type_map.rb +17 -21
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type.rb +9 -5
- data/lib/active_record/type_caster/connection.rb +15 -15
- data/lib/active_record/type_caster/map.rb +8 -8
- data/lib/active_record/validations/associated.rb +2 -3
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +39 -31
- data/lib/active_record/validations.rb +4 -3
- data/lib/active_record.rb +209 -32
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +33 -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 +48 -0
- data/lib/arel/delete_manager.rb +32 -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/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +48 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +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 +44 -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/filter.rb +10 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +45 -0
- data/lib/arel/nodes/grouping.rb +11 -0
- data/lib/arel/nodes/homogeneous_in.rb +76 -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 +46 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +71 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +258 -0
- data/lib/arel/select_manager.rb +276 -0
- data/lib/arel/table.rb +117 -0
- data/lib/arel/tree_manager.rb +60 -0
- data/lib/arel/update_manager.rb +48 -0
- data/lib/arel/visitors/dot.rb +298 -0
- data/lib/arel/visitors/mysql.rb +99 -0
- data/lib/arel/visitors/postgresql.rb +110 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +955 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors.rb +13 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +55 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -5
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +3 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +7 -5
- data/lib/rails/generators/active_record/migration.rb +19 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
- 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.tt +10 -1
- data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
- data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
- data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
- metadata +162 -32
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/collection_cache_key.rb +0 -53
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -287
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -33
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -19
- data/lib/active_record/relation/where_clause_factory.rb +0 -34
@@ -3,32 +3,33 @@
|
|
3
3
|
module ActiveRecord
|
4
4
|
module Tasks # :nodoc:
|
5
5
|
class MySQLDatabaseTasks # :nodoc:
|
6
|
+
ER_DB_CREATE_EXISTS = 1007
|
7
|
+
|
6
8
|
delegate :connection, :establish_connection, to: ActiveRecord::Base
|
7
9
|
|
8
|
-
def
|
9
|
-
|
10
|
+
def self.using_database_configurations?
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(db_config)
|
15
|
+
@db_config = db_config
|
16
|
+
@configuration_hash = db_config.configuration_hash
|
10
17
|
end
|
11
18
|
|
12
19
|
def create
|
13
|
-
establish_connection
|
14
|
-
connection.create_database
|
15
|
-
establish_connection
|
16
|
-
rescue ActiveRecord::StatementInvalid => error
|
17
|
-
if error.message.include?("database exists")
|
18
|
-
raise DatabaseAlreadyExists
|
19
|
-
else
|
20
|
-
raise
|
21
|
-
end
|
20
|
+
establish_connection(configuration_hash_without_database)
|
21
|
+
connection.create_database(db_config.database, creation_options)
|
22
|
+
establish_connection(db_config)
|
22
23
|
end
|
23
24
|
|
24
25
|
def drop
|
25
|
-
establish_connection
|
26
|
-
connection.drop_database
|
26
|
+
establish_connection(db_config)
|
27
|
+
connection.drop_database(db_config.database)
|
27
28
|
end
|
28
29
|
|
29
30
|
def purge
|
30
|
-
establish_connection
|
31
|
-
connection.recreate_database
|
31
|
+
establish_connection(db_config)
|
32
|
+
connection.recreate_database(db_config.database, creation_options)
|
32
33
|
end
|
33
34
|
|
34
35
|
def charset
|
@@ -48,10 +49,10 @@ module ActiveRecord
|
|
48
49
|
|
49
50
|
ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
|
50
51
|
if ignore_tables.any?
|
51
|
-
args += ignore_tables.map { |table| "--ignore-table=#{
|
52
|
+
args += ignore_tables.map { |table| "--ignore-table=#{db_config.database}.#{table}" }
|
52
53
|
end
|
53
54
|
|
54
|
-
args.concat([
|
55
|
+
args.concat([db_config.database.to_s])
|
55
56
|
args.unshift(*extra_flags) if extra_flags
|
56
57
|
|
57
58
|
run_cmd("mysqldump", args, "dumping")
|
@@ -60,43 +61,40 @@ module ActiveRecord
|
|
60
61
|
def structure_load(filename, extra_flags)
|
61
62
|
args = prepare_command_options
|
62
63
|
args.concat(["--execute", %{SET FOREIGN_KEY_CHECKS = 0; SOURCE #{filename}; SET FOREIGN_KEY_CHECKS = 1}])
|
63
|
-
args.concat(["--database",
|
64
|
+
args.concat(["--database", db_config.database.to_s])
|
64
65
|
args.unshift(*extra_flags) if extra_flags
|
65
66
|
|
66
67
|
run_cmd("mysql", args, "loading")
|
67
68
|
end
|
68
69
|
|
69
70
|
private
|
71
|
+
attr_reader :db_config, :configuration_hash
|
70
72
|
|
71
|
-
def
|
72
|
-
|
73
|
-
end
|
74
|
-
|
75
|
-
def configuration_without_database
|
76
|
-
configuration.merge("database" => nil)
|
73
|
+
def configuration_hash_without_database
|
74
|
+
configuration_hash.merge(database: nil)
|
77
75
|
end
|
78
76
|
|
79
77
|
def creation_options
|
80
78
|
Hash.new.tap do |options|
|
81
|
-
options[:charset] =
|
82
|
-
options[:collation] =
|
79
|
+
options[:charset] = configuration_hash[:encoding] if configuration_hash.include?(:encoding)
|
80
|
+
options[:collation] = configuration_hash[:collation] if configuration_hash.include?(:collation)
|
83
81
|
end
|
84
82
|
end
|
85
83
|
|
86
84
|
def prepare_command_options
|
87
85
|
args = {
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
}.
|
86
|
+
host: "--host",
|
87
|
+
port: "--port",
|
88
|
+
socket: "--socket",
|
89
|
+
username: "--user",
|
90
|
+
password: "--password",
|
91
|
+
encoding: "--default-character-set",
|
92
|
+
sslca: "--ssl-ca",
|
93
|
+
sslcert: "--ssl-cert",
|
94
|
+
sslcapath: "--ssl-capath",
|
95
|
+
sslcipher: "--ssl-cipher",
|
96
|
+
sslkey: "--ssl-key"
|
97
|
+
}.filter_map { |opt, arg| "#{arg}=#{configuration_hash[opt]}" if configuration_hash[opt] }
|
100
98
|
|
101
99
|
args
|
102
100
|
end
|
@@ -106,7 +104,7 @@ module ActiveRecord
|
|
106
104
|
end
|
107
105
|
|
108
106
|
def run_cmd_error(cmd, args, action)
|
109
|
-
msg = "failed to execute: `#{cmd}`\n"
|
107
|
+
msg = +"failed to execute: `#{cmd}`\n"
|
110
108
|
msg << "Please check the output above for any errors and make sure that `#{cmd}` is installed in your PATH and has proper permissions.\n\n"
|
111
109
|
msg
|
112
110
|
end
|
@@ -6,32 +6,30 @@ module ActiveRecord
|
|
6
6
|
module Tasks # :nodoc:
|
7
7
|
class PostgreSQLDatabaseTasks # :nodoc:
|
8
8
|
DEFAULT_ENCODING = ENV["CHARSET"] || "utf8"
|
9
|
-
ON_ERROR_STOP_1 = "ON_ERROR_STOP=1"
|
10
|
-
SQL_COMMENT_BEGIN = "--"
|
9
|
+
ON_ERROR_STOP_1 = "ON_ERROR_STOP=1"
|
10
|
+
SQL_COMMENT_BEGIN = "--"
|
11
11
|
|
12
12
|
delegate :connection, :establish_connection, :clear_active_connections!,
|
13
13
|
to: ActiveRecord::Base
|
14
14
|
|
15
|
-
def
|
16
|
-
|
15
|
+
def self.using_database_configurations?
|
16
|
+
true
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(db_config)
|
20
|
+
@db_config = db_config
|
21
|
+
@configuration_hash = db_config.configuration_hash
|
17
22
|
end
|
18
23
|
|
19
24
|
def create(master_established = false)
|
20
25
|
establish_master_connection unless master_established
|
21
|
-
connection.create_database
|
22
|
-
|
23
|
-
establish_connection configuration
|
24
|
-
rescue ActiveRecord::StatementInvalid => error
|
25
|
-
if error.cause.is_a?(PG::DuplicateDatabase)
|
26
|
-
raise DatabaseAlreadyExists
|
27
|
-
else
|
28
|
-
raise
|
29
|
-
end
|
26
|
+
connection.create_database(db_config.database, configuration_hash.merge(encoding: encoding))
|
27
|
+
establish_connection(db_config)
|
30
28
|
end
|
31
29
|
|
32
30
|
def drop
|
33
31
|
establish_master_connection
|
34
|
-
connection.drop_database
|
32
|
+
connection.drop_database(db_config.database)
|
35
33
|
end
|
36
34
|
|
37
35
|
def charset
|
@@ -49,20 +47,22 @@ module ActiveRecord
|
|
49
47
|
end
|
50
48
|
|
51
49
|
def structure_dump(filename, extra_flags)
|
52
|
-
set_psql_env
|
53
|
-
|
54
50
|
search_path = \
|
55
|
-
case ActiveRecord
|
51
|
+
case ActiveRecord.dump_schemas
|
56
52
|
when :schema_search_path
|
57
|
-
|
53
|
+
configuration_hash[:schema_search_path]
|
58
54
|
when :all
|
59
55
|
nil
|
60
56
|
when String
|
61
|
-
ActiveRecord
|
57
|
+
ActiveRecord.dump_schemas
|
62
58
|
end
|
63
59
|
|
64
|
-
args = ["-
|
60
|
+
args = ["--schema-only", "--no-privileges", "--no-owner"]
|
61
|
+
args << "--no-comments" if connection.database_version >= 110_000
|
62
|
+
args.concat(["--file", filename])
|
63
|
+
|
65
64
|
args.concat(Array(extra_flags)) if extra_flags
|
65
|
+
|
66
66
|
unless search_path.blank?
|
67
67
|
args += search_path.split(",").map do |part|
|
68
68
|
"--schema=#{part.strip}"
|
@@ -74,50 +74,52 @@ module ActiveRecord
|
|
74
74
|
args += ignore_tables.flat_map { |table| ["-T", table] }
|
75
75
|
end
|
76
76
|
|
77
|
-
args <<
|
77
|
+
args << db_config.database
|
78
78
|
run_cmd("pg_dump", args, "dumping")
|
79
79
|
remove_sql_header_comments(filename)
|
80
80
|
File.open(filename, "a") { |f| f << "SET search_path TO #{connection.schema_search_path};\n\n" }
|
81
81
|
end
|
82
82
|
|
83
83
|
def structure_load(filename, extra_flags)
|
84
|
-
|
85
|
-
args = ["-v", ON_ERROR_STOP_1, "-q", "-f", filename]
|
84
|
+
args = ["--set", ON_ERROR_STOP_1, "--quiet", "--no-psqlrc", "--file", filename]
|
86
85
|
args.concat(Array(extra_flags)) if extra_flags
|
87
|
-
args <<
|
86
|
+
args << db_config.database
|
88
87
|
run_cmd("psql", args, "loading")
|
89
88
|
end
|
90
89
|
|
91
90
|
private
|
92
|
-
|
93
|
-
def configuration
|
94
|
-
@configuration
|
95
|
-
end
|
91
|
+
attr_reader :db_config, :configuration_hash
|
96
92
|
|
97
93
|
def encoding
|
98
|
-
|
94
|
+
configuration_hash[:encoding] || DEFAULT_ENCODING
|
99
95
|
end
|
100
96
|
|
101
97
|
def establish_master_connection
|
102
|
-
establish_connection
|
103
|
-
|
104
|
-
|
98
|
+
establish_connection configuration_hash.merge(
|
99
|
+
database: "postgres",
|
100
|
+
schema_search_path: "public"
|
105
101
|
)
|
106
102
|
end
|
107
103
|
|
108
|
-
def
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
104
|
+
def psql_env
|
105
|
+
{}.tap do |env|
|
106
|
+
env["PGHOST"] = db_config.host if db_config.host
|
107
|
+
env["PGPORT"] = configuration_hash[:port].to_s if configuration_hash[:port]
|
108
|
+
env["PGPASSWORD"] = configuration_hash[:password].to_s if configuration_hash[:password]
|
109
|
+
env["PGUSER"] = configuration_hash[:username].to_s if configuration_hash[:username]
|
110
|
+
env["PGSSLMODE"] = configuration_hash[:sslmode].to_s if configuration_hash[:sslmode]
|
111
|
+
env["PGSSLCERT"] = configuration_hash[:sslcert].to_s if configuration_hash[:sslcert]
|
112
|
+
env["PGSSLKEY"] = configuration_hash[:sslkey].to_s if configuration_hash[:sslkey]
|
113
|
+
env["PGSSLROOTCERT"] = configuration_hash[:sslrootcert].to_s if configuration_hash[:sslrootcert]
|
114
|
+
end
|
113
115
|
end
|
114
116
|
|
115
117
|
def run_cmd(cmd, args, action)
|
116
|
-
fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args)
|
118
|
+
fail run_cmd_error(cmd, args, action) unless Kernel.system(psql_env, cmd, *args)
|
117
119
|
end
|
118
120
|
|
119
121
|
def run_cmd_error(cmd, args, action)
|
120
|
-
msg = "failed to execute:\n"
|
122
|
+
msg = +"failed to execute:\n"
|
121
123
|
msg << "#{cmd} #{args.join(' ')}\n\n"
|
122
124
|
msg << "Please check the output above for any errors and make sure that `#{cmd}` is installed in your PATH and has proper permissions.\n\n"
|
123
125
|
msg
|
@@ -5,20 +5,25 @@ module ActiveRecord
|
|
5
5
|
class SQLiteDatabaseTasks # :nodoc:
|
6
6
|
delegate :connection, :establish_connection, to: ActiveRecord::Base
|
7
7
|
|
8
|
-
def
|
9
|
-
|
8
|
+
def self.using_database_configurations?
|
9
|
+
true
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(db_config, root = ActiveRecord::Tasks::DatabaseTasks.root)
|
13
|
+
@db_config = db_config
|
14
|
+
@root = root
|
10
15
|
end
|
11
16
|
|
12
17
|
def create
|
13
|
-
raise DatabaseAlreadyExists if File.exist?(
|
18
|
+
raise DatabaseAlreadyExists if File.exist?(db_config.database)
|
14
19
|
|
15
|
-
establish_connection
|
20
|
+
establish_connection(db_config)
|
16
21
|
connection
|
17
22
|
end
|
18
23
|
|
19
24
|
def drop
|
20
25
|
require "pathname"
|
21
|
-
path = Pathname.new
|
26
|
+
path = Pathname.new(db_config.database)
|
22
27
|
file = path.absolute? ? path.to_s : File.join(root, path)
|
23
28
|
|
24
29
|
FileUtils.rm(file)
|
@@ -40,7 +45,7 @@ module ActiveRecord
|
|
40
45
|
def structure_dump(filename, extra_flags)
|
41
46
|
args = []
|
42
47
|
args.concat(Array(extra_flags)) if extra_flags
|
43
|
-
args <<
|
48
|
+
args << db_config.database
|
44
49
|
|
45
50
|
ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
|
46
51
|
if ignore_tables.any?
|
@@ -53,27 +58,19 @@ module ActiveRecord
|
|
53
58
|
end
|
54
59
|
|
55
60
|
def structure_load(filename, extra_flags)
|
56
|
-
dbfile = configuration["database"]
|
57
61
|
flags = extra_flags.join(" ") if extra_flags
|
58
|
-
`sqlite3 #{flags} #{
|
62
|
+
`sqlite3 #{flags} #{db_config.database} < "#{filename}"`
|
59
63
|
end
|
60
64
|
|
61
65
|
private
|
62
|
-
|
63
|
-
def configuration
|
64
|
-
@configuration
|
65
|
-
end
|
66
|
-
|
67
|
-
def root
|
68
|
-
@root
|
69
|
-
end
|
66
|
+
attr_reader :db_config, :root
|
70
67
|
|
71
68
|
def run_cmd(cmd, args, out)
|
72
69
|
fail run_cmd_error(cmd, args) unless Kernel.system(cmd, *args, out: out)
|
73
70
|
end
|
74
71
|
|
75
72
|
def run_cmd_error(cmd, args)
|
76
|
-
msg = "failed to execute:\n"
|
73
|
+
msg = +"failed to execute:\n"
|
77
74
|
msg << "#{cmd} #{args.join(' ')}\n\n"
|
78
75
|
msg << "Please check the output above for any errors and make sure that `#{cmd}` is installed in your PATH and has proper permissions.\n\n"
|
79
76
|
msg
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/testing/parallelization"
|
4
|
+
|
5
|
+
module ActiveRecord
|
6
|
+
module TestDatabases # :nodoc:
|
7
|
+
ActiveSupport::Testing::Parallelization.after_fork_hook do |i|
|
8
|
+
create_and_load_schema(i, env_name: ActiveRecord::ConnectionHandling::DEFAULT_ENV.call)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.create_and_load_schema(i, env_name:)
|
12
|
+
old, ENV["VERBOSE"] = ENV["VERBOSE"], "false"
|
13
|
+
|
14
|
+
ActiveRecord::Base.configurations.configs_for(env_name: env_name).each do |db_config|
|
15
|
+
db_config._database = "#{db_config.database}-#{i}"
|
16
|
+
|
17
|
+
ActiveRecord::Tasks::DatabaseTasks.reconstruct_from_schema(db_config, ActiveRecord.schema_format, nil)
|
18
|
+
end
|
19
|
+
ensure
|
20
|
+
ActiveRecord::Base.establish_connection
|
21
|
+
ENV["VERBOSE"] = old
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,287 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/enumerable"
|
4
|
+
|
5
|
+
module ActiveRecord
|
6
|
+
module TestFixtures
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
def before_setup # :nodoc:
|
10
|
+
setup_fixtures
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
def after_teardown # :nodoc:
|
15
|
+
super
|
16
|
+
teardown_fixtures
|
17
|
+
end
|
18
|
+
|
19
|
+
included do
|
20
|
+
class_attribute :fixture_path, instance_writer: false
|
21
|
+
class_attribute :fixture_table_names, default: []
|
22
|
+
class_attribute :fixture_class_names, default: {}
|
23
|
+
class_attribute :use_transactional_tests, default: true
|
24
|
+
class_attribute :use_instantiated_fixtures, default: false # true, false, or :no_instances
|
25
|
+
class_attribute :pre_loaded_fixtures, default: false
|
26
|
+
class_attribute :lock_threads, default: true
|
27
|
+
end
|
28
|
+
|
29
|
+
module ClassMethods
|
30
|
+
# Sets the model class for a fixture when the class name cannot be inferred from the fixture name.
|
31
|
+
#
|
32
|
+
# Examples:
|
33
|
+
#
|
34
|
+
# set_fixture_class some_fixture: SomeModel,
|
35
|
+
# 'namespaced/fixture' => Another::Model
|
36
|
+
#
|
37
|
+
# The keys must be the fixture names, that coincide with the short paths to the fixture files.
|
38
|
+
def set_fixture_class(class_names = {})
|
39
|
+
self.fixture_class_names = fixture_class_names.merge(class_names.stringify_keys)
|
40
|
+
end
|
41
|
+
|
42
|
+
def fixtures(*fixture_set_names)
|
43
|
+
if fixture_set_names.first == :all
|
44
|
+
raise StandardError, "No fixture path found. Please set `#{self}.fixture_path`." if fixture_path.blank?
|
45
|
+
fixture_set_names = Dir[::File.join(fixture_path, "{**,*}/*.{yml}")].uniq
|
46
|
+
fixture_set_names.reject! { |f| f.start_with?(file_fixture_path.to_s) } if defined?(file_fixture_path) && file_fixture_path
|
47
|
+
fixture_set_names.map! { |f| f[fixture_path.to_s.size..-5].delete_prefix("/") }
|
48
|
+
else
|
49
|
+
fixture_set_names = fixture_set_names.flatten.map(&:to_s)
|
50
|
+
end
|
51
|
+
|
52
|
+
self.fixture_table_names |= fixture_set_names
|
53
|
+
setup_fixture_accessors(fixture_set_names)
|
54
|
+
end
|
55
|
+
|
56
|
+
def setup_fixture_accessors(fixture_set_names = nil)
|
57
|
+
fixture_set_names = Array(fixture_set_names || fixture_table_names)
|
58
|
+
methods = Module.new do
|
59
|
+
fixture_set_names.each do |fs_name|
|
60
|
+
fs_name = fs_name.to_s
|
61
|
+
accessor_name = fs_name.tr("/", "_").to_sym
|
62
|
+
|
63
|
+
define_method(accessor_name) do |*fixture_names|
|
64
|
+
force_reload = fixture_names.pop if fixture_names.last == true || fixture_names.last == :reload
|
65
|
+
return_single_record = fixture_names.size == 1
|
66
|
+
fixture_names = @loaded_fixtures[fs_name].fixtures.keys if fixture_names.empty?
|
67
|
+
|
68
|
+
@fixture_cache[fs_name] ||= {}
|
69
|
+
|
70
|
+
instances = fixture_names.map do |f_name|
|
71
|
+
f_name = f_name.to_s if f_name.is_a?(Symbol)
|
72
|
+
@fixture_cache[fs_name].delete(f_name) if force_reload
|
73
|
+
|
74
|
+
if @loaded_fixtures[fs_name][f_name]
|
75
|
+
@fixture_cache[fs_name][f_name] ||= @loaded_fixtures[fs_name][f_name].find
|
76
|
+
else
|
77
|
+
raise StandardError, "No fixture named '#{f_name}' found for fixture set '#{fs_name}'"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
return_single_record ? instances.first : instances
|
82
|
+
end
|
83
|
+
private accessor_name
|
84
|
+
end
|
85
|
+
end
|
86
|
+
include methods
|
87
|
+
end
|
88
|
+
|
89
|
+
def uses_transaction(*methods)
|
90
|
+
@uses_transaction = [] unless defined?(@uses_transaction)
|
91
|
+
@uses_transaction.concat methods.map(&:to_s)
|
92
|
+
end
|
93
|
+
|
94
|
+
def uses_transaction?(method)
|
95
|
+
@uses_transaction = [] unless defined?(@uses_transaction)
|
96
|
+
@uses_transaction.include?(method.to_s)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def run_in_transaction?
|
101
|
+
use_transactional_tests &&
|
102
|
+
!self.class.uses_transaction?(name)
|
103
|
+
end
|
104
|
+
|
105
|
+
def setup_fixtures(config = ActiveRecord::Base)
|
106
|
+
if pre_loaded_fixtures && !use_transactional_tests
|
107
|
+
raise RuntimeError, "pre_loaded_fixtures requires use_transactional_tests"
|
108
|
+
end
|
109
|
+
|
110
|
+
@fixture_cache = {}
|
111
|
+
@fixture_connections = []
|
112
|
+
@@already_loaded_fixtures ||= {}
|
113
|
+
@connection_subscriber = nil
|
114
|
+
@legacy_saved_pool_configs = Hash.new { |hash, key| hash[key] = {} }
|
115
|
+
@saved_pool_configs = Hash.new { |hash, key| hash[key] = {} }
|
116
|
+
|
117
|
+
# Load fixtures once and begin transaction.
|
118
|
+
if run_in_transaction?
|
119
|
+
if @@already_loaded_fixtures[self.class]
|
120
|
+
@loaded_fixtures = @@already_loaded_fixtures[self.class]
|
121
|
+
else
|
122
|
+
@loaded_fixtures = load_fixtures(config)
|
123
|
+
@@already_loaded_fixtures[self.class] = @loaded_fixtures
|
124
|
+
end
|
125
|
+
|
126
|
+
# Begin transactions for connections already established
|
127
|
+
@fixture_connections = enlist_fixture_connections
|
128
|
+
@fixture_connections.each do |connection|
|
129
|
+
connection.begin_transaction joinable: false, _lazy: false
|
130
|
+
connection.pool.lock_thread = true if lock_threads
|
131
|
+
end
|
132
|
+
|
133
|
+
# When connections are established in the future, begin a transaction too
|
134
|
+
@connection_subscriber = ActiveSupport::Notifications.subscribe("!connection.active_record") do |_, _, _, _, payload|
|
135
|
+
spec_name = payload[:spec_name] if payload.key?(:spec_name)
|
136
|
+
shard = payload[:shard] if payload.key?(:shard)
|
137
|
+
setup_shared_connection_pool
|
138
|
+
|
139
|
+
if spec_name
|
140
|
+
begin
|
141
|
+
connection = ActiveRecord::Base.connection_handler.retrieve_connection(spec_name, shard: shard)
|
142
|
+
rescue ConnectionNotEstablished
|
143
|
+
connection = nil
|
144
|
+
end
|
145
|
+
|
146
|
+
if connection && !@fixture_connections.include?(connection)
|
147
|
+
connection.begin_transaction joinable: false, _lazy: false
|
148
|
+
connection.pool.lock_thread = true if lock_threads
|
149
|
+
@fixture_connections << connection
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
# Load fixtures for every test.
|
155
|
+
else
|
156
|
+
ActiveRecord::FixtureSet.reset_cache
|
157
|
+
@@already_loaded_fixtures[self.class] = nil
|
158
|
+
@loaded_fixtures = load_fixtures(config)
|
159
|
+
end
|
160
|
+
|
161
|
+
# Instantiate fixtures for every test if requested.
|
162
|
+
instantiate_fixtures if use_instantiated_fixtures
|
163
|
+
end
|
164
|
+
|
165
|
+
def teardown_fixtures
|
166
|
+
# Rollback changes if a transaction is active.
|
167
|
+
if run_in_transaction?
|
168
|
+
ActiveSupport::Notifications.unsubscribe(@connection_subscriber) if @connection_subscriber
|
169
|
+
@fixture_connections.each do |connection|
|
170
|
+
connection.rollback_transaction if connection.transaction_open?
|
171
|
+
connection.pool.lock_thread = false
|
172
|
+
end
|
173
|
+
@fixture_connections.clear
|
174
|
+
teardown_shared_connection_pool
|
175
|
+
else
|
176
|
+
ActiveRecord::FixtureSet.reset_cache
|
177
|
+
end
|
178
|
+
|
179
|
+
ActiveRecord::Base.clear_active_connections!
|
180
|
+
end
|
181
|
+
|
182
|
+
def enlist_fixture_connections
|
183
|
+
setup_shared_connection_pool
|
184
|
+
|
185
|
+
ActiveRecord::Base.connection_handler.connection_pool_list.map(&:connection)
|
186
|
+
end
|
187
|
+
|
188
|
+
private
|
189
|
+
# Shares the writing connection pool with connections on
|
190
|
+
# other handlers.
|
191
|
+
#
|
192
|
+
# In an application with a primary and replica the test fixtures
|
193
|
+
# need to share a connection pool so that the reading connection
|
194
|
+
# can see data in the open transaction on the writing connection.
|
195
|
+
def setup_shared_connection_pool
|
196
|
+
if ActiveRecord.legacy_connection_handling
|
197
|
+
writing_handler = ActiveRecord::Base.connection_handlers[ActiveRecord.writing_role]
|
198
|
+
|
199
|
+
ActiveRecord::Base.connection_handlers.values.each do |handler|
|
200
|
+
if handler != writing_handler
|
201
|
+
handler.connection_pool_names.each do |name|
|
202
|
+
writing_pool_manager = writing_handler.send(:owner_to_pool_manager)[name]
|
203
|
+
return unless writing_pool_manager
|
204
|
+
|
205
|
+
pool_manager = handler.send(:owner_to_pool_manager)[name]
|
206
|
+
@legacy_saved_pool_configs[handler][name] ||= {}
|
207
|
+
pool_manager.shard_names.each do |shard_name|
|
208
|
+
writing_pool_config = writing_pool_manager.get_pool_config(nil, shard_name)
|
209
|
+
pool_config = pool_manager.get_pool_config(nil, shard_name)
|
210
|
+
next if pool_config == writing_pool_config
|
211
|
+
|
212
|
+
@legacy_saved_pool_configs[handler][name][shard_name] = pool_config
|
213
|
+
pool_manager.set_pool_config(nil, shard_name, writing_pool_config)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
else
|
219
|
+
handler = ActiveRecord::Base.connection_handler
|
220
|
+
|
221
|
+
handler.connection_pool_names.each do |name|
|
222
|
+
pool_manager = handler.send(:owner_to_pool_manager)[name]
|
223
|
+
pool_manager.shard_names.each do |shard_name|
|
224
|
+
writing_pool_config = pool_manager.get_pool_config(ActiveRecord.writing_role, shard_name)
|
225
|
+
@saved_pool_configs[name][shard_name] ||= {}
|
226
|
+
pool_manager.role_names.each do |role|
|
227
|
+
next unless pool_config = pool_manager.get_pool_config(role, shard_name)
|
228
|
+
next if pool_config == writing_pool_config
|
229
|
+
|
230
|
+
@saved_pool_configs[name][shard_name][role] = pool_config
|
231
|
+
pool_manager.set_pool_config(role, shard_name, writing_pool_config)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
def teardown_shared_connection_pool
|
239
|
+
if ActiveRecord.legacy_connection_handling
|
240
|
+
@legacy_saved_pool_configs.each_pair do |handler, names|
|
241
|
+
names.each_pair do |name, shards|
|
242
|
+
shards.each_pair do |shard_name, pool_config|
|
243
|
+
pool_manager = handler.send(:owner_to_pool_manager)[name]
|
244
|
+
pool_manager.set_pool_config(nil, shard_name, pool_config)
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
else
|
249
|
+
handler = ActiveRecord::Base.connection_handler
|
250
|
+
|
251
|
+
@saved_pool_configs.each_pair do |name, shards|
|
252
|
+
pool_manager = handler.send(:owner_to_pool_manager)[name]
|
253
|
+
shards.each_pair do |shard_name, roles|
|
254
|
+
roles.each_pair do |role, pool_config|
|
255
|
+
next unless pool_manager.get_pool_config(role, shard_name)
|
256
|
+
|
257
|
+
pool_manager.set_pool_config(role, shard_name, pool_config)
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
@legacy_saved_pool_configs.clear
|
264
|
+
@saved_pool_configs.clear
|
265
|
+
end
|
266
|
+
|
267
|
+
def load_fixtures(config)
|
268
|
+
ActiveRecord::FixtureSet.create_fixtures(fixture_path, fixture_table_names, fixture_class_names, config).index_by(&:name)
|
269
|
+
end
|
270
|
+
|
271
|
+
def instantiate_fixtures
|
272
|
+
if pre_loaded_fixtures
|
273
|
+
raise RuntimeError, "Load fixtures before instantiating them." if ActiveRecord::FixtureSet.all_loaded_fixtures.empty?
|
274
|
+
ActiveRecord::FixtureSet.instantiate_all_loaded_fixtures(self, load_instances?)
|
275
|
+
else
|
276
|
+
raise RuntimeError, "Load fixtures before instantiating them." if @loaded_fixtures.nil?
|
277
|
+
@loaded_fixtures.each_value do |fixture_set|
|
278
|
+
ActiveRecord::FixtureSet.instantiate_fixtures(self, fixture_set, load_instances?)
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
def load_instances?
|
284
|
+
use_instantiated_fixtures != :no_instances
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|