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
data/lib/active_record/errors.rb
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/deprecation"
|
4
|
+
|
3
5
|
module ActiveRecord
|
6
|
+
include ActiveSupport::Deprecation::DeprecatedConstantAccessor
|
7
|
+
|
4
8
|
# = Active Record Errors
|
5
9
|
#
|
6
10
|
# Generic Active Record exception class.
|
7
11
|
class ActiveRecordError < StandardError
|
8
12
|
end
|
9
13
|
|
10
|
-
# Raised when trying to use a feature in Active Record which requires Active Job but the gem is not present.
|
11
|
-
class ActiveJobRequiredError < ActiveRecordError
|
12
|
-
end
|
13
|
-
|
14
14
|
# Raised when the single-table inheritance mechanism fails to locate the subclass
|
15
15
|
# (for example due to improper usage of column that
|
16
16
|
# {ActiveRecord::Base.inheritance_column}[rdoc-ref:ModelSchema::ClassMethods#inheritance_column]
|
@@ -51,10 +51,31 @@ module ActiveRecord
|
|
51
51
|
class AdapterNotFound < ActiveRecordError
|
52
52
|
end
|
53
53
|
|
54
|
+
# Superclass for all errors raised from an Active Record adapter.
|
55
|
+
class AdapterError < ActiveRecordError
|
56
|
+
def initialize(message = nil, connection_pool: nil)
|
57
|
+
@connection_pool = connection_pool
|
58
|
+
super(message)
|
59
|
+
end
|
60
|
+
|
61
|
+
attr_reader :connection_pool
|
62
|
+
end
|
63
|
+
|
54
64
|
# Raised when connection to the database could not been established (for example when
|
55
|
-
# {ActiveRecord::Base.
|
65
|
+
# {ActiveRecord::Base.lease_connection=}[rdoc-ref:ConnectionHandling#lease_connection]
|
56
66
|
# is given a +nil+ object).
|
57
|
-
class ConnectionNotEstablished <
|
67
|
+
class ConnectionNotEstablished < AdapterError
|
68
|
+
def initialize(message = nil, connection_pool: nil)
|
69
|
+
super(message, connection_pool: connection_pool)
|
70
|
+
end
|
71
|
+
|
72
|
+
def set_pool(connection_pool)
|
73
|
+
unless @connection_pool
|
74
|
+
@connection_pool = connection_pool
|
75
|
+
end
|
76
|
+
|
77
|
+
self
|
78
|
+
end
|
58
79
|
end
|
59
80
|
|
60
81
|
# Raised when a connection could not be obtained within the connection
|
@@ -63,10 +84,34 @@ module ActiveRecord
|
|
63
84
|
class ConnectionTimeoutError < ConnectionNotEstablished
|
64
85
|
end
|
65
86
|
|
87
|
+
# Raised when connection to the database could not been established because it was not
|
88
|
+
# able to connect to the host or when the authorization failed.
|
89
|
+
class DatabaseConnectionError < ConnectionNotEstablished
|
90
|
+
def initialize(message = nil)
|
91
|
+
super(message || "Database connection error")
|
92
|
+
end
|
93
|
+
|
94
|
+
class << self
|
95
|
+
def hostname_error(hostname)
|
96
|
+
DatabaseConnectionError.new(<<~MSG)
|
97
|
+
There is an issue connecting with your hostname: #{hostname}.\n
|
98
|
+
Please check your database configuration and ensure there is a valid connection to your database.
|
99
|
+
MSG
|
100
|
+
end
|
101
|
+
|
102
|
+
def username_error(username)
|
103
|
+
DatabaseConnectionError.new(<<~MSG)
|
104
|
+
There is an issue connecting to your database with your username/password, username: #{username}.\n
|
105
|
+
Please check your database configuration to ensure the username/password are valid.
|
106
|
+
MSG
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
66
111
|
# Raised when a pool was unable to get ahold of all its connections
|
67
112
|
# to perform a "group" action such as
|
68
113
|
# {ActiveRecord::Base.connection_pool.disconnect!}[rdoc-ref:ConnectionAdapters::ConnectionPool#disconnect!]
|
69
|
-
# or {ActiveRecord::Base.clear_reloadable_connections!}[rdoc-ref:ConnectionAdapters::ConnectionHandler#clear_reloadable_connections!].
|
114
|
+
# or {ActiveRecord::Base.connection_handler.clear_reloadable_connections!}[rdoc-ref:ConnectionAdapters::ConnectionHandler#clear_reloadable_connections!].
|
70
115
|
class ExclusiveConnectionTimeoutError < ConnectionTimeoutError
|
71
116
|
end
|
72
117
|
|
@@ -88,8 +133,18 @@ module ActiveRecord
|
|
88
133
|
end
|
89
134
|
|
90
135
|
# Raised by {ActiveRecord::Base#save!}[rdoc-ref:Persistence#save!] and
|
91
|
-
# {ActiveRecord::Base.
|
92
|
-
# methods when a record
|
136
|
+
# {ActiveRecord::Base.update_attribute!}[rdoc-ref:Persistence#update_attribute!]
|
137
|
+
# methods when a record failed to validate or cannot be saved due to any of the
|
138
|
+
# <tt>before_*</tt> callbacks throwing +:abort+. See
|
139
|
+
# ActiveRecord::Callbacks for further details.
|
140
|
+
#
|
141
|
+
# class Product < ActiveRecord::Base
|
142
|
+
# before_save do
|
143
|
+
# throw :abort if price < 0
|
144
|
+
# end
|
145
|
+
# end
|
146
|
+
#
|
147
|
+
# Product.create! # => raises an ActiveRecord::RecordNotSaved
|
93
148
|
class RecordNotSaved < ActiveRecordError
|
94
149
|
attr_reader :record
|
95
150
|
|
@@ -100,15 +155,17 @@ module ActiveRecord
|
|
100
155
|
end
|
101
156
|
|
102
157
|
# Raised by {ActiveRecord::Base#destroy!}[rdoc-ref:Persistence#destroy!]
|
103
|
-
# when a
|
104
|
-
#
|
158
|
+
# when a record cannot be destroyed due to any of the
|
159
|
+
# <tt>before_destroy</tt> callbacks throwing +:abort+. See
|
160
|
+
# ActiveRecord::Callbacks for further details.
|
105
161
|
#
|
106
|
-
#
|
107
|
-
#
|
108
|
-
#
|
109
|
-
#
|
162
|
+
# class User < ActiveRecord::Base
|
163
|
+
# before_destroy do
|
164
|
+
# throw :abort if still_active?
|
165
|
+
# end
|
110
166
|
# end
|
111
167
|
#
|
168
|
+
# User.first.destroy! # => raises an ActiveRecord::RecordNotDestroyed
|
112
169
|
class RecordNotDestroyed < ActiveRecordError
|
113
170
|
attr_reader :record
|
114
171
|
|
@@ -118,17 +175,36 @@ module ActiveRecord
|
|
118
175
|
end
|
119
176
|
end
|
120
177
|
|
178
|
+
# Raised when Active Record finds multiple records but only expected one.
|
179
|
+
class SoleRecordExceeded < ActiveRecordError
|
180
|
+
attr_reader :record
|
181
|
+
|
182
|
+
def initialize(record = nil)
|
183
|
+
@record = record
|
184
|
+
super "Wanted only one #{record&.name || "record"}"
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
121
188
|
# Superclass for all database execution errors.
|
122
189
|
#
|
123
190
|
# Wraps the underlying database error as +cause+.
|
124
|
-
class StatementInvalid <
|
125
|
-
def initialize(message = nil, sql: nil, binds: nil)
|
126
|
-
super(message || $!&.message)
|
191
|
+
class StatementInvalid < AdapterError
|
192
|
+
def initialize(message = nil, sql: nil, binds: nil, connection_pool: nil)
|
193
|
+
super(message || $!&.message, connection_pool: connection_pool)
|
127
194
|
@sql = sql
|
128
195
|
@binds = binds
|
129
196
|
end
|
130
197
|
|
131
198
|
attr_reader :sql, :binds
|
199
|
+
|
200
|
+
def set_query(sql, binds)
|
201
|
+
unless @sql
|
202
|
+
@sql = sql
|
203
|
+
@binds = binds
|
204
|
+
end
|
205
|
+
|
206
|
+
self
|
207
|
+
end
|
132
208
|
end
|
133
209
|
|
134
210
|
# Defunct wrapper class kept for compatibility.
|
@@ -155,8 +231,13 @@ module ActiveRecord
|
|
155
231
|
foreign_key: nil,
|
156
232
|
target_table: nil,
|
157
233
|
primary_key: nil,
|
158
|
-
primary_key_column: nil
|
234
|
+
primary_key_column: nil,
|
235
|
+
query_parser: nil,
|
236
|
+
connection_pool: nil
|
159
237
|
)
|
238
|
+
@original_message = message
|
239
|
+
@query_parser = query_parser
|
240
|
+
|
160
241
|
if table
|
161
242
|
type = primary_key_column.bigint? ? :bigint : primary_key_column.type
|
162
243
|
msg = <<~EOM.squish
|
@@ -174,7 +255,24 @@ module ActiveRecord
|
|
174
255
|
if message
|
175
256
|
msg << "\nOriginal message: #{message}"
|
176
257
|
end
|
177
|
-
|
258
|
+
|
259
|
+
super(msg, sql: sql, binds: binds, connection_pool: connection_pool)
|
260
|
+
end
|
261
|
+
|
262
|
+
def set_query(sql, binds)
|
263
|
+
if @query_parser && !@sql
|
264
|
+
self.class.new(
|
265
|
+
message: @original_message,
|
266
|
+
sql: sql,
|
267
|
+
binds: binds,
|
268
|
+
connection_pool: @connection_pool,
|
269
|
+
**@query_parser.call(sql)
|
270
|
+
).tap do |exception|
|
271
|
+
exception.set_backtrace backtrace
|
272
|
+
end
|
273
|
+
else
|
274
|
+
super
|
275
|
+
end
|
178
276
|
end
|
179
277
|
end
|
180
278
|
|
@@ -190,6 +288,19 @@ module ActiveRecord
|
|
190
288
|
class RangeError < StatementInvalid
|
191
289
|
end
|
192
290
|
|
291
|
+
# Raised when a statement produces an SQL warning.
|
292
|
+
class SQLWarning < AdapterError
|
293
|
+
attr_reader :code, :level
|
294
|
+
attr_accessor :sql
|
295
|
+
|
296
|
+
def initialize(message = nil, code = nil, level = nil, sql = nil, connection_pool = nil)
|
297
|
+
super(message, connection_pool: connection_pool)
|
298
|
+
@code = code
|
299
|
+
@level = level
|
300
|
+
@sql = sql
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
193
304
|
# Raised when the number of placeholders in an SQL fragment passed to
|
194
305
|
# {ActiveRecord::Base.where}[rdoc-ref:QueryMethods#where]
|
195
306
|
# does not match the number of values supplied.
|
@@ -202,6 +313,31 @@ module ActiveRecord
|
|
202
313
|
|
203
314
|
# Raised when a given database does not exist.
|
204
315
|
class NoDatabaseError < StatementInvalid
|
316
|
+
include ActiveSupport::ActionableError
|
317
|
+
|
318
|
+
action "Create database" do
|
319
|
+
ActiveRecord::Tasks::DatabaseTasks.create_current
|
320
|
+
end
|
321
|
+
|
322
|
+
def initialize(message = nil, connection_pool: nil)
|
323
|
+
super(message || "Database not found", connection_pool: connection_pool)
|
324
|
+
end
|
325
|
+
|
326
|
+
class << self
|
327
|
+
def db_error(db_name)
|
328
|
+
NoDatabaseError.new(<<~MSG)
|
329
|
+
We could not find your database: #{db_name}. Available database configurations can be found in config/database.yml.
|
330
|
+
|
331
|
+
To resolve this error:
|
332
|
+
|
333
|
+
- Did you not create the database, or did you delete it? To create the database, run:
|
334
|
+
|
335
|
+
bin/rails db:create
|
336
|
+
|
337
|
+
- Has the database name changed? Verify that config/database.yml contains the correct database name.
|
338
|
+
MSG
|
339
|
+
end
|
340
|
+
end
|
205
341
|
end
|
206
342
|
|
207
343
|
# Raised when creating a database if it exists.
|
@@ -246,6 +382,12 @@ module ActiveRecord
|
|
246
382
|
end
|
247
383
|
|
248
384
|
# Raised on attempt to lazily load records that are marked as strict loading.
|
385
|
+
#
|
386
|
+
# You can resolve this error by eager loading marked records before accessing
|
387
|
+
# them. The
|
388
|
+
# {Eager Loading Associations}[https://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations]
|
389
|
+
# guide covers solutions, such as using
|
390
|
+
# {ActiveRecord::Base.includes}[rdoc-ref:QueryMethods#includes].
|
249
391
|
class StrictLoadingViolationError < ActiveRecordError
|
250
392
|
end
|
251
393
|
|
@@ -268,7 +410,7 @@ module ActiveRecord
|
|
268
410
|
# # The system must fail on Friday so that our support department
|
269
411
|
# # won't be out of job. We silently rollback this transaction
|
270
412
|
# # without telling the user.
|
271
|
-
# raise ActiveRecord::Rollback
|
413
|
+
# raise ActiveRecord::Rollback
|
272
414
|
# end
|
273
415
|
# end
|
274
416
|
# # ActiveRecord::Rollback is the only exception that won't be passed on
|
@@ -338,10 +480,15 @@ module ActiveRecord
|
|
338
480
|
# relation.loaded? # => true
|
339
481
|
#
|
340
482
|
# # Methods which try to mutate a loaded relation fail.
|
341
|
-
# relation.where!(title: 'TODO') # => ActiveRecord::
|
342
|
-
# relation.limit!(5) # => ActiveRecord::
|
343
|
-
class
|
483
|
+
# relation.where!(title: 'TODO') # => ActiveRecord::UnmodifiableRelation
|
484
|
+
# relation.limit!(5) # => ActiveRecord::UnmodifiableRelation
|
485
|
+
class UnmodifiableRelation < ActiveRecordError
|
344
486
|
end
|
487
|
+
deprecate_constant(
|
488
|
+
:ImmutableRelation,
|
489
|
+
"ActiveRecord::UnmodifiableRelation",
|
490
|
+
deprecator: ActiveRecord.deprecator
|
491
|
+
)
|
345
492
|
|
346
493
|
# TransactionIsolationError will be raised under the following conditions:
|
347
494
|
#
|
@@ -349,13 +496,26 @@ module ActiveRecord
|
|
349
496
|
# * You are joining an existing open transaction
|
350
497
|
# * You are creating a nested (savepoint) transaction
|
351
498
|
#
|
352
|
-
# The mysql2 and postgresql adapters support setting the transaction isolation level.
|
499
|
+
# The mysql2, trilogy, and postgresql adapters support setting the transaction isolation level.
|
353
500
|
class TransactionIsolationError < ActiveRecordError
|
354
501
|
end
|
355
502
|
|
356
503
|
# TransactionRollbackError will be raised when a transaction is rolled
|
357
504
|
# back by the database due to a serialization failure or a deadlock.
|
358
505
|
#
|
506
|
+
# These exceptions should not be generally rescued in nested transaction
|
507
|
+
# blocks, because they have side-effects in the actual enclosing transaction
|
508
|
+
# and internal Active Record state. They can be rescued if you are above the
|
509
|
+
# root transaction block, though.
|
510
|
+
#
|
511
|
+
# In that case, beware of transactional tests, however, because they run test
|
512
|
+
# cases in their own umbrella transaction. If you absolutely need to handle
|
513
|
+
# these exceptions in tests please consider disabling transactional tests in
|
514
|
+
# the affected test class (<tt>self.use_transactional_tests = false</tt>).
|
515
|
+
#
|
516
|
+
# Due to the aforementioned side-effects, this exception should not be raised
|
517
|
+
# manually by users.
|
518
|
+
#
|
359
519
|
# See the following:
|
360
520
|
#
|
361
521
|
# * https://www.postgresql.org/docs/current/static/transaction-iso.html
|
@@ -363,13 +523,24 @@ module ActiveRecord
|
|
363
523
|
class TransactionRollbackError < StatementInvalid
|
364
524
|
end
|
365
525
|
|
526
|
+
# AsynchronousQueryInsideTransactionError will be raised when attempting
|
527
|
+
# to perform an asynchronous query from inside a transaction
|
528
|
+
class AsynchronousQueryInsideTransactionError < ActiveRecordError
|
529
|
+
end
|
530
|
+
|
366
531
|
# SerializationFailure will be raised when a transaction is rolled
|
367
532
|
# back by the database due to a serialization failure.
|
533
|
+
#
|
534
|
+
# This is a subclass of TransactionRollbackError, please make sure to check
|
535
|
+
# its documentation to be aware of its caveats.
|
368
536
|
class SerializationFailure < TransactionRollbackError
|
369
537
|
end
|
370
538
|
|
371
539
|
# Deadlocked will be raised when a transaction is rolled
|
372
540
|
# back by the database when a deadlock is encountered.
|
541
|
+
#
|
542
|
+
# This is a subclass of TransactionRollbackError, please make sure to check
|
543
|
+
# its documentation to be aware of its caveats.
|
373
544
|
class Deadlocked < TransactionRollbackError
|
374
545
|
end
|
375
546
|
|
@@ -398,6 +569,11 @@ module ActiveRecord
|
|
398
569
|
class AdapterTimeout < QueryAborted
|
399
570
|
end
|
400
571
|
|
572
|
+
# ConnectionFailed will be raised when the network connection to the
|
573
|
+
# database fails while sending a query or waiting for its result.
|
574
|
+
class ConnectionFailed < QueryAborted
|
575
|
+
end
|
576
|
+
|
401
577
|
# UnknownAttributeReference is raised when an unknown and potentially unsafe
|
402
578
|
# value is passed to a query method. For example, passing a non column name
|
403
579
|
# value to a relation's #order method might cause this exception.
|
@@ -409,15 +585,22 @@ module ActiveRecord
|
|
409
585
|
#
|
410
586
|
# For example, the following code would raise this exception:
|
411
587
|
#
|
412
|
-
# Post.order("
|
588
|
+
# Post.order("REPLACE(title, 'misc', 'zzzz') asc").pluck(:id)
|
413
589
|
#
|
414
590
|
# The desired result can be accomplished by wrapping the known-safe string
|
415
591
|
# in Arel.sql:
|
416
592
|
#
|
417
|
-
# Post.order(Arel.sql("
|
593
|
+
# Post.order(Arel.sql("REPLACE(title, 'misc', 'zzzz') asc")).pluck(:id)
|
418
594
|
#
|
419
595
|
# Again, such a workaround should *not* be used when passing user-provided
|
420
596
|
# values, such as request parameters or model attributes to query methods.
|
421
597
|
class UnknownAttributeReference < ActiveRecordError
|
422
598
|
end
|
599
|
+
|
600
|
+
# DatabaseVersionError will be raised when the database version is not supported, or when
|
601
|
+
# the database version cannot be determined.
|
602
|
+
class DatabaseVersionError < ActiveRecordError
|
603
|
+
end
|
423
604
|
end
|
605
|
+
|
606
|
+
require "active_record/associations/errors"
|
@@ -16,17 +16,18 @@ module ActiveRecord
|
|
16
16
|
|
17
17
|
# Makes the adapter execute EXPLAIN for the tuples of queries and bindings.
|
18
18
|
# Returns a formatted string ready to be logged.
|
19
|
-
def exec_explain(queries) # :nodoc:
|
20
|
-
str =
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
19
|
+
def exec_explain(queries, options = []) # :nodoc:
|
20
|
+
str = with_connection do |c|
|
21
|
+
queries.map do |sql, binds|
|
22
|
+
msg = +"#{build_explain_clause(c, options)} #{sql}"
|
23
|
+
unless binds.empty?
|
24
|
+
msg << " "
|
25
|
+
msg << binds.map { |attr| render_bind(c, attr) }.inspect
|
26
|
+
end
|
27
|
+
msg << "\n"
|
28
|
+
msg << c.explain(sql, binds, options)
|
29
|
+
end.join("\n")
|
30
|
+
end
|
30
31
|
# Overriding inspect to be more human readable, especially in the console.
|
31
32
|
def str.inspect
|
32
33
|
self
|
@@ -36,7 +37,7 @@ module ActiveRecord
|
|
36
37
|
end
|
37
38
|
|
38
39
|
private
|
39
|
-
def render_bind(attr)
|
40
|
+
def render_bind(connection, attr)
|
40
41
|
if ActiveModel::Attribute === attr
|
41
42
|
value = if attr.type.binary? && attr.value
|
42
43
|
"<#{attr.value_for_database.to_s.bytesize} bytes of binary data>"
|
@@ -50,5 +51,13 @@ module ActiveRecord
|
|
50
51
|
|
51
52
|
[attr&.name, value]
|
52
53
|
end
|
54
|
+
|
55
|
+
def build_explain_clause(connection, options = [])
|
56
|
+
if connection.respond_to?(:build_explain_clause, true)
|
57
|
+
connection.build_explain_clause(options)
|
58
|
+
else
|
59
|
+
"EXPLAIN for:"
|
60
|
+
end
|
61
|
+
end
|
53
62
|
end
|
54
63
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/
|
3
|
+
require "active_support/core_ext/module/delegation"
|
4
4
|
|
5
5
|
module ActiveRecord
|
6
6
|
# This is a thread locals registry for EXPLAIN. For example
|
@@ -8,13 +8,18 @@ module ActiveRecord
|
|
8
8
|
# ActiveRecord::ExplainRegistry.queries
|
9
9
|
#
|
10
10
|
# returns the collected queries local to the current thread.
|
11
|
-
#
|
12
|
-
# See the documentation of ActiveSupport::PerThreadRegistry
|
13
|
-
# for further details.
|
14
11
|
class ExplainRegistry # :nodoc:
|
15
|
-
|
12
|
+
class << self
|
13
|
+
delegate :reset, :collect, :collect=, :collect?, :queries, to: :instance
|
14
|
+
|
15
|
+
private
|
16
|
+
def instance
|
17
|
+
ActiveSupport::IsolatedExecutionState[:active_record_explain_registry] ||= new
|
18
|
+
end
|
19
|
+
end
|
16
20
|
|
17
|
-
attr_accessor :
|
21
|
+
attr_accessor :collect
|
22
|
+
attr_reader :queries
|
18
23
|
|
19
24
|
def initialize
|
20
25
|
reset
|
@@ -21,7 +21,7 @@ module ActiveRecord
|
|
21
21
|
# On the other hand, we want to monitor the performance of our real database
|
22
22
|
# queries, not the performance of the access to the query cache.
|
23
23
|
IGNORED_PAYLOADS = %w(SCHEMA EXPLAIN)
|
24
|
-
EXPLAINED_SQLS = /\A\s*(with|select|update|delete|insert)\b/i
|
24
|
+
EXPLAINED_SQLS = /\A\s*(\/\*.*\*\/)?\s*(with|select|update|delete|insert)\b/i
|
25
25
|
def ignore_payload?(payload)
|
26
26
|
payload[:exception] ||
|
27
27
|
payload[:cached] ||
|
@@ -41,7 +41,7 @@ module ActiveRecord
|
|
41
41
|
@config_row ||= begin
|
42
42
|
row = raw_rows.find { |fixture_name, _| fixture_name == "_fixture" }
|
43
43
|
if row
|
44
|
-
row.last
|
44
|
+
validate_config_row(row.last)
|
45
45
|
else
|
46
46
|
{ 'model_class': nil, 'ignore': nil }
|
47
47
|
end
|
@@ -58,6 +58,20 @@ module ActiveRecord
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
+
def validate_config_row(data)
|
62
|
+
unless Hash === data
|
63
|
+
raise Fixture::FormatError, "Invalid `_fixture` section: `_fixture` must be a hash: #{@file}"
|
64
|
+
end
|
65
|
+
|
66
|
+
begin
|
67
|
+
data.assert_valid_keys("model_class", "ignore")
|
68
|
+
rescue ArgumentError => error
|
69
|
+
raise Fixture::FormatError, "Invalid `_fixture` section: #{error.message}: #{@file}"
|
70
|
+
end
|
71
|
+
|
72
|
+
data
|
73
|
+
end
|
74
|
+
|
61
75
|
# Validate our unmarshalled data.
|
62
76
|
def validate(data)
|
63
77
|
unless Hash === data || YAML::Omap === data
|
@@ -12,12 +12,22 @@ module ActiveRecord
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def primary_key_type
|
15
|
-
@primary_key_type ||= @model_class &&
|
15
|
+
@primary_key_type ||= @model_class && column_type(@model_class.primary_key)
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
19
|
-
@
|
20
|
-
|
18
|
+
def column_type(column_name)
|
19
|
+
@column_type ||= {}
|
20
|
+
return @column_type[column_name] if @column_type.key?(column_name)
|
21
|
+
|
22
|
+
@column_type[column_name] = @model_class && @model_class.type_for_attribute(column_name).type
|
23
|
+
end
|
24
|
+
|
25
|
+
def has_column?(column_name)
|
26
|
+
column_names.include?(column_name)
|
27
|
+
end
|
28
|
+
|
29
|
+
def column_names
|
30
|
+
@column_names ||= @model_class ? @model_class.columns.map(&:name).to_set : Set.new
|
21
31
|
end
|
22
32
|
|
23
33
|
def timestamp_column_names
|
@@ -33,6 +33,33 @@ module ActiveRecord
|
|
33
33
|
def join_table
|
34
34
|
@association.through_reflection.table_name
|
35
35
|
end
|
36
|
+
|
37
|
+
def timestamp_column_names
|
38
|
+
@association.through_reflection.klass.all_timestamp_attributes_in_model
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class PrimaryKeyError < StandardError # :nodoc:
|
43
|
+
def initialize(label, association, value)
|
44
|
+
super(<<~MSG)
|
45
|
+
Unable to set #{association.name} to #{value} because the association has a
|
46
|
+
custom primary key (#{association.join_primary_key}) that does not match the
|
47
|
+
associated table's primary key (#{association.klass.primary_key}).
|
48
|
+
|
49
|
+
To fix this, change your fixture from
|
50
|
+
|
51
|
+
#{label}:
|
52
|
+
#{association.name}: #{value}
|
53
|
+
|
54
|
+
to
|
55
|
+
|
56
|
+
#{label}:
|
57
|
+
#{association.foreign_key}: **value**
|
58
|
+
|
59
|
+
where **value** is the #{association.join_primary_key} value for the
|
60
|
+
associated #{association.klass.name} record.
|
61
|
+
MSG
|
62
|
+
end
|
36
63
|
end
|
37
64
|
|
38
65
|
def initialize(fixture, table_rows:, label:, now:)
|
@@ -60,7 +87,7 @@ module ActiveRecord
|
|
60
87
|
return unless model_class
|
61
88
|
fill_timestamps
|
62
89
|
interpolate_label
|
63
|
-
generate_primary_key
|
90
|
+
model_class.composite_primary_key? ? generate_composite_primary_key : generate_primary_key
|
64
91
|
resolve_enums
|
65
92
|
resolve_sti_reflections
|
66
93
|
end
|
@@ -90,16 +117,28 @@ module ActiveRecord
|
|
90
117
|
end
|
91
118
|
|
92
119
|
def generate_primary_key
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
120
|
+
pk = model_metadata.primary_key_name
|
121
|
+
|
122
|
+
unless column_defined?(pk)
|
123
|
+
@row[pk] = ActiveRecord::FixtureSet.identify(@label, model_metadata.column_type(pk))
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def generate_composite_primary_key
|
128
|
+
composite_key = ActiveRecord::FixtureSet.composite_identify(@label, model_metadata.primary_key_name)
|
129
|
+
composite_key.each do |column, value|
|
130
|
+
next if column_defined?(column)
|
131
|
+
|
132
|
+
@row[column] = value
|
98
133
|
end
|
99
134
|
end
|
100
135
|
|
136
|
+
def column_defined?(col)
|
137
|
+
!model_metadata.has_column?(col) || @row.include?(col)
|
138
|
+
end
|
139
|
+
|
101
140
|
def resolve_enums
|
102
|
-
|
141
|
+
reflection_class.defined_enums.each do |name, values|
|
103
142
|
if @row.include?(name)
|
104
143
|
@row[name] = values.fetch(@row[name], @row[name])
|
105
144
|
end
|
@@ -115,13 +154,26 @@ module ActiveRecord
|
|
115
154
|
fk_name = association.join_foreign_key
|
116
155
|
|
117
156
|
if association.name.to_s != fk_name && value = @row.delete(association.name.to_s)
|
118
|
-
if association.polymorphic?
|
119
|
-
|
120
|
-
|
157
|
+
if association.polymorphic?
|
158
|
+
if value.sub!(/\s*\(([^)]*)\)\s*$/, "")
|
159
|
+
# support polymorphic belongs_to as "label (Type)"
|
160
|
+
@row[association.join_foreign_type] = $1
|
161
|
+
end
|
162
|
+
elsif association.join_primary_key != association.klass.primary_key
|
163
|
+
raise PrimaryKeyError.new(@label, association, value)
|
121
164
|
end
|
122
165
|
|
123
|
-
|
124
|
-
|
166
|
+
if fk_name.is_a?(Array)
|
167
|
+
composite_key = ActiveRecord::FixtureSet.composite_identify(value, fk_name)
|
168
|
+
composite_key.each do |column, value|
|
169
|
+
next if column_defined?(column)
|
170
|
+
|
171
|
+
@row[column] = value
|
172
|
+
end
|
173
|
+
else
|
174
|
+
fk_type = reflection_class.type_for_attribute(fk_name).type
|
175
|
+
@row[fk_name] = ActiveRecord::FixtureSet.identify(value, fk_type)
|
176
|
+
end
|
125
177
|
end
|
126
178
|
when :has_many
|
127
179
|
if association.options[:through]
|
@@ -141,8 +193,12 @@ module ActiveRecord
|
|
141
193
|
|
142
194
|
targets = targets.is_a?(Array) ? targets : targets.split(/\s*,\s*/)
|
143
195
|
joins = targets.map do |target|
|
144
|
-
{ lhs_key => @row[model_metadata.primary_key_name],
|
145
|
-
|
196
|
+
join = { lhs_key => @row[model_metadata.primary_key_name],
|
197
|
+
rhs_key => ActiveRecord::FixtureSet.identify(target, column_type) }
|
198
|
+
association.timestamp_column_names.each do |col|
|
199
|
+
join[col] = @now
|
200
|
+
end
|
201
|
+
join
|
146
202
|
end
|
147
203
|
@table_rows.tables[table_name].concat(joins)
|
148
204
|
end
|