activerecord 6.1.7 → 7.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +616 -1290
- data/MIT-LICENSE +1 -1
- data/README.rdoc +31 -31
- data/examples/performance.rb +2 -2
- data/lib/active_record/aggregations.rb +17 -14
- data/lib/active_record/association_relation.rb +2 -12
- data/lib/active_record/associations/alias_tracker.rb +25 -19
- data/lib/active_record/associations/association.rb +60 -21
- data/lib/active_record/associations/association_scope.rb +17 -12
- data/lib/active_record/associations/belongs_to_association.rb +37 -11
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -4
- data/lib/active_record/associations/builder/association.rb +11 -5
- data/lib/active_record/associations/builder/belongs_to.rb +41 -14
- data/lib/active_record/associations/builder/collection_association.rb +10 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -7
- data/lib/active_record/associations/builder/has_many.rb +4 -4
- data/lib/active_record/associations/builder/has_one.rb +4 -4
- data/lib/active_record/associations/builder/singular_association.rb +6 -2
- data/lib/active_record/associations/collection_association.rb +46 -36
- data/lib/active_record/associations/collection_proxy.rb +44 -16
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/errors.rb +265 -0
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +29 -19
- data/lib/active_record/associations/has_many_through_association.rb +19 -8
- data/lib/active_record/associations/has_one_association.rb +20 -10
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +30 -27
- data/lib/active_record/associations/join_dependency.rb +28 -20
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +212 -53
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +153 -0
- data/lib/active_record/associations/preloader/through_association.rb +50 -16
- data/lib/active_record/associations/preloader.rb +50 -121
- data/lib/active_record/associations/singular_association.rb +15 -3
- data/lib/active_record/associations/through_association.rb +25 -14
- data/lib/active_record/associations.rb +429 -522
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +1 -5
- data/lib/active_record/attribute_methods/before_type_cast.rb +24 -2
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +73 -22
- data/lib/active_record/attribute_methods/primary_key.rb +47 -27
- data/lib/active_record/attribute_methods/query.rb +31 -19
- data/lib/active_record/attribute_methods/read.rb +14 -11
- data/lib/active_record/attribute_methods/serialization.rb +174 -37
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +15 -9
- data/lib/active_record/attribute_methods/write.rb +12 -15
- data/lib/active_record/attribute_methods.rb +164 -52
- data/lib/active_record/attributes.rb +57 -54
- data/lib/active_record/autosave_association.rb +74 -57
- data/lib/active_record/base.rb +27 -5
- data/lib/active_record/callbacks.rb +19 -35
- data/lib/active_record/coders/column_serializer.rb +61 -0
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +70 -46
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +284 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +79 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +325 -604
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +199 -60
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +230 -64
- data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -131
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +21 -20
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +186 -31
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +378 -143
- data/lib/active_record/connection_adapters/abstract/transaction.rb +361 -76
- data/lib/active_record/connection_adapters/abstract_adapter.rb +624 -163
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +348 -165
- data/lib/active_record/connection_adapters/column.rb +13 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +29 -130
- data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -55
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +45 -14
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +107 -68
- data/lib/active_record/connection_adapters/pool_config.rb +26 -16
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +30 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +114 -54
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +12 -3
- 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 +18 -6
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +137 -104
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +92 -2
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +173 -3
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +403 -77
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +520 -253
- data/lib/active_record/connection_adapters/schema_cache.rb +326 -102
- data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +78 -55
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +68 -54
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +20 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +66 -22
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +372 -130
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +229 -0
- data/lib/active_record/connection_adapters.rb +130 -6
- data/lib/active_record/connection_handling.rb +132 -146
- data/lib/active_record/core.rb +310 -253
- data/lib/active_record/counter_cache.rb +68 -34
- data/lib/active_record/database_configurations/connection_url_resolver.rb +10 -4
- data/lib/active_record/database_configurations/database_config.rb +34 -10
- data/lib/active_record/database_configurations/hash_config.rb +107 -31
- data/lib/active_record/database_configurations/url_config.rb +38 -13
- data/lib/active_record/database_configurations.rb +96 -60
- data/lib/active_record/delegated_type.rb +90 -20
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +4 -2
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +3 -3
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +68 -0
- data/lib/active_record/encryption/configurable.rb +60 -0
- data/lib/active_record/encryption/context.rb +42 -0
- data/lib/active_record/encryption/contexts.rb +76 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +230 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +175 -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 +170 -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 +157 -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 +53 -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_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +96 -0
- data/lib/active_record/encryption/null_encryptor.rb +25 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +28 -0
- data/lib/active_record/encryption/scheme.rb +100 -0
- data/lib/active_record/encryption.rb +58 -0
- data/lib/active_record/enum.rb +170 -62
- data/lib/active_record/errors.rb +210 -27
- data/lib/active_record/explain.rb +21 -12
- 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 +15 -1
- data/lib/active_record/fixture_set/model_metadata.rb +14 -4
- data/lib/active_record/fixture_set/render_context.rb +2 -0
- data/lib/active_record/fixture_set/table_row.rb +70 -14
- data/lib/active_record/fixture_set/table_rows.rb +4 -4
- data/lib/active_record/fixtures.rb +179 -112
- data/lib/active_record/future_result.rb +178 -0
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +85 -31
- data/lib/active_record/insert_all.rb +148 -32
- data/lib/active_record/integration.rb +14 -10
- data/lib/active_record/internal_metadata.rb +123 -23
- data/lib/active_record/legacy_yaml_adapter.rb +2 -39
- data/lib/active_record/locking/optimistic.rb +43 -27
- data/lib/active_record/locking/pessimistic.rb +15 -6
- data/lib/active_record/log_subscriber.rb +41 -29
- data/lib/active_record/marshalling.rb +59 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +10 -10
- data/lib/active_record/middleware/database_selector.rb +23 -13
- data/lib/active_record/middleware/shard_selector.rb +62 -0
- data/lib/active_record/migration/command_recorder.rb +113 -16
- data/lib/active_record/migration/compatibility.rb +235 -46
- data/lib/active_record/migration/default_strategy.rb +22 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +374 -177
- data/lib/active_record/model_schema.rb +145 -158
- data/lib/active_record/nested_attributes.rb +61 -23
- data/lib/active_record/no_touching.rb +3 -3
- data/lib/active_record/normalization.rb +163 -0
- data/lib/active_record/persistence.rb +282 -283
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +18 -25
- data/lib/active_record/query_logs.rb +189 -0
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +44 -9
- data/lib/active_record/railtie.rb +229 -71
- data/lib/active_record/railties/controller_runtime.rb +25 -11
- data/lib/active_record/railties/databases.rake +189 -256
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +41 -3
- data/lib/active_record/reflection.rb +332 -103
- data/lib/active_record/relation/batches/batch_enumerator.rb +38 -9
- data/lib/active_record/relation/batches.rb +200 -65
- data/lib/active_record/relation/calculations.rb +301 -112
- data/lib/active_record/relation/delegation.rb +33 -22
- data/lib/active_record/relation/finder_methods.rb +123 -52
- data/lib/active_record/relation/merger.rb +26 -19
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +38 -4
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -7
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +29 -22
- data/lib/active_record/relation/query_attribute.rb +30 -12
- data/lib/active_record/relation/query_methods.rb +870 -163
- data/lib/active_record/relation/record_fetch_warning.rb +10 -9
- data/lib/active_record/relation/spawn_methods.rb +7 -6
- data/lib/active_record/relation/where_clause.rb +15 -36
- data/lib/active_record/relation.rb +736 -145
- data/lib/active_record/result.rb +67 -54
- data/lib/active_record/runtime_registry.rb +71 -13
- data/lib/active_record/sanitization.rb +84 -34
- data/lib/active_record/schema.rb +39 -23
- data/lib/active_record/schema_dumper.rb +90 -31
- data/lib/active_record/schema_migration.rb +74 -23
- data/lib/active_record/scoping/default.rb +72 -15
- data/lib/active_record/scoping/named.rb +6 -13
- data/lib/active_record/scoping.rb +65 -34
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/serialization.rb +6 -1
- data/lib/active_record/signed_id.rb +30 -9
- data/lib/active_record/statement_cache.rb +7 -7
- data/lib/active_record/store.rb +10 -10
- data/lib/active_record/suppressor.rb +13 -15
- data/lib/active_record/table_metadata.rb +7 -3
- data/lib/active_record/tasks/database_tasks.rb +288 -149
- data/lib/active_record/tasks/mysql_database_tasks.rb +16 -7
- data/lib/active_record/tasks/postgresql_database_tasks.rb +35 -26
- data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -7
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +173 -155
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +32 -19
- data/lib/active_record/token_for.rb +123 -0
- data/lib/active_record/touch_later.rb +12 -7
- data/lib/active_record/transaction.rb +132 -0
- data/lib/active_record/transactions.rb +118 -41
- data/lib/active_record/translation.rb +3 -5
- data/lib/active_record/type/adapter_specific_registry.rb +32 -14
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +9 -7
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/type/type_map.rb +17 -20
- data/lib/active_record/type.rb +1 -2
- data/lib/active_record/type_caster/connection.rb +4 -4
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +13 -7
- data/lib/active_record/validations/numericality.rb +5 -4
- data/lib/active_record/validations/presence.rb +5 -28
- data/lib/active_record/validations/uniqueness.rb +65 -15
- data/lib/active_record/validations.rb +12 -5
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +444 -32
- data/lib/arel/alias_predication.rb +1 -1
- data/lib/arel/attributes/attribute.rb +0 -8
- data/lib/arel/collectors/bind.rb +2 -0
- data/lib/arel/collectors/composite.rb +7 -0
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +1 -1
- data/lib/arel/crud.rb +28 -22
- data/lib/arel/delete_manager.rb +18 -4
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +2 -3
- data/lib/arel/nodes/binary.rb +6 -7
- data/lib/arel/nodes/bound_sql_literal.rb +65 -0
- data/lib/arel/nodes/casted.rb +1 -1
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/delete_statement.rb +12 -13
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/function.rb +1 -0
- data/lib/arel/nodes/homogeneous_in.rb +1 -9
- data/lib/arel/nodes/insert_statement.rb +2 -2
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/{and.rb → nary.rb} +9 -2
- data/lib/arel/nodes/node.rb +115 -5
- data/lib/arel/nodes/select_core.rb +2 -2
- data/lib/arel/nodes/select_statement.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +13 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes/update_statement.rb +8 -3
- data/lib/arel/nodes.rb +7 -2
- data/lib/arel/predications.rb +14 -4
- data/lib/arel/select_manager.rb +11 -5
- data/lib/arel/table.rb +9 -6
- data/lib/arel/tree_manager.rb +8 -15
- data/lib/arel/update_manager.rb +20 -5
- data/lib/arel/visitors/dot.rb +81 -90
- data/lib/arel/visitors/mysql.rb +23 -5
- data/lib/arel/visitors/postgresql.rb +1 -22
- data/lib/arel/visitors/sqlite.rb +25 -0
- data/lib/arel/visitors/to_sql.rb +170 -36
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +23 -4
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
- data/lib/rails/generators/active_record/migration.rb +3 -1
- data/lib/rails/generators/active_record/model/USAGE +113 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -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 +103 -17
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -67
@@ -6,7 +6,7 @@ require "active_record/fixture_set/model_metadata"
|
|
6
6
|
module ActiveRecord
|
7
7
|
class FixtureSet
|
8
8
|
class TableRows # :nodoc:
|
9
|
-
def initialize(table_name, model_class:, fixtures
|
9
|
+
def initialize(table_name, model_class:, fixtures:)
|
10
10
|
@model_class = model_class
|
11
11
|
|
12
12
|
# track any join tables we need to insert later
|
@@ -15,7 +15,7 @@ module ActiveRecord
|
|
15
15
|
# ensure this table is loaded before any HABTM associations
|
16
16
|
@tables[table_name] = nil
|
17
17
|
|
18
|
-
build_table_rows_from(table_name, fixtures
|
18
|
+
build_table_rows_from(table_name, fixtures)
|
19
19
|
end
|
20
20
|
|
21
21
|
attr_reader :tables, :model_class
|
@@ -29,8 +29,8 @@ module ActiveRecord
|
|
29
29
|
end
|
30
30
|
|
31
31
|
private
|
32
|
-
def build_table_rows_from(table_name, fixtures
|
33
|
-
now =
|
32
|
+
def build_table_rows_from(table_name, fixtures)
|
33
|
+
now = ActiveRecord.default_timezone == :utc ? Time.now.utc : Time.now
|
34
34
|
|
35
35
|
@tables[table_name] = fixtures.map do |label, fixture|
|
36
36
|
TableRow.new(
|
@@ -6,20 +6,23 @@ require "zlib"
|
|
6
6
|
require "set"
|
7
7
|
require "active_support/dependencies"
|
8
8
|
require "active_support/core_ext/digest/uuid"
|
9
|
-
require "active_record/fixture_set/file"
|
10
|
-
require "active_record/fixture_set/render_context"
|
11
|
-
require "active_record/fixture_set/table_rows"
|
12
9
|
require "active_record/test_fixtures"
|
13
10
|
|
14
11
|
module ActiveRecord
|
15
|
-
class FixtureClassNotFound < ActiveRecord::ActiveRecordError
|
12
|
+
class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc:
|
16
13
|
end
|
17
14
|
|
15
|
+
# = Active Record \Fixtures
|
16
|
+
#
|
18
17
|
# \Fixtures are a way of organizing data that you want to test against; in short, sample data.
|
19
18
|
#
|
20
|
-
# They are stored in YAML files, one file per model, which are placed in
|
21
|
-
#
|
22
|
-
#
|
19
|
+
# They are stored in YAML files, one file per model, which are by default placed in either
|
20
|
+
# <tt><your-rails-app>/test/fixtures/</tt> or in the <tt>test/fixtures</tt>
|
21
|
+
# folder under any of your application's engines.
|
22
|
+
#
|
23
|
+
# The location can also be changed with ActiveSupport::TestCase.fixture_paths=,
|
24
|
+
# once you have <tt>require "rails/test_help"</tt> in your +test_helper.rb+.
|
25
|
+
#
|
23
26
|
# The fixture file ends with the +.yml+ file extension, for example:
|
24
27
|
# <tt><your-rails-app>/test/fixtures/web_sites.yml</tt>).
|
25
28
|
#
|
@@ -35,14 +38,21 @@ module ActiveRecord
|
|
35
38
|
# name: Google
|
36
39
|
# url: http://www.google.com
|
37
40
|
#
|
38
|
-
# This fixture file includes two fixtures. Each YAML fixture (
|
41
|
+
# This fixture file includes two fixtures. Each YAML fixture (i.e. record) is given a name and
|
39
42
|
# is followed by an indented list of key/value pairs in the "key: value" format. Records are
|
40
43
|
# separated by a blank line for your viewing pleasure.
|
41
44
|
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
45
|
+
# == Ordering
|
46
|
+
#
|
47
|
+
# Fixtures by default are unordered. This is because the maps in YAML are unordered.
|
48
|
+
#
|
49
|
+
# If you want ordered fixtures, use the omap YAML type.
|
50
|
+
# See https://yaml.org/type/omap.html for the specification.
|
51
|
+
#
|
52
|
+
# You will need ordered fixtures when you have foreign key constraints
|
53
|
+
# on keys in the same table. This is commonly needed for tree structures.
|
54
|
+
#
|
55
|
+
# For example:
|
46
56
|
#
|
47
57
|
# --- !omap
|
48
58
|
# - parent:
|
@@ -54,7 +64,7 @@ module ActiveRecord
|
|
54
64
|
# parent_id: 1
|
55
65
|
# title: Child
|
56
66
|
#
|
57
|
-
#
|
67
|
+
# == Using Fixtures in Test Cases
|
58
68
|
#
|
59
69
|
# Since fixtures are a testing construct, we use them in our unit and functional tests. There
|
60
70
|
# are two ways to use the fixtures, but first let's take a look at a sample unit test:
|
@@ -100,6 +110,12 @@ module ActiveRecord
|
|
100
110
|
# assert_raise(StandardError) { web_sites(:reddit) }
|
101
111
|
# end
|
102
112
|
#
|
113
|
+
# If the model names conflicts with a +TestCase+ methods, you can use the generic +fixture+ accessor
|
114
|
+
#
|
115
|
+
# test "generic find" do
|
116
|
+
# assert_equal "Ruby on Rails", fixture(:web_sites, :rubyonrails).name
|
117
|
+
# end
|
118
|
+
#
|
103
119
|
# Alternatively, you may enable auto-instantiation of the fixture data. For instance, take the
|
104
120
|
# following tests:
|
105
121
|
#
|
@@ -124,7 +140,7 @@ module ActiveRecord
|
|
124
140
|
# traversed in the database to create the fixture hash and/or instance variables. This is expensive for
|
125
141
|
# large sets of fixtured data.
|
126
142
|
#
|
127
|
-
#
|
143
|
+
# == Dynamic fixtures with \ERB
|
128
144
|
#
|
129
145
|
# Sometimes you don't care about the content of the fixtures as much as you care about the volume.
|
130
146
|
# In these cases, you can mix ERB in with your YAML fixtures to create a bunch of fixtures for load
|
@@ -152,7 +168,7 @@ module ActiveRecord
|
|
152
168
|
# - define a helper method in <tt>test_helper.rb</tt>
|
153
169
|
# module FixtureFileHelpers
|
154
170
|
# def file_sha(path)
|
155
|
-
# Digest::
|
171
|
+
# OpenSSL::Digest::SHA256.hexdigest(File.read(Rails.root.join('test/fixtures', path)))
|
156
172
|
# end
|
157
173
|
# end
|
158
174
|
# ActiveRecord::FixtureSet.context_class.include FixtureFileHelpers
|
@@ -162,7 +178,7 @@ module ActiveRecord
|
|
162
178
|
# name: kitten.png
|
163
179
|
# sha: <%= file_sha 'files/kitten.png' %>
|
164
180
|
#
|
165
|
-
#
|
181
|
+
# == Transactional Tests
|
166
182
|
#
|
167
183
|
# Test cases can use begin+rollback to isolate their changes to the database instead of having to
|
168
184
|
# delete+insert for every test case.
|
@@ -198,7 +214,7 @@ module ActiveRecord
|
|
198
214
|
# 2. Your database does not support transactions. Every Active Record database supports transactions except MySQL MyISAM.
|
199
215
|
# Use InnoDB, MaxDB, or NDB instead.
|
200
216
|
#
|
201
|
-
#
|
217
|
+
# == Advanced Fixtures
|
202
218
|
#
|
203
219
|
# Fixtures that don't specify an ID get some extra features:
|
204
220
|
#
|
@@ -212,7 +228,7 @@ module ActiveRecord
|
|
212
228
|
# * Fixture label interpolation
|
213
229
|
# * Support for YAML defaults
|
214
230
|
#
|
215
|
-
#
|
231
|
+
# === Stable, Autogenerated IDs
|
216
232
|
#
|
217
233
|
# Here, have a monkey fixture:
|
218
234
|
#
|
@@ -241,13 +257,13 @@ module ActiveRecord
|
|
241
257
|
# The generated ID for a given label is constant, so we can discover
|
242
258
|
# any fixture's ID without loading anything, as long as we know the label.
|
243
259
|
#
|
244
|
-
#
|
260
|
+
# === Label references for associations (+belongs_to+, +has_one+, +has_many+)
|
245
261
|
#
|
246
262
|
# Specifying foreign keys in fixtures can be very fragile, not to
|
247
263
|
# mention difficult to read. Since Active Record can figure out the ID of
|
248
264
|
# any fixture from its label, you can specify FK's by label instead of ID.
|
249
265
|
#
|
250
|
-
#
|
266
|
+
# ==== +belongs_to+
|
251
267
|
#
|
252
268
|
# Let's break out some more monkeys and pirates.
|
253
269
|
#
|
@@ -258,6 +274,8 @@ module ActiveRecord
|
|
258
274
|
# name: Reginald the Pirate
|
259
275
|
# monkey_id: 1
|
260
276
|
#
|
277
|
+
# <code></code>
|
278
|
+
#
|
261
279
|
# ### in monkeys.yml
|
262
280
|
#
|
263
281
|
# george:
|
@@ -275,6 +293,8 @@ module ActiveRecord
|
|
275
293
|
# name: Reginald the Pirate
|
276
294
|
# monkey: george
|
277
295
|
#
|
296
|
+
# <code></code>
|
297
|
+
#
|
278
298
|
# ### in monkeys.yml
|
279
299
|
#
|
280
300
|
# george:
|
@@ -286,7 +306,7 @@ module ActiveRecord
|
|
286
306
|
# a target *label* for the *association* (monkey: george) rather than
|
287
307
|
# a target *id* for the *FK* (<tt>monkey_id: 1</tt>).
|
288
308
|
#
|
289
|
-
# ==== Polymorphic belongs_to
|
309
|
+
# ==== Polymorphic +belongs_to+
|
290
310
|
#
|
291
311
|
# Supporting polymorphic relationships is a little bit more complicated, since
|
292
312
|
# Active Record needs to know what type your association is pointing at. Something
|
@@ -296,6 +316,8 @@ module ActiveRecord
|
|
296
316
|
#
|
297
317
|
# belongs_to :eater, polymorphic: true
|
298
318
|
#
|
319
|
+
# <code></code>
|
320
|
+
#
|
299
321
|
# ### in fruits.yml
|
300
322
|
#
|
301
323
|
# apple:
|
@@ -311,9 +333,9 @@ module ActiveRecord
|
|
311
333
|
#
|
312
334
|
# Just provide the polymorphic target type and Active Record will take care of the rest.
|
313
335
|
#
|
314
|
-
#
|
336
|
+
# ==== +has_and_belongs_to_many+ or <tt>has_many :through</tt>
|
315
337
|
#
|
316
|
-
# Time to give our monkey some fruit.
|
338
|
+
# \Time to give our monkey some fruit.
|
317
339
|
#
|
318
340
|
# ### in monkeys.yml
|
319
341
|
#
|
@@ -321,6 +343,8 @@ module ActiveRecord
|
|
321
343
|
# id: 1
|
322
344
|
# name: George the Monkey
|
323
345
|
#
|
346
|
+
# <code></code>
|
347
|
+
#
|
324
348
|
# ### in fruits.yml
|
325
349
|
#
|
326
350
|
# apple:
|
@@ -335,6 +359,8 @@ module ActiveRecord
|
|
335
359
|
# id: 3
|
336
360
|
# name: grape
|
337
361
|
#
|
362
|
+
# <code></code>
|
363
|
+
#
|
338
364
|
# ### in fruits_monkeys.yml
|
339
365
|
#
|
340
366
|
# apple_george:
|
@@ -358,6 +384,8 @@ module ActiveRecord
|
|
358
384
|
# name: George the Monkey
|
359
385
|
# fruits: apple, orange, grape
|
360
386
|
#
|
387
|
+
# <code></code>
|
388
|
+
#
|
361
389
|
# ### in fruits.yml
|
362
390
|
#
|
363
391
|
# apple:
|
@@ -375,7 +403,7 @@ module ActiveRecord
|
|
375
403
|
# the fixture's model class and discovers the +has_and_belongs_to_many+
|
376
404
|
# associations.
|
377
405
|
#
|
378
|
-
#
|
406
|
+
# === Autofilled \Timestamp Columns
|
379
407
|
#
|
380
408
|
# If your table/model specifies any of Active Record's
|
381
409
|
# standard timestamp columns (+created_at+, +created_on+, +updated_at+, +updated_on+),
|
@@ -383,7 +411,7 @@ module ActiveRecord
|
|
383
411
|
#
|
384
412
|
# If you've set specific values, they'll be left alone.
|
385
413
|
#
|
386
|
-
#
|
414
|
+
# === Fixture label interpolation
|
387
415
|
#
|
388
416
|
# The label of the current fixture is always available as a column value:
|
389
417
|
#
|
@@ -400,14 +428,18 @@ module ActiveRecord
|
|
400
428
|
# monkey_id: <%= ActiveRecord::FixtureSet.identify(:reginald) %>
|
401
429
|
# pirate_id: <%= ActiveRecord::FixtureSet.identify(:george) %>
|
402
430
|
#
|
403
|
-
#
|
431
|
+
# If the model uses UUID values for identifiers, add the +:uuid+ argument:
|
432
|
+
#
|
433
|
+
# ActiveRecord::FixtureSet.identify(:boaty_mcboatface, :uuid)
|
434
|
+
#
|
435
|
+
# === Support for YAML defaults
|
404
436
|
#
|
405
437
|
# You can set and reuse defaults in your fixtures YAML file.
|
406
438
|
# This is the same technique used in the +database.yml+ file to specify
|
407
439
|
# defaults:
|
408
440
|
#
|
409
441
|
# DEFAULTS: &DEFAULTS
|
410
|
-
# created_on: <%= 3.weeks.ago.
|
442
|
+
# created_on: <%= 3.weeks.ago.to_fs(:db) %>
|
411
443
|
#
|
412
444
|
# first:
|
413
445
|
# name: Smurf
|
@@ -426,7 +458,7 @@ module ActiveRecord
|
|
426
458
|
# _fixture:
|
427
459
|
# ignore:
|
428
460
|
# - base
|
429
|
-
# # or use "ignore: base" when there is only one fixture needs to be ignored.
|
461
|
+
# # or use "ignore: base" when there is only one fixture that needs to be ignored.
|
430
462
|
#
|
431
463
|
# base: &base
|
432
464
|
# admin: false
|
@@ -442,6 +474,45 @@ module ActiveRecord
|
|
442
474
|
# In the above example, 'base' will be ignored when creating fixtures.
|
443
475
|
# This can be used for common attributes inheriting.
|
444
476
|
#
|
477
|
+
# == Composite Primary Key Fixtures
|
478
|
+
#
|
479
|
+
# Fixtures for composite primary key tables are fairly similar to normal tables.
|
480
|
+
# When using an id column, the column may be omitted as usual:
|
481
|
+
#
|
482
|
+
# # app/models/book.rb
|
483
|
+
# class Book < ApplicationRecord
|
484
|
+
# self.primary_key = [:author_id, :id]
|
485
|
+
# belongs_to :author
|
486
|
+
# end
|
487
|
+
#
|
488
|
+
# <code></code>
|
489
|
+
#
|
490
|
+
# # books.yml
|
491
|
+
# alices_adventure_in_wonderland:
|
492
|
+
# author_id: <%= ActiveRecord::FixtureSet.identify(:lewis_carroll) %>
|
493
|
+
# title: "Alice's Adventures in Wonderland"
|
494
|
+
#
|
495
|
+
# However, in order to support composite primary key relationships,
|
496
|
+
# you must use the `composite_identify` method:
|
497
|
+
#
|
498
|
+
# # app/models/book_orders.rb
|
499
|
+
# class BookOrder < ApplicationRecord
|
500
|
+
# self.primary_key = [:shop_id, :id]
|
501
|
+
# belongs_to :order, foreign_key: [:shop_id, :order_id]
|
502
|
+
# belongs_to :book, foreign_key: [:author_id, :book_id]
|
503
|
+
# end
|
504
|
+
#
|
505
|
+
# <code></code>
|
506
|
+
#
|
507
|
+
# # book_orders.yml
|
508
|
+
# alices_adventure_in_wonderland_in_books:
|
509
|
+
# author: lewis_carroll
|
510
|
+
# book_id: <%= ActiveRecord::FixtureSet.composite_identify(
|
511
|
+
# :alices_adventure_in_wonderland, Book.primary_key)[:id] %>
|
512
|
+
# shop: book_store
|
513
|
+
# order_id: <%= ActiveRecord::FixtureSet.composite_identify(
|
514
|
+
# :books, Order.primary_key)[:id] %>
|
515
|
+
#
|
445
516
|
# == Configure the fixture model class
|
446
517
|
#
|
447
518
|
# It's possible to set the fixture's model class directly in the YAML file.
|
@@ -456,6 +527,10 @@ module ActiveRecord
|
|
456
527
|
#
|
457
528
|
# Any fixtures labeled "_fixture" are safely ignored.
|
458
529
|
class FixtureSet
|
530
|
+
require "active_record/fixture_set/file"
|
531
|
+
require "active_record/fixture_set/render_context"
|
532
|
+
require "active_record/fixture_set/table_rows"
|
533
|
+
|
459
534
|
#--
|
460
535
|
# An instance of FixtureSet is normally stored in a single YAML file and
|
461
536
|
# possibly in a folder with the same name.
|
@@ -467,39 +542,6 @@ module ActiveRecord
|
|
467
542
|
|
468
543
|
cattr_accessor :all_loaded_fixtures, default: {}
|
469
544
|
|
470
|
-
class ClassCache
|
471
|
-
def initialize(class_names, config)
|
472
|
-
@class_names = class_names.stringify_keys
|
473
|
-
@config = config
|
474
|
-
|
475
|
-
# Remove string values that aren't constants or subclasses of AR
|
476
|
-
@class_names.delete_if do |klass_name, klass|
|
477
|
-
!insert_class(@class_names, klass_name, klass)
|
478
|
-
end
|
479
|
-
end
|
480
|
-
|
481
|
-
def [](fs_name)
|
482
|
-
@class_names.fetch(fs_name) do
|
483
|
-
klass = default_fixture_model(fs_name, @config).safe_constantize
|
484
|
-
insert_class(@class_names, fs_name, klass)
|
485
|
-
end
|
486
|
-
end
|
487
|
-
|
488
|
-
private
|
489
|
-
def insert_class(class_names, name, klass)
|
490
|
-
# We only want to deal with AR objects.
|
491
|
-
if klass && klass < ActiveRecord::Base
|
492
|
-
class_names[name] = klass
|
493
|
-
else
|
494
|
-
class_names[name] = nil
|
495
|
-
end
|
496
|
-
end
|
497
|
-
|
498
|
-
def default_fixture_model(fs_name, config)
|
499
|
-
ActiveRecord::FixtureSet.default_fixture_model_name(fs_name, config)
|
500
|
-
end
|
501
|
-
end
|
502
|
-
|
503
545
|
class << self
|
504
546
|
def default_fixture_model_name(fixture_set_name, config = ActiveRecord::Base) # :nodoc:
|
505
547
|
config.pluralize_table_names ?
|
@@ -517,24 +559,24 @@ module ActiveRecord
|
|
517
559
|
@@all_cached_fixtures.clear
|
518
560
|
end
|
519
561
|
|
520
|
-
def
|
521
|
-
@@all_cached_fixtures[
|
562
|
+
def cache_for_connection_pool(connection_pool)
|
563
|
+
@@all_cached_fixtures[connection_pool]
|
522
564
|
end
|
523
565
|
|
524
|
-
def fixture_is_cached?(
|
525
|
-
|
566
|
+
def fixture_is_cached?(connection_pool, table_name)
|
567
|
+
cache_for_connection_pool(connection_pool)[table_name]
|
526
568
|
end
|
527
569
|
|
528
|
-
def cached_fixtures(
|
570
|
+
def cached_fixtures(connection_pool, keys_to_fetch = nil)
|
529
571
|
if keys_to_fetch
|
530
|
-
|
572
|
+
cache_for_connection_pool(connection_pool).values_at(*keys_to_fetch)
|
531
573
|
else
|
532
|
-
|
574
|
+
cache_for_connection_pool(connection_pool).values
|
533
575
|
end
|
534
576
|
end
|
535
577
|
|
536
|
-
def cache_fixtures(
|
537
|
-
|
578
|
+
def cache_fixtures(connection_pool, fixtures_map)
|
579
|
+
cache_for_connection_pool(connection_pool).update(fixtures_map)
|
538
580
|
end
|
539
581
|
|
540
582
|
def instantiate_fixtures(object, fixture_set, load_instances = true)
|
@@ -552,31 +594,30 @@ module ActiveRecord
|
|
552
594
|
end
|
553
595
|
end
|
554
596
|
|
555
|
-
def create_fixtures(
|
597
|
+
def create_fixtures(fixtures_directories, fixture_set_names, class_names = {}, config = ActiveRecord::Base)
|
556
598
|
fixture_set_names = Array(fixture_set_names).map(&:to_s)
|
557
|
-
class_names
|
558
|
-
|
559
|
-
# FIXME: Apparently JK uses this.
|
560
|
-
connection = block_given? ? block : lambda { ActiveRecord::Base.connection }
|
599
|
+
class_names.stringify_keys!
|
561
600
|
|
601
|
+
connection_pool = config.connection_pool
|
562
602
|
fixture_files_to_read = fixture_set_names.reject do |fs_name|
|
563
|
-
fixture_is_cached?(
|
603
|
+
fixture_is_cached?(connection_pool, fs_name)
|
564
604
|
end
|
565
605
|
|
566
606
|
if fixture_files_to_read.any?
|
567
607
|
fixtures_map = read_and_insert(
|
568
|
-
|
608
|
+
Array(fixtures_directories),
|
569
609
|
fixture_files_to_read,
|
570
610
|
class_names,
|
571
|
-
|
611
|
+
connection_pool,
|
572
612
|
)
|
573
|
-
cache_fixtures(
|
613
|
+
cache_fixtures(connection_pool, fixtures_map)
|
574
614
|
end
|
575
|
-
cached_fixtures(
|
615
|
+
cached_fixtures(connection_pool, fixture_set_names)
|
576
616
|
end
|
577
617
|
|
578
618
|
# Returns a consistent, platform-independent identifier for +label+.
|
579
|
-
#
|
619
|
+
#
|
620
|
+
# \Integer identifiers are values less than 2^30. UUIDs are RFC 4122 version 5 SHA-1 hashes.
|
580
621
|
def identify(label, column_type = :integer)
|
581
622
|
if column_type == :uuid
|
582
623
|
Digest::UUID.uuid_v5(Digest::UUID::OID_NAMESPACE, label.to_s)
|
@@ -585,48 +626,54 @@ module ActiveRecord
|
|
585
626
|
end
|
586
627
|
end
|
587
628
|
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
629
|
+
# Returns a consistent, platform-independent hash representing a mapping
|
630
|
+
# between the label and the subcomponents of the provided composite key.
|
631
|
+
#
|
632
|
+
# Example:
|
633
|
+
#
|
634
|
+
# composite_identify("label", [:a, :b, :c]) # => { a: hash_1, b: hash_2, c: hash_3 }
|
635
|
+
def composite_identify(label, key)
|
636
|
+
key
|
637
|
+
.index_with
|
638
|
+
.with_index { |sub_key, index| (identify(label) << index) % MAX_ID }
|
639
|
+
.with_indifferent_access
|
594
640
|
end
|
595
641
|
|
596
|
-
# Superclass for the evaluation contexts used by ERB fixtures.
|
642
|
+
# Superclass for the evaluation contexts used by \ERB fixtures.
|
597
643
|
def context_class
|
598
644
|
@context_class ||= Class.new
|
599
645
|
end
|
600
646
|
|
601
647
|
private
|
602
|
-
def read_and_insert(
|
648
|
+
def read_and_insert(fixtures_directories, fixture_files, class_names, connection_pool) # :nodoc:
|
603
649
|
fixtures_map = {}
|
650
|
+
directory_glob = "{#{fixtures_directories.join(",")}}"
|
604
651
|
fixture_sets = fixture_files.map do |fixture_set_name|
|
605
652
|
klass = class_names[fixture_set_name]
|
606
653
|
fixtures_map[fixture_set_name] = new( # ActiveRecord::FixtureSet.new
|
607
654
|
nil,
|
608
655
|
fixture_set_name,
|
609
656
|
klass,
|
610
|
-
::File.join(
|
657
|
+
::File.join(directory_glob, fixture_set_name)
|
611
658
|
)
|
612
659
|
end
|
613
660
|
update_all_loaded_fixtures(fixtures_map)
|
614
661
|
|
615
|
-
insert(fixture_sets,
|
662
|
+
insert(fixture_sets, connection_pool)
|
616
663
|
|
617
664
|
fixtures_map
|
618
665
|
end
|
619
666
|
|
620
|
-
def insert(fixture_sets,
|
621
|
-
|
667
|
+
def insert(fixture_sets, connection_pool) # :nodoc:
|
668
|
+
fixture_sets_by_pool = fixture_sets.group_by do |fixture_set|
|
622
669
|
if fixture_set.model_class
|
623
|
-
fixture_set.model_class.
|
670
|
+
fixture_set.model_class.connection_pool
|
624
671
|
else
|
625
|
-
|
672
|
+
connection_pool
|
626
673
|
end
|
627
674
|
end
|
628
675
|
|
629
|
-
|
676
|
+
fixture_sets_by_pool.each do |pool, set|
|
630
677
|
table_rows_for_connection = Hash.new { |h, k| h[k] = [] }
|
631
678
|
|
632
679
|
set.each do |fixture_set|
|
@@ -635,15 +682,29 @@ module ActiveRecord
|
|
635
682
|
end
|
636
683
|
end
|
637
684
|
|
638
|
-
|
685
|
+
pool.with_connection do |conn|
|
686
|
+
conn.insert_fixtures_set(table_rows_for_connection, table_rows_for_connection.keys)
|
687
|
+
|
688
|
+
check_all_foreign_keys_valid!(conn)
|
639
689
|
|
640
|
-
|
641
|
-
|
642
|
-
|
690
|
+
# Cap primary key sequences to max(pk).
|
691
|
+
if conn.respond_to?(:reset_pk_sequence!)
|
692
|
+
set.each { |fs| conn.reset_pk_sequence!(fs.table_name) }
|
693
|
+
end
|
643
694
|
end
|
644
695
|
end
|
645
696
|
end
|
646
697
|
|
698
|
+
def check_all_foreign_keys_valid!(conn)
|
699
|
+
return unless ActiveRecord.verify_foreign_keys_for_fixtures
|
700
|
+
|
701
|
+
begin
|
702
|
+
conn.check_all_foreign_keys_valid!
|
703
|
+
rescue ActiveRecord::StatementInvalid => e
|
704
|
+
raise "Foreign key violations found in your fixture data. Ensure you aren't referring to labels that don't exist on associations. Error from database:\n\n#{e.message}"
|
705
|
+
end
|
706
|
+
end
|
707
|
+
|
647
708
|
def update_all_loaded_fixtures(fixtures_map) # :nodoc:
|
648
709
|
all_loaded_fixtures.update(fixtures_map)
|
649
710
|
end
|
@@ -657,7 +718,6 @@ module ActiveRecord
|
|
657
718
|
@config = config
|
658
719
|
|
659
720
|
self.model_class = class_name
|
660
|
-
|
661
721
|
@fixtures = read_fixture_files(path)
|
662
722
|
|
663
723
|
@table_name = model_class&.table_name || self.class.default_fixture_table_name(name, config)
|
@@ -689,7 +749,6 @@ module ActiveRecord
|
|
689
749
|
table_name,
|
690
750
|
model_class: model_class,
|
691
751
|
fixtures: fixtures,
|
692
|
-
config: config,
|
693
752
|
).to_hash
|
694
753
|
end
|
695
754
|
|
@@ -720,14 +779,18 @@ module ActiveRecord
|
|
720
779
|
# Loads the fixtures from the YAML file at +path+.
|
721
780
|
# If the file sets the +model_class+ and current instance value is not set,
|
722
781
|
# it uses the file value.
|
782
|
+
|
723
783
|
def read_fixture_files(path)
|
724
|
-
yaml_files = Dir["#{path}
|
784
|
+
yaml_files = Dir["#{path}{.yml,/{**,*}/*.yml}"].select { |f|
|
725
785
|
::File.file?(f)
|
726
|
-
}
|
786
|
+
}
|
787
|
+
|
788
|
+
raise ArgumentError, "No fixture files found for #{@name}" if yaml_files.empty?
|
727
789
|
|
728
790
|
yaml_files.each_with_object({}) do |file, fixtures|
|
729
791
|
FixtureSet::File.open(file) do |fh|
|
730
792
|
self.model_class ||= fh.model_class if fh.model_class
|
793
|
+
self.model_class ||= default_fixture_model_class
|
731
794
|
self.ignored_fixtures ||= fh.ignored_fixtures
|
732
795
|
fh.each do |fixture_name, row|
|
733
796
|
fixtures[fixture_name] = ActiveRecord::Fixture.new(row, model_class)
|
@@ -736,18 +799,19 @@ module ActiveRecord
|
|
736
799
|
end
|
737
800
|
end
|
738
801
|
|
739
|
-
def
|
740
|
-
|
802
|
+
def default_fixture_model_class
|
803
|
+
klass = ActiveRecord::FixtureSet.default_fixture_model_name(@name, @config).safe_constantize
|
804
|
+
klass if klass && klass < ActiveRecord::Base
|
741
805
|
end
|
742
806
|
end
|
743
807
|
|
744
|
-
class Fixture
|
808
|
+
class Fixture # :nodoc:
|
745
809
|
include Enumerable
|
746
810
|
|
747
|
-
class FixtureError < StandardError
|
811
|
+
class FixtureError < StandardError # :nodoc:
|
748
812
|
end
|
749
813
|
|
750
|
-
class FormatError < FixtureError
|
814
|
+
class FormatError < FixtureError # :nodoc:
|
751
815
|
end
|
752
816
|
|
753
817
|
attr_reader :model_class, :fixture
|
@@ -761,8 +825,8 @@ module ActiveRecord
|
|
761
825
|
model_class.name if model_class
|
762
826
|
end
|
763
827
|
|
764
|
-
def each
|
765
|
-
fixture.each
|
828
|
+
def each(&block)
|
829
|
+
fixture.each(&block)
|
766
830
|
end
|
767
831
|
|
768
832
|
def [](key)
|
@@ -774,7 +838,8 @@ module ActiveRecord
|
|
774
838
|
def find
|
775
839
|
raise FixtureClassNotFound, "No class attached to find." unless model_class
|
776
840
|
object = model_class.unscoped do
|
777
|
-
|
841
|
+
pk_clauses = fixture.slice(*Array(model_class.primary_key))
|
842
|
+
model_class.find_by!(pk_clauses)
|
778
843
|
end
|
779
844
|
# Fixtures can't be eagerly loaded
|
780
845
|
object.instance_variable_set(:@strict_loading, false)
|
@@ -782,3 +847,5 @@ module ActiveRecord
|
|
782
847
|
end
|
783
848
|
end
|
784
849
|
end
|
850
|
+
|
851
|
+
ActiveSupport.run_load_hooks :active_record_fixture_set, ActiveRecord::FixtureSet
|