activerecord 7.0.8 → 7.2.0
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 +530 -2004
- data/MIT-LICENSE +1 -1
- data/README.rdoc +29 -29
- data/examples/performance.rb +2 -2
- data/lib/active_record/aggregations.rb +16 -13
- data/lib/active_record/association_relation.rb +2 -2
- data/lib/active_record/associations/alias_tracker.rb +25 -19
- data/lib/active_record/associations/association.rb +35 -12
- data/lib/active_record/associations/association_scope.rb +16 -9
- data/lib/active_record/associations/belongs_to_association.rb +23 -8
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
- data/lib/active_record/associations/builder/association.rb +3 -3
- data/lib/active_record/associations/builder/belongs_to.rb +22 -8
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -7
- data/lib/active_record/associations/builder/has_many.rb +3 -4
- data/lib/active_record/associations/builder/has_one.rb +3 -4
- data/lib/active_record/associations/builder/singular_association.rb +4 -0
- data/lib/active_record/associations/collection_association.rb +26 -14
- data/lib/active_record/associations/collection_proxy.rb +29 -11
- 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 +21 -14
- data/lib/active_record/associations/has_many_through_association.rb +10 -6
- data/lib/active_record/associations/has_one_association.rb +10 -3
- data/lib/active_record/associations/join_dependency/join_association.rb +27 -25
- data/lib/active_record/associations/join_dependency.rb +5 -5
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +33 -8
- data/lib/active_record/associations/preloader/branch.rb +7 -1
- data/lib/active_record/associations/preloader/through_association.rb +1 -3
- data/lib/active_record/associations/preloader.rb +13 -10
- data/lib/active_record/associations/singular_association.rb +7 -1
- data/lib/active_record/associations/through_association.rb +22 -11
- data/lib/active_record/associations.rb +328 -471
- data/lib/active_record/attribute_assignment.rb +1 -13
- data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +53 -35
- data/lib/active_record/attribute_methods/primary_key.rb +45 -25
- data/lib/active_record/attribute_methods/query.rb +28 -16
- data/lib/active_record/attribute_methods/read.rb +8 -7
- data/lib/active_record/attribute_methods/serialization.rb +131 -32
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +7 -6
- data/lib/active_record/attribute_methods/write.rb +6 -6
- data/lib/active_record/attribute_methods.rb +148 -33
- data/lib/active_record/attributes.rb +58 -45
- data/lib/active_record/autosave_association.rb +69 -37
- data/lib/active_record/base.rb +9 -5
- data/lib/active_record/callbacks.rb +10 -24
- 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 -42
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +123 -131
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +4 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +317 -88
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +160 -45
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +188 -63
- data/lib/active_record/connection_adapters/abstract/quoting.rb +72 -63
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +18 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +137 -11
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +306 -128
- data/lib/active_record/connection_adapters/abstract/transaction.rb +367 -75
- data/lib/active_record/connection_adapters/abstract_adapter.rb +510 -111
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +274 -125
- data/lib/active_record/connection_adapters/column.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +26 -139
- data/lib/active_record/connection_adapters/mysql/quoting.rb +53 -54
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +6 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +25 -13
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +101 -68
- data/lib/active_record/connection_adapters/pool_config.rb +20 -10
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +14 -3
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +100 -43
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
- 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 +11 -2
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +65 -61
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +3 -9
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +151 -2
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +53 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +368 -63
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +364 -198
- data/lib/active_record/connection_adapters/schema_cache.rb +302 -79
- data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +60 -43
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +45 -46
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +14 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +50 -8
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +290 -110
- 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 +124 -1
- data/lib/active_record/connection_handling.rb +96 -104
- data/lib/active_record/core.rb +217 -174
- data/lib/active_record/counter_cache.rb +68 -34
- data/lib/active_record/database_configurations/connection_url_resolver.rb +7 -2
- data/lib/active_record/database_configurations/database_config.rb +26 -5
- data/lib/active_record/database_configurations/hash_config.rb +52 -34
- data/lib/active_record/database_configurations/url_config.rb +37 -12
- data/lib/active_record/database_configurations.rb +87 -34
- data/lib/active_record/delegated_type.rb +39 -10
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +3 -1
- data/lib/active_record/dynamic_matchers.rb +2 -2
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +4 -1
- data/lib/active_record/encryption/config.rb +25 -1
- data/lib/active_record/encryption/configurable.rb +12 -19
- data/lib/active_record/encryption/context.rb +10 -3
- data/lib/active_record/encryption/contexts.rb +5 -1
- data/lib/active_record/encryption/derived_secret_key_provider.rb +8 -2
- data/lib/active_record/encryption/encryptable_record.rb +44 -20
- data/lib/active_record/encryption/encrypted_attribute_type.rb +45 -10
- data/lib/active_record/encryption/encryptor.rb +17 -2
- data/lib/active_record/encryption/extended_deterministic_queries.rb +66 -69
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +3 -3
- data/lib/active_record/encryption/key_generator.rb +12 -1
- data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +6 -0
- data/lib/active_record/encryption/null_encryptor.rb +4 -0
- data/lib/active_record/encryption/properties.rb +3 -3
- data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
- data/lib/active_record/encryption/scheme.rb +22 -21
- data/lib/active_record/encryption.rb +1 -0
- data/lib/active_record/enum.rb +122 -29
- data/lib/active_record/errors.rb +151 -31
- data/lib/active_record/explain.rb +21 -12
- 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 +29 -8
- data/lib/active_record/fixtures.rb +167 -97
- data/lib/active_record/future_result.rb +47 -8
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +34 -18
- data/lib/active_record/insert_all.rb +72 -22
- data/lib/active_record/integration.rb +11 -8
- data/lib/active_record/internal_metadata.rb +124 -20
- data/lib/active_record/locking/optimistic.rb +8 -7
- data/lib/active_record/locking/pessimistic.rb +5 -2
- data/lib/active_record/log_subscriber.rb +18 -22
- data/lib/active_record/marshalling.rb +56 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +4 -0
- data/lib/active_record/middleware/database_selector.rb +6 -8
- data/lib/active_record/middleware/shard_selector.rb +3 -1
- data/lib/active_record/migration/command_recorder.rb +106 -8
- data/lib/active_record/migration/compatibility.rb +147 -5
- 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/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +234 -117
- data/lib/active_record/model_schema.rb +88 -103
- data/lib/active_record/nested_attributes.rb +35 -9
- data/lib/active_record/normalization.rb +163 -0
- data/lib/active_record/persistence.rb +168 -339
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +19 -25
- data/lib/active_record/query_logs.rb +92 -52
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +33 -8
- data/lib/active_record/railtie.rb +135 -86
- data/lib/active_record/railties/controller_runtime.rb +22 -7
- data/lib/active_record/railties/databases.rake +145 -154
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +32 -5
- data/lib/active_record/reflection.rb +259 -68
- data/lib/active_record/relation/batches/batch_enumerator.rb +20 -5
- data/lib/active_record/relation/batches.rb +196 -61
- data/lib/active_record/relation/calculations.rb +249 -92
- data/lib/active_record/relation/delegation.rb +30 -19
- data/lib/active_record/relation/finder_methods.rb +93 -18
- data/lib/active_record/relation/merger.rb +6 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +18 -3
- 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 +28 -16
- data/lib/active_record/relation/query_attribute.rb +2 -1
- data/lib/active_record/relation/query_methods.rb +548 -94
- data/lib/active_record/relation/record_fetch_warning.rb +3 -0
- data/lib/active_record/relation/spawn_methods.rb +5 -4
- data/lib/active_record/relation/where_clause.rb +7 -19
- data/lib/active_record/relation.rb +580 -90
- data/lib/active_record/result.rb +49 -48
- data/lib/active_record/runtime_registry.rb +63 -1
- data/lib/active_record/sanitization.rb +70 -25
- data/lib/active_record/schema.rb +8 -7
- data/lib/active_record/schema_dumper.rb +63 -14
- data/lib/active_record/schema_migration.rb +75 -24
- data/lib/active_record/scoping/default.rb +15 -5
- data/lib/active_record/scoping/named.rb +2 -2
- data/lib/active_record/scoping.rb +2 -1
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/signed_id.rb +27 -6
- data/lib/active_record/statement_cache.rb +7 -7
- data/lib/active_record/store.rb +8 -8
- data/lib/active_record/suppressor.rb +3 -1
- data/lib/active_record/table_metadata.rb +1 -1
- data/lib/active_record/tasks/database_tasks.rb +180 -119
- data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
- data/lib/active_record/tasks/postgresql_database_tasks.rb +16 -13
- data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -7
- data/lib/active_record/test_fixtures.rb +170 -155
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +31 -17
- 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 +106 -24
- data/lib/active_record/translation.rb +0 -2
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +1 -3
- data/lib/active_record/type/time.rb +4 -0
- 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 +9 -3
- 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 +60 -11
- data/lib/active_record/validations.rb +12 -5
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +247 -33
- data/lib/arel/alias_predication.rb +1 -1
- 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/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/nodes/binary.rb +6 -7
- data/lib/arel/nodes/bound_sql_literal.rb +65 -0
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/homogeneous_in.rb +1 -9
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/{and.rb → nary.rb} +5 -2
- data/lib/arel/nodes/node.rb +115 -5
- data/lib/arel/nodes/sql_literal.rb +13 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes.rb +6 -2
- data/lib/arel/predications.rb +3 -1
- data/lib/arel/select_manager.rb +1 -1
- data/lib/arel/table.rb +9 -5
- data/lib/arel/tree_manager.rb +8 -3
- data/lib/arel/update_manager.rb +2 -1
- data/lib/arel/visitors/dot.rb +1 -0
- data/lib/arel/visitors/mysql.rb +17 -5
- data/lib/arel/visitors/postgresql.rb +1 -12
- data/lib/arel/visitors/to_sql.rb +112 -34
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +21 -3
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- 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
- metadata +56 -14
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -63
|
@@ -10,7 +10,7 @@ module ActiveRecord
|
|
|
10
10
|
class Scheme
|
|
11
11
|
attr_accessor :previous_schemes
|
|
12
12
|
|
|
13
|
-
def initialize(key_provider: nil, key: nil, deterministic: nil, downcase: nil, ignore_case: nil,
|
|
13
|
+
def initialize(key_provider: nil, key: nil, deterministic: nil, support_unencrypted_data: nil, downcase: nil, ignore_case: nil,
|
|
14
14
|
previous_schemes: nil, **context_properties)
|
|
15
15
|
# Initializing all attributes to +nil+ as we want to allow a "not set" semantics so that we
|
|
16
16
|
# can merge schemes without overriding values with defaults. See +#merge+
|
|
@@ -18,6 +18,7 @@ module ActiveRecord
|
|
|
18
18
|
@key_provider_param = key_provider
|
|
19
19
|
@key = key
|
|
20
20
|
@deterministic = deterministic
|
|
21
|
+
@support_unencrypted_data = support_unencrypted_data
|
|
21
22
|
@downcase = downcase || ignore_case
|
|
22
23
|
@ignore_case = ignore_case
|
|
23
24
|
@previous_schemes_param = previous_schemes
|
|
@@ -36,7 +37,11 @@ module ActiveRecord
|
|
|
36
37
|
end
|
|
37
38
|
|
|
38
39
|
def deterministic?
|
|
39
|
-
|
|
40
|
+
!!@deterministic
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def support_unencrypted_data?
|
|
44
|
+
@support_unencrypted_data.nil? ? ActiveRecord::Encryption.config.support_unencrypted_data : @support_unencrypted_data
|
|
40
45
|
end
|
|
41
46
|
|
|
42
47
|
def fixed?
|
|
@@ -45,10 +50,7 @@ module ActiveRecord
|
|
|
45
50
|
end
|
|
46
51
|
|
|
47
52
|
def key_provider
|
|
48
|
-
@
|
|
49
|
-
validate_keys!
|
|
50
|
-
@key_provider_param || build_key_provider
|
|
51
|
-
end
|
|
53
|
+
@key_provider_param || key_provider_from_key || deterministic_key_provider || default_key_provider
|
|
52
54
|
end
|
|
53
55
|
|
|
54
56
|
def merge(other_scheme)
|
|
@@ -56,7 +58,7 @@ module ActiveRecord
|
|
|
56
58
|
end
|
|
57
59
|
|
|
58
60
|
def to_h
|
|
59
|
-
{ key_provider: @key_provider_param,
|
|
61
|
+
{ key_provider: @key_provider_param, deterministic: @deterministic, downcase: @downcase, ignore_case: @ignore_case,
|
|
60
62
|
previous_schemes: @previous_schemes_param, **@context_properties }.compact
|
|
61
63
|
end
|
|
62
64
|
|
|
@@ -68,31 +70,30 @@ module ActiveRecord
|
|
|
68
70
|
end
|
|
69
71
|
end
|
|
70
72
|
|
|
73
|
+
def compatible_with?(other_scheme)
|
|
74
|
+
deterministic? == other_scheme.deterministic?
|
|
75
|
+
end
|
|
76
|
+
|
|
71
77
|
private
|
|
72
78
|
def validate_config!
|
|
73
79
|
raise Errors::Configuration, "ignore_case: can only be used with deterministic encryption" if @ignore_case && !@deterministic
|
|
74
80
|
raise Errors::Configuration, "key_provider: and key: can't be used simultaneously" if @key_provider_param && @key
|
|
75
81
|
end
|
|
76
82
|
|
|
77
|
-
def
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
83
|
+
def key_provider_from_key
|
|
84
|
+
@key_provider_from_key ||= if @key.present?
|
|
85
|
+
DerivedSecretKeyProvider.new(@key)
|
|
86
|
+
end
|
|
81
87
|
end
|
|
82
88
|
|
|
83
|
-
def
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
"active_record_encryption.#{key} or by setting config.active_record.encryption.#{key}"
|
|
89
|
+
def deterministic_key_provider
|
|
90
|
+
@deterministic_key_provider ||= if @deterministic
|
|
91
|
+
DeterministicKeyProvider.new(ActiveRecord::Encryption.config.deterministic_key)
|
|
87
92
|
end
|
|
88
93
|
end
|
|
89
94
|
|
|
90
|
-
def
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if @deterministic && (deterministic_key = ActiveRecord::Encryption.config.deterministic_key)
|
|
94
|
-
DeterministicKeyProvider.new(deterministic_key)
|
|
95
|
-
end
|
|
95
|
+
def default_key_provider
|
|
96
|
+
ActiveRecord::Encryption.key_provider
|
|
96
97
|
end
|
|
97
98
|
end
|
|
98
99
|
end
|
data/lib/active_record/enum.rb
CHANGED
|
@@ -111,23 +111,70 @@ module ActiveRecord
|
|
|
111
111
|
#
|
|
112
112
|
# conversation.comments_inactive!
|
|
113
113
|
# conversation.comments_active? # => false
|
|
114
|
+
#
|
|
115
|
+
# If you want to disable the auto-generated methods on the model, you can do
|
|
116
|
+
# so by setting the +:instance_methods+ option to false:
|
|
117
|
+
#
|
|
118
|
+
# class Conversation < ActiveRecord::Base
|
|
119
|
+
# enum :status, [ :active, :archived ], instance_methods: false
|
|
120
|
+
# end
|
|
121
|
+
#
|
|
122
|
+
# If you want the enum value to be validated before saving, use the option +:validate+:
|
|
123
|
+
#
|
|
124
|
+
# class Conversation < ActiveRecord::Base
|
|
125
|
+
# enum :status, [ :active, :archived ], validate: true
|
|
126
|
+
# end
|
|
127
|
+
#
|
|
128
|
+
# conversation = Conversation.new
|
|
129
|
+
#
|
|
130
|
+
# conversation.status = :unknown
|
|
131
|
+
# conversation.valid? # => false
|
|
132
|
+
#
|
|
133
|
+
# conversation.status = nil
|
|
134
|
+
# conversation.valid? # => false
|
|
135
|
+
#
|
|
136
|
+
# conversation.status = :active
|
|
137
|
+
# conversation.valid? # => true
|
|
138
|
+
#
|
|
139
|
+
# It is also possible to pass additional validation options:
|
|
140
|
+
#
|
|
141
|
+
# class Conversation < ActiveRecord::Base
|
|
142
|
+
# enum :status, [ :active, :archived ], validate: { allow_nil: true }
|
|
143
|
+
# end
|
|
144
|
+
#
|
|
145
|
+
# conversation = Conversation.new
|
|
146
|
+
#
|
|
147
|
+
# conversation.status = :unknown
|
|
148
|
+
# conversation.valid? # => false
|
|
149
|
+
#
|
|
150
|
+
# conversation.status = nil
|
|
151
|
+
# conversation.valid? # => true
|
|
152
|
+
#
|
|
153
|
+
# conversation.status = :active
|
|
154
|
+
# conversation.valid? # => true
|
|
155
|
+
#
|
|
156
|
+
# Otherwise +ArgumentError+ will raise:
|
|
157
|
+
#
|
|
158
|
+
# class Conversation < ActiveRecord::Base
|
|
159
|
+
# enum :status, [ :active, :archived ]
|
|
160
|
+
# end
|
|
161
|
+
#
|
|
162
|
+
# conversation = Conversation.new
|
|
163
|
+
#
|
|
164
|
+
# conversation.status = :unknown # 'unknown' is not a valid status (ArgumentError)
|
|
114
165
|
module Enum
|
|
115
166
|
def self.extended(base) # :nodoc:
|
|
116
167
|
base.class_attribute(:defined_enums, instance_writer: false, default: {})
|
|
117
168
|
end
|
|
118
169
|
|
|
119
|
-
def inherited(base) # :nodoc:
|
|
120
|
-
base.defined_enums = defined_enums.deep_dup
|
|
121
|
-
super
|
|
122
|
-
end
|
|
123
|
-
|
|
124
170
|
class EnumType < Type::Value # :nodoc:
|
|
125
171
|
delegate :type, to: :subtype
|
|
126
172
|
|
|
127
|
-
def initialize(name, mapping, subtype)
|
|
173
|
+
def initialize(name, mapping, subtype, raise_on_invalid_values: true)
|
|
128
174
|
@name = name
|
|
129
175
|
@mapping = mapping
|
|
130
176
|
@subtype = subtype
|
|
177
|
+
@_raise_on_invalid_values = raise_on_invalid_values
|
|
131
178
|
end
|
|
132
179
|
|
|
133
180
|
def cast(value)
|
|
@@ -153,6 +200,8 @@ module ActiveRecord
|
|
|
153
200
|
end
|
|
154
201
|
|
|
155
202
|
def assert_valid_value(value)
|
|
203
|
+
return unless @_raise_on_invalid_values
|
|
204
|
+
|
|
156
205
|
unless value.blank? || mapping.has_key?(value) || mapping.has_value?(value)
|
|
157
206
|
raise ArgumentError, "'#{value}' is not a valid #{name}"
|
|
158
207
|
end
|
|
@@ -170,14 +219,26 @@ module ActiveRecord
|
|
|
170
219
|
return _enum(name, values, **options)
|
|
171
220
|
end
|
|
172
221
|
|
|
173
|
-
definitions = options.slice!(:_prefix, :_suffix, :_scopes, :_default)
|
|
222
|
+
definitions = options.slice!(:_prefix, :_suffix, :_scopes, :_default, :_instance_methods)
|
|
174
223
|
options.transform_keys! { |key| :"#{key[1..-1]}" }
|
|
175
224
|
|
|
176
225
|
definitions.each { |name, values| _enum(name, values, **options) }
|
|
226
|
+
|
|
227
|
+
ActiveRecord.deprecator.warn(<<~MSG)
|
|
228
|
+
Defining enums with keyword arguments is deprecated and will be removed
|
|
229
|
+
in Rails 8.0. Positional arguments should be used instead:
|
|
230
|
+
|
|
231
|
+
#{definitions.map { |name, values| "enum :#{name}, #{values}" }.join("\n")}
|
|
232
|
+
MSG
|
|
177
233
|
end
|
|
178
234
|
|
|
179
235
|
private
|
|
180
|
-
def
|
|
236
|
+
def inherited(base)
|
|
237
|
+
base.defined_enums = defined_enums.deep_dup
|
|
238
|
+
super
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def _enum(name, values, prefix: nil, suffix: nil, scopes: true, instance_methods: true, validate: false, **options)
|
|
181
242
|
assert_valid_enum_definition_values(values)
|
|
182
243
|
# statuses = { }
|
|
183
244
|
enum_values = ActiveSupport::HashWithIndifferentAccess.new
|
|
@@ -191,9 +252,17 @@ module ActiveRecord
|
|
|
191
252
|
detect_enum_conflict!(name, name)
|
|
192
253
|
detect_enum_conflict!(name, "#{name}=")
|
|
193
254
|
|
|
194
|
-
attribute(name, **options)
|
|
255
|
+
attribute(name, **options)
|
|
256
|
+
|
|
257
|
+
decorate_attributes([name]) do |_name, subtype|
|
|
258
|
+
if subtype == ActiveModel::Type.default_value
|
|
259
|
+
raise "Undeclared attribute type for enum '#{name}' in #{self.name}. Enums must be" \
|
|
260
|
+
" backed by a database column or declared with an explicit type" \
|
|
261
|
+
" via `attribute`."
|
|
262
|
+
end
|
|
263
|
+
|
|
195
264
|
subtype = subtype.subtype if EnumType === subtype
|
|
196
|
-
EnumType.new(name, enum_values, subtype)
|
|
265
|
+
EnumType.new(name, enum_values, subtype, raise_on_invalid_values: !validate)
|
|
197
266
|
end
|
|
198
267
|
|
|
199
268
|
value_method_names = []
|
|
@@ -213,18 +282,24 @@ module ActiveRecord
|
|
|
213
282
|
|
|
214
283
|
value_method_name = "#{prefix}#{label}#{suffix}"
|
|
215
284
|
value_method_names << value_method_name
|
|
216
|
-
define_enum_methods(name, value_method_name, value, scopes)
|
|
285
|
+
define_enum_methods(name, value_method_name, value, scopes, instance_methods)
|
|
217
286
|
|
|
218
287
|
method_friendly_label = label.gsub(/[\W&&[:ascii:]]+/, "_")
|
|
219
288
|
value_method_alias = "#{prefix}#{method_friendly_label}#{suffix}"
|
|
220
289
|
|
|
221
290
|
if value_method_alias != value_method_name && !value_method_names.include?(value_method_alias)
|
|
222
291
|
value_method_names << value_method_alias
|
|
223
|
-
define_enum_methods(name, value_method_alias, value, scopes)
|
|
292
|
+
define_enum_methods(name, value_method_alias, value, scopes, instance_methods)
|
|
224
293
|
end
|
|
225
294
|
end
|
|
226
295
|
end
|
|
227
296
|
detect_negative_enum_conditions!(value_method_names) if scopes
|
|
297
|
+
|
|
298
|
+
if validate
|
|
299
|
+
validate = {} unless Hash === validate
|
|
300
|
+
validates_inclusion_of name, in: enum_values.keys, **validate
|
|
301
|
+
end
|
|
302
|
+
|
|
228
303
|
enum_values.freeze
|
|
229
304
|
end
|
|
230
305
|
|
|
@@ -236,21 +311,23 @@ module ActiveRecord
|
|
|
236
311
|
private
|
|
237
312
|
attr_reader :klass
|
|
238
313
|
|
|
239
|
-
def define_enum_methods(name, value_method_name, value, scopes)
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
314
|
+
def define_enum_methods(name, value_method_name, value, scopes, instance_methods)
|
|
315
|
+
if instance_methods
|
|
316
|
+
# def active?() status_for_database == 0 end
|
|
317
|
+
klass.send(:detect_enum_conflict!, name, "#{value_method_name}?")
|
|
318
|
+
define_method("#{value_method_name}?") { public_send(:"#{name}_for_database") == value }
|
|
243
319
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
320
|
+
# def active!() update!(status: 0) end
|
|
321
|
+
klass.send(:detect_enum_conflict!, name, "#{value_method_name}!")
|
|
322
|
+
define_method("#{value_method_name}!") { update!(name => value) }
|
|
323
|
+
end
|
|
247
324
|
|
|
248
|
-
# scope :active, -> { where(status: 0) }
|
|
249
|
-
# scope :not_active, -> { where.not(status: 0) }
|
|
250
325
|
if scopes
|
|
326
|
+
# scope :active, -> { where(status: 0) }
|
|
251
327
|
klass.send(:detect_enum_conflict!, name, value_method_name, true)
|
|
252
328
|
klass.scope value_method_name, -> { where(name => value) }
|
|
253
329
|
|
|
330
|
+
# scope :not_active, -> { where.not(status: 0) }
|
|
254
331
|
klass.send(:detect_enum_conflict!, name, "not_#{value_method_name}", true)
|
|
255
332
|
klass.scope "not_#{value_method_name}", -> { where.not(name => value) }
|
|
256
333
|
end
|
|
@@ -267,15 +344,29 @@ module ActiveRecord
|
|
|
267
344
|
end
|
|
268
345
|
|
|
269
346
|
def assert_valid_enum_definition_values(values)
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
347
|
+
case values
|
|
348
|
+
when Hash
|
|
349
|
+
if values.empty?
|
|
350
|
+
raise ArgumentError, "Enum values #{values} must not be empty."
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
if values.keys.any?(&:blank?)
|
|
354
|
+
raise ArgumentError, "Enum values #{values} must not contain a blank name."
|
|
355
|
+
end
|
|
356
|
+
when Array
|
|
357
|
+
if values.empty?
|
|
358
|
+
raise ArgumentError, "Enum values #{values} must not be empty."
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
unless values.all?(Symbol) || values.all?(String)
|
|
362
|
+
raise ArgumentError, "Enum values #{values} must only contain symbols or strings."
|
|
363
|
+
end
|
|
276
364
|
|
|
277
|
-
|
|
278
|
-
|
|
365
|
+
if values.any?(&:blank?)
|
|
366
|
+
raise ArgumentError, "Enum values #{values} must not contain a blank name."
|
|
367
|
+
end
|
|
368
|
+
else
|
|
369
|
+
raise ArgumentError, "Enum values #{values} must be either a non-empty hash or an array."
|
|
279
370
|
end
|
|
280
371
|
end
|
|
281
372
|
|
|
@@ -290,6 +381,8 @@ module ActiveRecord
|
|
|
290
381
|
raise_conflict_error(enum_name, method_name, type: "class")
|
|
291
382
|
elsif klass_method && method_defined_within?(method_name, Relation)
|
|
292
383
|
raise_conflict_error(enum_name, method_name, type: "class", source: Relation.name)
|
|
384
|
+
elsif klass_method && method_name.to_sym == :id
|
|
385
|
+
raise_conflict_error(enum_name, method_name)
|
|
293
386
|
elsif !klass_method && dangerous_attribute_method?(method_name)
|
|
294
387
|
raise_conflict_error(enum_name, method_name)
|
|
295
388
|
elsif !klass_method && method_defined_within?(method_name, _enum_methods_module, Module)
|
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
|
|
@@ -90,7 +111,7 @@ module ActiveRecord
|
|
|
90
111
|
# Raised when a pool was unable to get ahold of all its connections
|
|
91
112
|
# to perform a "group" action such as
|
|
92
113
|
# {ActiveRecord::Base.connection_pool.disconnect!}[rdoc-ref:ConnectionAdapters::ConnectionPool#disconnect!]
|
|
93
|
-
# 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!].
|
|
94
115
|
class ExclusiveConnectionTimeoutError < ConnectionTimeoutError
|
|
95
116
|
end
|
|
96
117
|
|
|
@@ -112,8 +133,18 @@ module ActiveRecord
|
|
|
112
133
|
end
|
|
113
134
|
|
|
114
135
|
# Raised by {ActiveRecord::Base#save!}[rdoc-ref:Persistence#save!] and
|
|
115
|
-
# {ActiveRecord::Base.
|
|
116
|
-
# 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
|
|
117
148
|
class RecordNotSaved < ActiveRecordError
|
|
118
149
|
attr_reader :record
|
|
119
150
|
|
|
@@ -124,15 +155,17 @@ module ActiveRecord
|
|
|
124
155
|
end
|
|
125
156
|
|
|
126
157
|
# Raised by {ActiveRecord::Base#destroy!}[rdoc-ref:Persistence#destroy!]
|
|
127
|
-
# when a
|
|
128
|
-
#
|
|
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.
|
|
129
161
|
#
|
|
130
|
-
#
|
|
131
|
-
#
|
|
132
|
-
#
|
|
133
|
-
#
|
|
162
|
+
# class User < ActiveRecord::Base
|
|
163
|
+
# before_destroy do
|
|
164
|
+
# throw :abort if still_active?
|
|
165
|
+
# end
|
|
134
166
|
# end
|
|
135
167
|
#
|
|
168
|
+
# User.first.destroy! # => raises an ActiveRecord::RecordNotDestroyed
|
|
136
169
|
class RecordNotDestroyed < ActiveRecordError
|
|
137
170
|
attr_reader :record
|
|
138
171
|
|
|
@@ -155,14 +188,23 @@ module ActiveRecord
|
|
|
155
188
|
# Superclass for all database execution errors.
|
|
156
189
|
#
|
|
157
190
|
# Wraps the underlying database error as +cause+.
|
|
158
|
-
class StatementInvalid <
|
|
159
|
-
def initialize(message = nil, sql: nil, binds: nil)
|
|
160
|
-
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)
|
|
161
194
|
@sql = sql
|
|
162
195
|
@binds = binds
|
|
163
196
|
end
|
|
164
197
|
|
|
165
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
|
|
166
208
|
end
|
|
167
209
|
|
|
168
210
|
# Defunct wrapper class kept for compatibility.
|
|
@@ -189,8 +231,13 @@ module ActiveRecord
|
|
|
189
231
|
foreign_key: nil,
|
|
190
232
|
target_table: nil,
|
|
191
233
|
primary_key: nil,
|
|
192
|
-
primary_key_column: nil
|
|
234
|
+
primary_key_column: nil,
|
|
235
|
+
query_parser: nil,
|
|
236
|
+
connection_pool: nil
|
|
193
237
|
)
|
|
238
|
+
@original_message = message
|
|
239
|
+
@query_parser = query_parser
|
|
240
|
+
|
|
194
241
|
if table
|
|
195
242
|
type = primary_key_column.bigint? ? :bigint : primary_key_column.type
|
|
196
243
|
msg = <<~EOM.squish
|
|
@@ -208,7 +255,24 @@ module ActiveRecord
|
|
|
208
255
|
if message
|
|
209
256
|
msg << "\nOriginal message: #{message}"
|
|
210
257
|
end
|
|
211
|
-
|
|
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
|
|
212
276
|
end
|
|
213
277
|
end
|
|
214
278
|
|
|
@@ -224,6 +288,19 @@ module ActiveRecord
|
|
|
224
288
|
class RangeError < StatementInvalid
|
|
225
289
|
end
|
|
226
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
|
+
|
|
227
304
|
# Raised when the number of placeholders in an SQL fragment passed to
|
|
228
305
|
# {ActiveRecord::Base.where}[rdoc-ref:QueryMethods#where]
|
|
229
306
|
# does not match the number of values supplied.
|
|
@@ -242,21 +319,22 @@ module ActiveRecord
|
|
|
242
319
|
ActiveRecord::Tasks::DatabaseTasks.create_current
|
|
243
320
|
end
|
|
244
321
|
|
|
245
|
-
def initialize(message = nil)
|
|
246
|
-
super(message || "Database not found")
|
|
322
|
+
def initialize(message = nil, connection_pool: nil)
|
|
323
|
+
super(message || "Database not found", connection_pool: connection_pool)
|
|
247
324
|
end
|
|
248
325
|
|
|
249
326
|
class << self
|
|
250
327
|
def db_error(db_name)
|
|
251
328
|
NoDatabaseError.new(<<~MSG)
|
|
252
|
-
We could not find your database: #{db_name}.
|
|
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:
|
|
253
332
|
|
|
254
|
-
To
|
|
333
|
+
- Did you not create the database, or did you delete it? To create the database, run:
|
|
255
334
|
|
|
256
|
-
|
|
257
|
-
- Has the database name changed? Check your database.yml config has the correct database name.
|
|
335
|
+
bin/rails db:create
|
|
258
336
|
|
|
259
|
-
|
|
337
|
+
- Has the database name changed? Verify that config/database.yml contains the correct database name.
|
|
260
338
|
MSG
|
|
261
339
|
end
|
|
262
340
|
end
|
|
@@ -304,6 +382,12 @@ module ActiveRecord
|
|
|
304
382
|
end
|
|
305
383
|
|
|
306
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].
|
|
307
391
|
class StrictLoadingViolationError < ActiveRecordError
|
|
308
392
|
end
|
|
309
393
|
|
|
@@ -396,10 +480,15 @@ module ActiveRecord
|
|
|
396
480
|
# relation.loaded? # => true
|
|
397
481
|
#
|
|
398
482
|
# # Methods which try to mutate a loaded relation fail.
|
|
399
|
-
# relation.where!(title: 'TODO') # => ActiveRecord::
|
|
400
|
-
# relation.limit!(5) # => ActiveRecord::
|
|
401
|
-
class
|
|
483
|
+
# relation.where!(title: 'TODO') # => ActiveRecord::UnmodifiableRelation
|
|
484
|
+
# relation.limit!(5) # => ActiveRecord::UnmodifiableRelation
|
|
485
|
+
class UnmodifiableRelation < ActiveRecordError
|
|
402
486
|
end
|
|
487
|
+
deprecate_constant(
|
|
488
|
+
:ImmutableRelation,
|
|
489
|
+
"ActiveRecord::UnmodifiableRelation",
|
|
490
|
+
deprecator: ActiveRecord.deprecator
|
|
491
|
+
)
|
|
403
492
|
|
|
404
493
|
# TransactionIsolationError will be raised under the following conditions:
|
|
405
494
|
#
|
|
@@ -407,13 +496,26 @@ module ActiveRecord
|
|
|
407
496
|
# * You are joining an existing open transaction
|
|
408
497
|
# * You are creating a nested (savepoint) transaction
|
|
409
498
|
#
|
|
410
|
-
# The mysql2 and postgresql adapters support setting the transaction isolation level.
|
|
499
|
+
# The mysql2, trilogy, and postgresql adapters support setting the transaction isolation level.
|
|
411
500
|
class TransactionIsolationError < ActiveRecordError
|
|
412
501
|
end
|
|
413
502
|
|
|
414
503
|
# TransactionRollbackError will be raised when a transaction is rolled
|
|
415
504
|
# back by the database due to a serialization failure or a deadlock.
|
|
416
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
|
+
#
|
|
417
519
|
# See the following:
|
|
418
520
|
#
|
|
419
521
|
# * https://www.postgresql.org/docs/current/static/transaction-iso.html
|
|
@@ -428,11 +530,17 @@ module ActiveRecord
|
|
|
428
530
|
|
|
429
531
|
# SerializationFailure will be raised when a transaction is rolled
|
|
430
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.
|
|
431
536
|
class SerializationFailure < TransactionRollbackError
|
|
432
537
|
end
|
|
433
538
|
|
|
434
539
|
# Deadlocked will be raised when a transaction is rolled
|
|
435
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.
|
|
436
544
|
class Deadlocked < TransactionRollbackError
|
|
437
545
|
end
|
|
438
546
|
|
|
@@ -461,6 +569,11 @@ module ActiveRecord
|
|
|
461
569
|
class AdapterTimeout < QueryAborted
|
|
462
570
|
end
|
|
463
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
|
+
|
|
464
577
|
# UnknownAttributeReference is raised when an unknown and potentially unsafe
|
|
465
578
|
# value is passed to a query method. For example, passing a non column name
|
|
466
579
|
# value to a relation's #order method might cause this exception.
|
|
@@ -483,4 +596,11 @@ module ActiveRecord
|
|
|
483
596
|
# values, such as request parameters or model attributes to query methods.
|
|
484
597
|
class UnknownAttributeReference < ActiveRecordError
|
|
485
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
|
|
486
604
|
end
|
|
605
|
+
|
|
606
|
+
require "active_record/associations/errors"
|