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
@@ -7,10 +7,12 @@ require "set"
|
|
7
7
|
require "active_support/dependencies"
|
8
8
|
require "active_support/core_ext/digest/uuid"
|
9
9
|
require "active_record/fixture_set/file"
|
10
|
-
require "active_record/
|
10
|
+
require "active_record/fixture_set/render_context"
|
11
|
+
require "active_record/fixture_set/table_rows"
|
12
|
+
require "active_record/test_fixtures"
|
11
13
|
|
12
14
|
module ActiveRecord
|
13
|
-
class FixtureClassNotFound < ActiveRecord::ActiveRecordError
|
15
|
+
class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc:
|
14
16
|
end
|
15
17
|
|
16
18
|
# \Fixtures are a way of organizing data that you want to test against; in short, sample data.
|
@@ -33,12 +35,12 @@ module ActiveRecord
|
|
33
35
|
# name: Google
|
34
36
|
# url: http://www.google.com
|
35
37
|
#
|
36
|
-
# This fixture file includes two fixtures. Each YAML fixture (
|
38
|
+
# This fixture file includes two fixtures. Each YAML fixture (i.e. record) is given a name and
|
37
39
|
# is followed by an indented list of key/value pairs in the "key: value" format. Records are
|
38
40
|
# separated by a blank line for your viewing pleasure.
|
39
41
|
#
|
40
42
|
# Note: Fixtures are unordered. If you want ordered fixtures, use the omap YAML type.
|
41
|
-
# See
|
43
|
+
# See https://yaml.org/type/omap.html
|
42
44
|
# for the specification. You will need ordered fixtures when you have foreign key constraints
|
43
45
|
# on keys in the same table. This is commonly needed for tree structures. Example:
|
44
46
|
#
|
@@ -57,7 +59,7 @@ module ActiveRecord
|
|
57
59
|
# Since fixtures are a testing construct, we use them in our unit and functional tests. There
|
58
60
|
# are two ways to use the fixtures, but first let's take a look at a sample unit test:
|
59
61
|
#
|
60
|
-
# require
|
62
|
+
# require "test_helper"
|
61
63
|
#
|
62
64
|
# class WebSiteTest < ActiveSupport::TestCase
|
63
65
|
# test "web_site_count" do
|
@@ -150,7 +152,7 @@ module ActiveRecord
|
|
150
152
|
# - define a helper method in <tt>test_helper.rb</tt>
|
151
153
|
# module FixtureFileHelpers
|
152
154
|
# def file_sha(path)
|
153
|
-
# Digest::
|
155
|
+
# OpenSSL::Digest::SHA256.hexdigest(File.read(Rails.root.join('test/fixtures', path)))
|
154
156
|
# end
|
155
157
|
# end
|
156
158
|
# ActiveRecord::FixtureSet.context_class.include FixtureFileHelpers
|
@@ -179,8 +181,8 @@ module ActiveRecord
|
|
179
181
|
# end
|
180
182
|
# end
|
181
183
|
#
|
182
|
-
# If you preload your test database with all fixture data (probably
|
183
|
-
# transactional tests, then you may omit all fixtures declarations in your test cases since
|
184
|
+
# If you preload your test database with all fixture data (probably by running <tt>bin/rails db:fixtures:load</tt>)
|
185
|
+
# and use transactional tests, then you may omit all fixtures declarations in your test cases since
|
184
186
|
# all the data's already there and every case rolls back its changes.
|
185
187
|
#
|
186
188
|
# In order to use instantiated fixtures with preloaded data, set +self.pre_loaded_fixtures+ to
|
@@ -309,7 +311,7 @@ module ActiveRecord
|
|
309
311
|
#
|
310
312
|
# Just provide the polymorphic target type and Active Record will take care of the rest.
|
311
313
|
#
|
312
|
-
# === has_and_belongs_to_many
|
314
|
+
# === has_and_belongs_to_many or has_many :through
|
313
315
|
#
|
314
316
|
# Time to give our monkey some fruit.
|
315
317
|
#
|
@@ -405,7 +407,7 @@ module ActiveRecord
|
|
405
407
|
# defaults:
|
406
408
|
#
|
407
409
|
# DEFAULTS: &DEFAULTS
|
408
|
-
# created_on: <%= 3.weeks.ago.
|
410
|
+
# created_on: <%= 3.weeks.ago.to_fs(:db) %>
|
409
411
|
#
|
410
412
|
# first:
|
411
413
|
# name: Smurf
|
@@ -417,12 +419,35 @@ module ActiveRecord
|
|
417
419
|
#
|
418
420
|
# Any fixture labeled "DEFAULTS" is safely ignored.
|
419
421
|
#
|
422
|
+
# Besides using "DEFAULTS", you can also specify what fixtures will
|
423
|
+
# be ignored by setting "ignore" in "_fixture" section.
|
424
|
+
#
|
425
|
+
# # users.yml
|
426
|
+
# _fixture:
|
427
|
+
# ignore:
|
428
|
+
# - base
|
429
|
+
# # or use "ignore: base" when there is only one fixture that needs to be ignored.
|
430
|
+
#
|
431
|
+
# base: &base
|
432
|
+
# admin: false
|
433
|
+
# introduction: "This is a default description"
|
434
|
+
#
|
435
|
+
# admin:
|
436
|
+
# <<: *base
|
437
|
+
# admin: true
|
438
|
+
#
|
439
|
+
# visitor:
|
440
|
+
# <<: *base
|
441
|
+
#
|
442
|
+
# In the above example, 'base' will be ignored when creating fixtures.
|
443
|
+
# This can be used for common attributes inheriting.
|
444
|
+
#
|
420
445
|
# == Configure the fixture model class
|
421
446
|
#
|
422
447
|
# It's possible to set the fixture's model class directly in the YAML file.
|
423
448
|
# This is helpful when fixtures are loaded outside tests and
|
424
449
|
# +set_fixture_class+ is not available (e.g.
|
425
|
-
# when running <tt>rails db:fixtures:load</tt>).
|
450
|
+
# when running <tt>bin/rails db:fixtures:load</tt>).
|
426
451
|
#
|
427
452
|
# _fixture:
|
428
453
|
# model_class: User
|
@@ -440,60 +465,6 @@ module ActiveRecord
|
|
440
465
|
|
441
466
|
@@all_cached_fixtures = Hash.new { |h, k| h[k] = {} }
|
442
467
|
|
443
|
-
def self.default_fixture_model_name(fixture_set_name, config = ActiveRecord::Base) # :nodoc:
|
444
|
-
config.pluralize_table_names ?
|
445
|
-
fixture_set_name.singularize.camelize :
|
446
|
-
fixture_set_name.camelize
|
447
|
-
end
|
448
|
-
|
449
|
-
def self.default_fixture_table_name(fixture_set_name, config = ActiveRecord::Base) # :nodoc:
|
450
|
-
"#{ config.table_name_prefix }"\
|
451
|
-
"#{ fixture_set_name.tr('/', '_') }"\
|
452
|
-
"#{ config.table_name_suffix }".to_sym
|
453
|
-
end
|
454
|
-
|
455
|
-
def self.reset_cache
|
456
|
-
@@all_cached_fixtures.clear
|
457
|
-
end
|
458
|
-
|
459
|
-
def self.cache_for_connection(connection)
|
460
|
-
@@all_cached_fixtures[connection]
|
461
|
-
end
|
462
|
-
|
463
|
-
def self.fixture_is_cached?(connection, table_name)
|
464
|
-
cache_for_connection(connection)[table_name]
|
465
|
-
end
|
466
|
-
|
467
|
-
def self.cached_fixtures(connection, keys_to_fetch = nil)
|
468
|
-
if keys_to_fetch
|
469
|
-
cache_for_connection(connection).values_at(*keys_to_fetch)
|
470
|
-
else
|
471
|
-
cache_for_connection(connection).values
|
472
|
-
end
|
473
|
-
end
|
474
|
-
|
475
|
-
def self.cache_fixtures(connection, fixtures_map)
|
476
|
-
cache_for_connection(connection).update(fixtures_map)
|
477
|
-
end
|
478
|
-
|
479
|
-
def self.instantiate_fixtures(object, fixture_set, load_instances = true)
|
480
|
-
if load_instances
|
481
|
-
fixture_set.each do |fixture_name, fixture|
|
482
|
-
begin
|
483
|
-
object.instance_variable_set "@#{fixture_name}", fixture.find
|
484
|
-
rescue FixtureClassNotFound
|
485
|
-
nil
|
486
|
-
end
|
487
|
-
end
|
488
|
-
end
|
489
|
-
end
|
490
|
-
|
491
|
-
def self.instantiate_all_loaded_fixtures(object, load_instances = true)
|
492
|
-
all_loaded_fixtures.each_value do |fixture_set|
|
493
|
-
instantiate_fixtures(object, fixture_set, load_instances)
|
494
|
-
end
|
495
|
-
end
|
496
|
-
|
497
468
|
cattr_accessor :all_loaded_fixtures, default: {}
|
498
469
|
|
499
470
|
class ClassCache
|
@@ -502,18 +473,19 @@ module ActiveRecord
|
|
502
473
|
@config = config
|
503
474
|
|
504
475
|
# Remove string values that aren't constants or subclasses of AR
|
505
|
-
@class_names.delete_if
|
476
|
+
@class_names.delete_if do |klass_name, klass|
|
477
|
+
!insert_class(@class_names, klass_name, klass)
|
478
|
+
end
|
506
479
|
end
|
507
480
|
|
508
481
|
def [](fs_name)
|
509
|
-
@class_names.fetch(fs_name)
|
482
|
+
@class_names.fetch(fs_name) do
|
510
483
|
klass = default_fixture_model(fs_name, @config).safe_constantize
|
511
484
|
insert_class(@class_names, fs_name, klass)
|
512
|
-
|
485
|
+
end
|
513
486
|
end
|
514
487
|
|
515
488
|
private
|
516
|
-
|
517
489
|
def insert_class(class_names, name, klass)
|
518
490
|
# We only want to deal with AR objects.
|
519
491
|
if klass && klass < ActiveRecord::Base
|
@@ -528,76 +500,154 @@ module ActiveRecord
|
|
528
500
|
end
|
529
501
|
end
|
530
502
|
|
531
|
-
|
532
|
-
|
533
|
-
|
503
|
+
class << self
|
504
|
+
def default_fixture_model_name(fixture_set_name, config = ActiveRecord::Base) # :nodoc:
|
505
|
+
config.pluralize_table_names ?
|
506
|
+
fixture_set_name.singularize.camelize :
|
507
|
+
fixture_set_name.camelize
|
508
|
+
end
|
509
|
+
|
510
|
+
def default_fixture_table_name(fixture_set_name, config = ActiveRecord::Base) # :nodoc:
|
511
|
+
"#{ config.table_name_prefix }"\
|
512
|
+
"#{ fixture_set_name.tr('/', '_') }"\
|
513
|
+
"#{ config.table_name_suffix }".to_sym
|
514
|
+
end
|
534
515
|
|
535
|
-
|
536
|
-
|
516
|
+
def reset_cache
|
517
|
+
@@all_cached_fixtures.clear
|
518
|
+
end
|
537
519
|
|
538
|
-
|
539
|
-
|
540
|
-
|
520
|
+
def cache_for_connection(connection)
|
521
|
+
@@all_cached_fixtures[connection]
|
522
|
+
end
|
541
523
|
|
542
|
-
|
543
|
-
|
524
|
+
def fixture_is_cached?(connection, table_name)
|
525
|
+
cache_for_connection(connection)[table_name]
|
526
|
+
end
|
544
527
|
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
fs_name,
|
551
|
-
klass,
|
552
|
-
::File.join(fixtures_directory, fs_name))
|
528
|
+
def cached_fixtures(connection, keys_to_fetch = nil)
|
529
|
+
if keys_to_fetch
|
530
|
+
cache_for_connection(connection).values_at(*keys_to_fetch)
|
531
|
+
else
|
532
|
+
cache_for_connection(connection).values
|
553
533
|
end
|
534
|
+
end
|
554
535
|
|
555
|
-
|
556
|
-
|
536
|
+
def cache_fixtures(connection, fixtures_map)
|
537
|
+
cache_for_connection(connection).update(fixtures_map)
|
538
|
+
end
|
557
539
|
|
558
|
-
|
559
|
-
|
540
|
+
def instantiate_fixtures(object, fixture_set, load_instances = true)
|
541
|
+
return unless load_instances
|
542
|
+
fixture_set.each do |fixture_name, fixture|
|
543
|
+
object.instance_variable_set "@#{fixture_name}", fixture.find
|
544
|
+
rescue FixtureClassNotFound
|
545
|
+
nil
|
546
|
+
end
|
547
|
+
end
|
560
548
|
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
conn.insert_fixtures_set(table_rows_for_connection, table_rows_for_connection.keys)
|
549
|
+
def instantiate_all_loaded_fixtures(object, load_instances = true)
|
550
|
+
all_loaded_fixtures.each_value do |fixture_set|
|
551
|
+
instantiate_fixtures(object, fixture_set, load_instances)
|
552
|
+
end
|
553
|
+
end
|
567
554
|
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
555
|
+
def create_fixtures(fixtures_directory, fixture_set_names, class_names = {}, config = ActiveRecord::Base, &block)
|
556
|
+
fixture_set_names = Array(fixture_set_names).map(&:to_s)
|
557
|
+
class_names = ClassCache.new class_names, config
|
558
|
+
|
559
|
+
# FIXME: Apparently JK uses this.
|
560
|
+
connection = block_given? ? block : lambda { ActiveRecord::Base.connection }
|
561
|
+
|
562
|
+
fixture_files_to_read = fixture_set_names.reject do |fs_name|
|
563
|
+
fixture_is_cached?(connection.call, fs_name)
|
572
564
|
end
|
573
565
|
|
574
|
-
|
566
|
+
if fixture_files_to_read.any?
|
567
|
+
fixtures_map = read_and_insert(
|
568
|
+
fixtures_directory,
|
569
|
+
fixture_files_to_read,
|
570
|
+
class_names,
|
571
|
+
connection,
|
572
|
+
)
|
573
|
+
cache_fixtures(connection.call, fixtures_map)
|
574
|
+
end
|
575
|
+
cached_fixtures(connection.call, fixture_set_names)
|
575
576
|
end
|
576
|
-
cached_fixtures(connection, fixture_set_names)
|
577
|
-
end
|
578
577
|
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
578
|
+
# Returns a consistent, platform-independent identifier for +label+.
|
579
|
+
# Integer identifiers are values less than 2^30. UUIDs are RFC 4122 version 5 SHA-1 hashes.
|
580
|
+
def identify(label, column_type = :integer)
|
581
|
+
if column_type == :uuid
|
582
|
+
Digest::UUID.uuid_v5(Digest::UUID::OID_NAMESPACE, label.to_s)
|
583
|
+
else
|
584
|
+
Zlib.crc32(label.to_s) % MAX_ID
|
585
|
+
end
|
586
586
|
end
|
587
|
-
end
|
588
587
|
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
588
|
+
# Superclass for the evaluation contexts used by ERB fixtures.
|
589
|
+
def context_class
|
590
|
+
@context_class ||= Class.new
|
591
|
+
end
|
592
|
+
|
593
|
+
private
|
594
|
+
def read_and_insert(fixtures_directory, fixture_files, class_names, connection) # :nodoc:
|
595
|
+
fixtures_map = {}
|
596
|
+
fixture_sets = fixture_files.map do |fixture_set_name|
|
597
|
+
klass = class_names[fixture_set_name]
|
598
|
+
fixtures_map[fixture_set_name] = new( # ActiveRecord::FixtureSet.new
|
599
|
+
nil,
|
600
|
+
fixture_set_name,
|
601
|
+
klass,
|
602
|
+
::File.join(fixtures_directory, fixture_set_name)
|
603
|
+
)
|
604
|
+
end
|
605
|
+
update_all_loaded_fixtures(fixtures_map)
|
606
|
+
|
607
|
+
insert(fixture_sets, connection)
|
608
|
+
|
609
|
+
fixtures_map
|
610
|
+
end
|
611
|
+
|
612
|
+
def insert(fixture_sets, connection) # :nodoc:
|
613
|
+
fixture_sets_by_connection = fixture_sets.group_by do |fixture_set|
|
614
|
+
if fixture_set.model_class
|
615
|
+
fixture_set.model_class.connection
|
616
|
+
else
|
617
|
+
connection.call
|
618
|
+
end
|
619
|
+
end
|
620
|
+
|
621
|
+
fixture_sets_by_connection.each do |conn, set|
|
622
|
+
table_rows_for_connection = Hash.new { |h, k| h[k] = [] }
|
623
|
+
|
624
|
+
set.each do |fixture_set|
|
625
|
+
fixture_set.table_rows.each do |table, rows|
|
626
|
+
table_rows_for_connection[table].unshift(*rows)
|
627
|
+
end
|
628
|
+
end
|
629
|
+
|
630
|
+
conn.insert_fixtures_set(table_rows_for_connection, table_rows_for_connection.keys)
|
631
|
+
|
632
|
+
if ActiveRecord.verify_foreign_keys_for_fixtures && !conn.all_foreign_keys_valid?
|
633
|
+
raise "Foreign key violations found in your fixture data. Ensure you aren't referring to labels that don't exist on associations."
|
634
|
+
end
|
593
635
|
|
594
|
-
|
595
|
-
|
636
|
+
# Cap primary key sequences to max(pk).
|
637
|
+
if conn.respond_to?(:reset_pk_sequence!)
|
638
|
+
set.each { |fs| conn.reset_pk_sequence!(fs.table_name) }
|
639
|
+
end
|
640
|
+
end
|
641
|
+
end
|
642
|
+
|
643
|
+
def update_all_loaded_fixtures(fixtures_map) # :nodoc:
|
644
|
+
all_loaded_fixtures.update(fixtures_map)
|
645
|
+
end
|
596
646
|
end
|
597
647
|
|
598
|
-
attr_reader :table_name, :name, :fixtures, :model_class, :config
|
648
|
+
attr_reader :table_name, :name, :fixtures, :model_class, :ignored_fixtures, :config
|
599
649
|
|
600
|
-
def initialize(
|
650
|
+
def initialize(_, name, class_name, path, config = ActiveRecord::Base)
|
601
651
|
@name = name
|
602
652
|
@path = path
|
603
653
|
@config = config
|
@@ -606,11 +656,7 @@ module ActiveRecord
|
|
606
656
|
|
607
657
|
@fixtures = read_fixture_files(path)
|
608
658
|
|
609
|
-
@
|
610
|
-
|
611
|
-
@table_name = (model_class.respond_to?(:table_name) ?
|
612
|
-
model_class.table_name :
|
613
|
-
self.class.default_fixture_table_name(name, config))
|
659
|
+
@table_name = model_class&.table_name || self.class.default_fixture_table_name(name, config)
|
614
660
|
end
|
615
661
|
|
616
662
|
def [](x)
|
@@ -632,153 +678,17 @@ module ActiveRecord
|
|
632
678
|
# Returns a hash of rows to be inserted. The key is the table, the value is
|
633
679
|
# a list of rows to insert to that table.
|
634
680
|
def table_rows
|
635
|
-
|
681
|
+
# allow specifying fixtures to be ignored by setting `ignore` in `_fixture` section
|
682
|
+
fixtures.except!(*ignored_fixtures)
|
636
683
|
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
rows[table_name] = fixtures.map do |label, fixture|
|
644
|
-
row = fixture.to_hash
|
645
|
-
|
646
|
-
if model_class
|
647
|
-
# fill in timestamp columns if they aren't specified and the model is set to record_timestamps
|
648
|
-
if model_class.record_timestamps
|
649
|
-
timestamp_column_names.each do |c_name|
|
650
|
-
row[c_name] = now unless row.key?(c_name)
|
651
|
-
end
|
652
|
-
end
|
653
|
-
|
654
|
-
# interpolate the fixture label
|
655
|
-
row.each do |key, value|
|
656
|
-
row[key] = value.gsub("$LABEL", label.to_s) if value.is_a?(String)
|
657
|
-
end
|
658
|
-
|
659
|
-
# generate a primary key if necessary
|
660
|
-
if has_primary_key_column? && !row.include?(primary_key_name)
|
661
|
-
row[primary_key_name] = ActiveRecord::FixtureSet.identify(label, primary_key_type)
|
662
|
-
end
|
663
|
-
|
664
|
-
# Resolve enums
|
665
|
-
model_class.defined_enums.each do |name, values|
|
666
|
-
if row.include?(name)
|
667
|
-
row[name] = values.fetch(row[name], row[name])
|
668
|
-
end
|
669
|
-
end
|
670
|
-
|
671
|
-
# If STI is used, find the correct subclass for association reflection
|
672
|
-
reflection_class =
|
673
|
-
if row.include?(inheritance_column_name)
|
674
|
-
row[inheritance_column_name].constantize rescue model_class
|
675
|
-
else
|
676
|
-
model_class
|
677
|
-
end
|
678
|
-
|
679
|
-
reflection_class._reflections.each_value do |association|
|
680
|
-
case association.macro
|
681
|
-
when :belongs_to
|
682
|
-
# Do not replace association name with association foreign key if they are named the same
|
683
|
-
fk_name = (association.options[:foreign_key] || "#{association.name}_id").to_s
|
684
|
-
|
685
|
-
if association.name.to_s != fk_name && value = row.delete(association.name.to_s)
|
686
|
-
if association.polymorphic? && value.sub!(/\s*\(([^\)]*)\)\s*$/, "")
|
687
|
-
# support polymorphic belongs_to as "label (Type)"
|
688
|
-
row[association.foreign_type] = $1
|
689
|
-
end
|
690
|
-
|
691
|
-
fk_type = reflection_class.type_for_attribute(fk_name).type
|
692
|
-
row[fk_name] = ActiveRecord::FixtureSet.identify(value, fk_type)
|
693
|
-
end
|
694
|
-
when :has_many
|
695
|
-
if association.options[:through]
|
696
|
-
add_join_records(rows, row, HasManyThroughProxy.new(association))
|
697
|
-
end
|
698
|
-
end
|
699
|
-
end
|
700
|
-
end
|
701
|
-
|
702
|
-
row
|
703
|
-
end
|
704
|
-
rows
|
705
|
-
end
|
706
|
-
|
707
|
-
class ReflectionProxy # :nodoc:
|
708
|
-
def initialize(association)
|
709
|
-
@association = association
|
710
|
-
end
|
711
|
-
|
712
|
-
def join_table
|
713
|
-
@association.join_table
|
714
|
-
end
|
715
|
-
|
716
|
-
def name
|
717
|
-
@association.name
|
718
|
-
end
|
719
|
-
|
720
|
-
def primary_key_type
|
721
|
-
@association.klass.type_for_attribute(@association.klass.primary_key).type
|
722
|
-
end
|
723
|
-
end
|
724
|
-
|
725
|
-
class HasManyThroughProxy < ReflectionProxy # :nodoc:
|
726
|
-
def rhs_key
|
727
|
-
@association.foreign_key
|
728
|
-
end
|
729
|
-
|
730
|
-
def lhs_key
|
731
|
-
@association.through_reflection.foreign_key
|
732
|
-
end
|
733
|
-
|
734
|
-
def join_table
|
735
|
-
@association.through_reflection.table_name
|
736
|
-
end
|
684
|
+
TableRows.new(
|
685
|
+
table_name,
|
686
|
+
model_class: model_class,
|
687
|
+
fixtures: fixtures,
|
688
|
+
).to_hash
|
737
689
|
end
|
738
690
|
|
739
691
|
private
|
740
|
-
def primary_key_name
|
741
|
-
@primary_key_name ||= model_class && model_class.primary_key
|
742
|
-
end
|
743
|
-
|
744
|
-
def primary_key_type
|
745
|
-
@primary_key_type ||= model_class && model_class.type_for_attribute(model_class.primary_key).type
|
746
|
-
end
|
747
|
-
|
748
|
-
def add_join_records(rows, row, association)
|
749
|
-
# This is the case when the join table has no fixtures file
|
750
|
-
if (targets = row.delete(association.name.to_s))
|
751
|
-
table_name = association.join_table
|
752
|
-
column_type = association.primary_key_type
|
753
|
-
lhs_key = association.lhs_key
|
754
|
-
rhs_key = association.rhs_key
|
755
|
-
|
756
|
-
targets = targets.is_a?(Array) ? targets : targets.split(/\s*,\s*/)
|
757
|
-
rows[table_name].concat targets.map { |target|
|
758
|
-
{ lhs_key => row[primary_key_name],
|
759
|
-
rhs_key => ActiveRecord::FixtureSet.identify(target, column_type) }
|
760
|
-
}
|
761
|
-
end
|
762
|
-
end
|
763
|
-
|
764
|
-
def has_primary_key_column?
|
765
|
-
@has_primary_key_column ||= primary_key_name &&
|
766
|
-
model_class.columns.any? { |c| c.name == primary_key_name }
|
767
|
-
end
|
768
|
-
|
769
|
-
def timestamp_column_names
|
770
|
-
@timestamp_column_names ||=
|
771
|
-
%w(created_at created_on updated_at updated_on) & column_names
|
772
|
-
end
|
773
|
-
|
774
|
-
def inheritance_column_name
|
775
|
-
@inheritance_column_name ||= model_class && model_class.inheritance_column
|
776
|
-
end
|
777
|
-
|
778
|
-
def column_names
|
779
|
-
@column_names ||= @connection.columns(@table_name).collect(&:name)
|
780
|
-
end
|
781
|
-
|
782
692
|
def model_class=(class_name)
|
783
693
|
if class_name.is_a?(Class) # TODO: Should be an AR::Base type class, or any?
|
784
694
|
@model_class = class_name
|
@@ -787,6 +697,21 @@ module ActiveRecord
|
|
787
697
|
end
|
788
698
|
end
|
789
699
|
|
700
|
+
def ignored_fixtures=(base)
|
701
|
+
@ignored_fixtures =
|
702
|
+
case base
|
703
|
+
when Array
|
704
|
+
base
|
705
|
+
when String
|
706
|
+
[base]
|
707
|
+
else
|
708
|
+
[]
|
709
|
+
end
|
710
|
+
|
711
|
+
@ignored_fixtures << "DEFAULTS" unless @ignored_fixtures.include?("DEFAULTS")
|
712
|
+
@ignored_fixtures.compact
|
713
|
+
end
|
714
|
+
|
790
715
|
# Loads the fixtures from the YAML file at +path+.
|
791
716
|
# If the file sets the +model_class+ and current instance value is not set,
|
792
717
|
# it uses the file value.
|
@@ -798,6 +723,7 @@ module ActiveRecord
|
|
798
723
|
yaml_files.each_with_object({}) do |file, fixtures|
|
799
724
|
FixtureSet::File.open(file) do |fh|
|
800
725
|
self.model_class ||= fh.model_class if fh.model_class
|
726
|
+
self.ignored_fixtures ||= fh.ignored_fixtures
|
801
727
|
fh.each do |fixture_name, row|
|
802
728
|
fixtures[fixture_name] = ActiveRecord::Fixture.new(row, model_class)
|
803
729
|
end
|
@@ -810,13 +736,13 @@ module ActiveRecord
|
|
810
736
|
end
|
811
737
|
end
|
812
738
|
|
813
|
-
class Fixture
|
739
|
+
class Fixture # :nodoc:
|
814
740
|
include Enumerable
|
815
741
|
|
816
|
-
class FixtureError < StandardError
|
742
|
+
class FixtureError < StandardError # :nodoc:
|
817
743
|
end
|
818
744
|
|
819
|
-
class FormatError < FixtureError
|
745
|
+
class FormatError < FixtureError # :nodoc:
|
820
746
|
end
|
821
747
|
|
822
748
|
attr_reader :model_class, :fixture
|
@@ -830,8 +756,8 @@ module ActiveRecord
|
|
830
756
|
model_class.name if model_class
|
831
757
|
end
|
832
758
|
|
833
|
-
def each
|
834
|
-
fixture.each
|
759
|
+
def each(&block)
|
760
|
+
fixture.each(&block)
|
835
761
|
end
|
836
762
|
|
837
763
|
def [](key)
|
@@ -841,225 +767,15 @@ module ActiveRecord
|
|
841
767
|
alias :to_hash :fixture
|
842
768
|
|
843
769
|
def find
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
end
|
848
|
-
else
|
849
|
-
raise FixtureClassNotFound, "No class attached to find."
|
770
|
+
raise FixtureClassNotFound, "No class attached to find." unless model_class
|
771
|
+
object = model_class.unscoped do
|
772
|
+
model_class.find(fixture[model_class.primary_key])
|
850
773
|
end
|
774
|
+
# Fixtures can't be eagerly loaded
|
775
|
+
object.instance_variable_set(:@strict_loading, false)
|
776
|
+
object
|
851
777
|
end
|
852
778
|
end
|
853
779
|
end
|
854
780
|
|
855
|
-
|
856
|
-
module TestFixtures
|
857
|
-
extend ActiveSupport::Concern
|
858
|
-
|
859
|
-
def before_setup # :nodoc:
|
860
|
-
setup_fixtures
|
861
|
-
super
|
862
|
-
end
|
863
|
-
|
864
|
-
def after_teardown # :nodoc:
|
865
|
-
super
|
866
|
-
teardown_fixtures
|
867
|
-
end
|
868
|
-
|
869
|
-
included do
|
870
|
-
class_attribute :fixture_path, instance_writer: false
|
871
|
-
class_attribute :fixture_table_names, default: []
|
872
|
-
class_attribute :fixture_class_names, default: {}
|
873
|
-
class_attribute :use_transactional_tests, default: true
|
874
|
-
class_attribute :use_instantiated_fixtures, default: false # true, false, or :no_instances
|
875
|
-
class_attribute :pre_loaded_fixtures, default: false
|
876
|
-
class_attribute :config, default: ActiveRecord::Base
|
877
|
-
end
|
878
|
-
|
879
|
-
module ClassMethods
|
880
|
-
# Sets the model class for a fixture when the class name cannot be inferred from the fixture name.
|
881
|
-
#
|
882
|
-
# Examples:
|
883
|
-
#
|
884
|
-
# set_fixture_class some_fixture: SomeModel,
|
885
|
-
# 'namespaced/fixture' => Another::Model
|
886
|
-
#
|
887
|
-
# The keys must be the fixture names, that coincide with the short paths to the fixture files.
|
888
|
-
def set_fixture_class(class_names = {})
|
889
|
-
self.fixture_class_names = fixture_class_names.merge(class_names.stringify_keys)
|
890
|
-
end
|
891
|
-
|
892
|
-
def fixtures(*fixture_set_names)
|
893
|
-
if fixture_set_names.first == :all
|
894
|
-
fixture_set_names = Dir["#{fixture_path}/{**,*}/*.{yml}"].uniq
|
895
|
-
fixture_set_names.map! { |f| f[(fixture_path.to_s.size + 1)..-5] }
|
896
|
-
else
|
897
|
-
fixture_set_names = fixture_set_names.flatten.map(&:to_s)
|
898
|
-
end
|
899
|
-
|
900
|
-
self.fixture_table_names |= fixture_set_names
|
901
|
-
setup_fixture_accessors(fixture_set_names)
|
902
|
-
end
|
903
|
-
|
904
|
-
def setup_fixture_accessors(fixture_set_names = nil)
|
905
|
-
fixture_set_names = Array(fixture_set_names || fixture_table_names)
|
906
|
-
methods = Module.new do
|
907
|
-
fixture_set_names.each do |fs_name|
|
908
|
-
fs_name = fs_name.to_s
|
909
|
-
accessor_name = fs_name.tr("/", "_").to_sym
|
910
|
-
|
911
|
-
define_method(accessor_name) do |*fixture_names|
|
912
|
-
force_reload = fixture_names.pop if fixture_names.last == true || fixture_names.last == :reload
|
913
|
-
return_single_record = fixture_names.size == 1
|
914
|
-
fixture_names = @loaded_fixtures[fs_name].fixtures.keys if fixture_names.empty?
|
915
|
-
|
916
|
-
@fixture_cache[fs_name] ||= {}
|
917
|
-
|
918
|
-
instances = fixture_names.map do |f_name|
|
919
|
-
f_name = f_name.to_s if f_name.is_a?(Symbol)
|
920
|
-
@fixture_cache[fs_name].delete(f_name) if force_reload
|
921
|
-
|
922
|
-
if @loaded_fixtures[fs_name][f_name]
|
923
|
-
@fixture_cache[fs_name][f_name] ||= @loaded_fixtures[fs_name][f_name].find
|
924
|
-
else
|
925
|
-
raise StandardError, "No fixture named '#{f_name}' found for fixture set '#{fs_name}'"
|
926
|
-
end
|
927
|
-
end
|
928
|
-
|
929
|
-
return_single_record ? instances.first : instances
|
930
|
-
end
|
931
|
-
private accessor_name
|
932
|
-
end
|
933
|
-
end
|
934
|
-
include methods
|
935
|
-
end
|
936
|
-
|
937
|
-
def uses_transaction(*methods)
|
938
|
-
@uses_transaction = [] unless defined?(@uses_transaction)
|
939
|
-
@uses_transaction.concat methods.map(&:to_s)
|
940
|
-
end
|
941
|
-
|
942
|
-
def uses_transaction?(method)
|
943
|
-
@uses_transaction = [] unless defined?(@uses_transaction)
|
944
|
-
@uses_transaction.include?(method.to_s)
|
945
|
-
end
|
946
|
-
end
|
947
|
-
|
948
|
-
def run_in_transaction?
|
949
|
-
use_transactional_tests &&
|
950
|
-
!self.class.uses_transaction?(method_name)
|
951
|
-
end
|
952
|
-
|
953
|
-
def setup_fixtures(config = ActiveRecord::Base)
|
954
|
-
if pre_loaded_fixtures && !use_transactional_tests
|
955
|
-
raise RuntimeError, "pre_loaded_fixtures requires use_transactional_tests"
|
956
|
-
end
|
957
|
-
|
958
|
-
@fixture_cache = {}
|
959
|
-
@fixture_connections = []
|
960
|
-
@@already_loaded_fixtures ||= {}
|
961
|
-
@connection_subscriber = nil
|
962
|
-
|
963
|
-
# Load fixtures once and begin transaction.
|
964
|
-
if run_in_transaction?
|
965
|
-
if @@already_loaded_fixtures[self.class]
|
966
|
-
@loaded_fixtures = @@already_loaded_fixtures[self.class]
|
967
|
-
else
|
968
|
-
@loaded_fixtures = load_fixtures(config)
|
969
|
-
@@already_loaded_fixtures[self.class] = @loaded_fixtures
|
970
|
-
end
|
971
|
-
|
972
|
-
# Begin transactions for connections already established
|
973
|
-
@fixture_connections = enlist_fixture_connections
|
974
|
-
@fixture_connections.each do |connection|
|
975
|
-
connection.begin_transaction joinable: false
|
976
|
-
connection.pool.lock_thread = true
|
977
|
-
end
|
978
|
-
|
979
|
-
# When connections are established in the future, begin a transaction too
|
980
|
-
@connection_subscriber = ActiveSupport::Notifications.subscribe("!connection.active_record") do |_, _, _, _, payload|
|
981
|
-
spec_name = payload[:spec_name] if payload.key?(:spec_name)
|
982
|
-
|
983
|
-
if spec_name
|
984
|
-
begin
|
985
|
-
connection = ActiveRecord::Base.connection_handler.retrieve_connection(spec_name)
|
986
|
-
rescue ConnectionNotEstablished
|
987
|
-
connection = nil
|
988
|
-
end
|
989
|
-
|
990
|
-
if connection && !@fixture_connections.include?(connection)
|
991
|
-
connection.begin_transaction joinable: false
|
992
|
-
connection.pool.lock_thread = true
|
993
|
-
@fixture_connections << connection
|
994
|
-
end
|
995
|
-
end
|
996
|
-
end
|
997
|
-
|
998
|
-
# Load fixtures for every test.
|
999
|
-
else
|
1000
|
-
ActiveRecord::FixtureSet.reset_cache
|
1001
|
-
@@already_loaded_fixtures[self.class] = nil
|
1002
|
-
@loaded_fixtures = load_fixtures(config)
|
1003
|
-
end
|
1004
|
-
|
1005
|
-
# Instantiate fixtures for every test if requested.
|
1006
|
-
instantiate_fixtures if use_instantiated_fixtures
|
1007
|
-
end
|
1008
|
-
|
1009
|
-
def teardown_fixtures
|
1010
|
-
# Rollback changes if a transaction is active.
|
1011
|
-
if run_in_transaction?
|
1012
|
-
ActiveSupport::Notifications.unsubscribe(@connection_subscriber) if @connection_subscriber
|
1013
|
-
@fixture_connections.each do |connection|
|
1014
|
-
connection.rollback_transaction if connection.transaction_open?
|
1015
|
-
connection.pool.lock_thread = false
|
1016
|
-
end
|
1017
|
-
@fixture_connections.clear
|
1018
|
-
else
|
1019
|
-
ActiveRecord::FixtureSet.reset_cache
|
1020
|
-
end
|
1021
|
-
|
1022
|
-
ActiveRecord::Base.clear_active_connections!
|
1023
|
-
end
|
1024
|
-
|
1025
|
-
def enlist_fixture_connections
|
1026
|
-
ActiveRecord::Base.connection_handler.connection_pool_list.map(&:connection)
|
1027
|
-
end
|
1028
|
-
|
1029
|
-
private
|
1030
|
-
def load_fixtures(config)
|
1031
|
-
fixtures = ActiveRecord::FixtureSet.create_fixtures(fixture_path, fixture_table_names, fixture_class_names, config)
|
1032
|
-
Hash[fixtures.map { |f| [f.name, f] }]
|
1033
|
-
end
|
1034
|
-
|
1035
|
-
def instantiate_fixtures
|
1036
|
-
if pre_loaded_fixtures
|
1037
|
-
raise RuntimeError, "Load fixtures before instantiating them." if ActiveRecord::FixtureSet.all_loaded_fixtures.empty?
|
1038
|
-
ActiveRecord::FixtureSet.instantiate_all_loaded_fixtures(self, load_instances?)
|
1039
|
-
else
|
1040
|
-
raise RuntimeError, "Load fixtures before instantiating them." if @loaded_fixtures.nil?
|
1041
|
-
@loaded_fixtures.each_value do |fixture_set|
|
1042
|
-
ActiveRecord::FixtureSet.instantiate_fixtures(self, fixture_set, load_instances?)
|
1043
|
-
end
|
1044
|
-
end
|
1045
|
-
end
|
1046
|
-
|
1047
|
-
def load_instances?
|
1048
|
-
use_instantiated_fixtures != :no_instances
|
1049
|
-
end
|
1050
|
-
end
|
1051
|
-
end
|
1052
|
-
|
1053
|
-
class ActiveRecord::FixtureSet::RenderContext # :nodoc:
|
1054
|
-
def self.create_subclass
|
1055
|
-
Class.new ActiveRecord::FixtureSet.context_class do
|
1056
|
-
def get_binding
|
1057
|
-
binding()
|
1058
|
-
end
|
1059
|
-
|
1060
|
-
def binary(path)
|
1061
|
-
%(!!binary "#{Base64.strict_encode64(File.read(path))}")
|
1062
|
-
end
|
1063
|
-
end
|
1064
|
-
end
|
1065
|
-
end
|
781
|
+
ActiveSupport.run_load_hooks :active_record_fixture_set, ActiveRecord::FixtureSet
|