activerecord 7.0.8.7 → 7.1.0.beta1
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 +1339 -1572
- data/MIT-LICENSE +1 -1
- data/README.rdoc +15 -16
- data/lib/active_record/aggregations.rb +16 -13
- data/lib/active_record/association_relation.rb +1 -1
- data/lib/active_record/associations/association.rb +18 -3
- data/lib/active_record/associations/association_scope.rb +16 -9
- data/lib/active_record/associations/belongs_to_association.rb +14 -6
- data/lib/active_record/associations/builder/association.rb +3 -3
- data/lib/active_record/associations/builder/belongs_to.rb +21 -8
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
- data/lib/active_record/associations/builder/singular_association.rb +4 -0
- data/lib/active_record/associations/collection_association.rb +17 -9
- data/lib/active_record/associations/collection_proxy.rb +16 -11
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +20 -13
- 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.rb +10 -8
- data/lib/active_record/associations/preloader/association.rb +27 -6
- data/lib/active_record/associations/preloader.rb +12 -9
- data/lib/active_record/associations/singular_association.rb +1 -1
- data/lib/active_record/associations/through_association.rb +22 -11
- data/lib/active_record/associations.rb +193 -97
- data/lib/active_record/attribute_assignment.rb +0 -2
- data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
- data/lib/active_record/attribute_methods/dirty.rb +40 -26
- data/lib/active_record/attribute_methods/primary_key.rb +76 -24
- data/lib/active_record/attribute_methods/query.rb +28 -16
- data/lib/active_record/attribute_methods/read.rb +18 -5
- data/lib/active_record/attribute_methods/serialization.rb +150 -31
- data/lib/active_record/attribute_methods/write.rb +3 -3
- data/lib/active_record/attribute_methods.rb +105 -21
- data/lib/active_record/attributes.rb +3 -3
- data/lib/active_record/autosave_association.rb +55 -9
- data/lib/active_record/base.rb +7 -2
- 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 +163 -88
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +3 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +63 -43
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +109 -32
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +60 -22
- data/lib/active_record/connection_adapters/abstract/quoting.rb +41 -6
- 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 +289 -122
- data/lib/active_record/connection_adapters/abstract/transaction.rb +280 -58
- data/lib/active_record/connection_adapters/abstract_adapter.rb +502 -91
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +200 -108
- 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 +22 -143
- data/lib/active_record/connection_adapters/mysql/quoting.rb +16 -12
- 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 +17 -12
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +148 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +98 -53
- data/lib/active_record/connection_adapters/pool_config.rb +14 -5
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +76 -29
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +11 -2
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +9 -6
- 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 +131 -2
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +42 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +351 -54
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +336 -168
- data/lib/active_record/connection_adapters/schema_cache.rb +287 -59
- data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +42 -36
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +4 -3
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +1 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +26 -7
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +162 -77
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +98 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +254 -0
- data/lib/active_record/connection_adapters.rb +3 -1
- data/lib/active_record/connection_handling.rb +71 -94
- data/lib/active_record/core.rb +128 -138
- data/lib/active_record/counter_cache.rb +46 -25
- data/lib/active_record/database_configurations/database_config.rb +9 -3
- data/lib/active_record/database_configurations/hash_config.rb +22 -12
- data/lib/active_record/database_configurations/url_config.rb +17 -11
- data/lib/active_record/database_configurations.rb +86 -33
- data/lib/active_record/delegated_type.rb +8 -3
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +2 -0
- 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 +36 -18
- data/lib/active_record/encryption/encrypted_attribute_type.rb +17 -6
- data/lib/active_record/encryption/extended_deterministic_queries.rb +66 -54
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +2 -2
- data/lib/active_record/encryption/key_generator.rb +12 -1
- data/lib/active_record/encryption/message_serializer.rb +2 -0
- data/lib/active_record/encryption/properties.rb +3 -3
- data/lib/active_record/encryption/scheme.rb +19 -22
- data/lib/active_record/encryption.rb +1 -0
- data/lib/active_record/enum.rb +113 -26
- data/lib/active_record/errors.rb +89 -15
- data/lib/active_record/explain.rb +23 -3
- 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 +119 -71
- data/lib/active_record/future_result.rb +30 -5
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +30 -16
- data/lib/active_record/insert_all.rb +55 -8
- data/lib/active_record/integration.rb +8 -8
- data/lib/active_record/internal_metadata.rb +118 -30
- data/lib/active_record/locking/pessimistic.rb +5 -2
- data/lib/active_record/log_subscriber.rb +29 -12
- 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 +5 -7
- data/lib/active_record/middleware/shard_selector.rb +3 -1
- data/lib/active_record/migration/command_recorder.rb +100 -4
- data/lib/active_record/migration/compatibility.rb +131 -5
- data/lib/active_record/migration/default_strategy.rb +23 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration.rb +213 -109
- data/lib/active_record/model_schema.rb +47 -27
- data/lib/active_record/nested_attributes.rb +28 -3
- data/lib/active_record/normalization.rb +158 -0
- data/lib/active_record/persistence.rb +183 -33
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +3 -21
- data/lib/active_record/query_logs.rb +77 -52
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +15 -2
- data/lib/active_record/railtie.rb +107 -45
- data/lib/active_record/railties/controller_runtime.rb +10 -5
- data/lib/active_record/railties/databases.rake +139 -145
- 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 +169 -45
- data/lib/active_record/relation/batches/batch_enumerator.rb +5 -3
- data/lib/active_record/relation/batches.rb +190 -61
- data/lib/active_record/relation/calculations.rb +152 -63
- data/lib/active_record/relation/delegation.rb +22 -8
- data/lib/active_record/relation/finder_methods.rb +85 -15
- data/lib/active_record/relation/merger.rb +2 -0
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +11 -2
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +26 -14
- data/lib/active_record/relation/query_attribute.rb +2 -1
- data/lib/active_record/relation/query_methods.rb +351 -62
- data/lib/active_record/relation/spawn_methods.rb +18 -1
- data/lib/active_record/relation.rb +76 -35
- data/lib/active_record/result.rb +19 -5
- data/lib/active_record/runtime_registry.rb +10 -1
- data/lib/active_record/sanitization.rb +51 -11
- data/lib/active_record/schema.rb +2 -3
- data/lib/active_record/schema_dumper.rb +41 -7
- data/lib/active_record/schema_migration.rb +68 -33
- 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 +7 -5
- data/lib/active_record/store.rb +8 -8
- data/lib/active_record/suppressor.rb +3 -1
- data/lib/active_record/table_metadata.rb +10 -1
- data/lib/active_record/tasks/database_tasks.rb +127 -105
- 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 +14 -7
- data/lib/active_record/test_fixtures.rb +113 -96
- data/lib/active_record/timestamp.rb +26 -14
- data/lib/active_record/token_for.rb +113 -0
- data/lib/active_record/touch_later.rb +11 -6
- data/lib/active_record/transactions.rb +36 -10
- 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/time.rb +4 -0
- data/lib/active_record/validations/absence.rb +1 -1
- 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 +47 -2
- data/lib/active_record/validations.rb +8 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +121 -16
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/nodes/binary.rb +6 -1
- data/lib/arel/nodes/bound_sql_literal.rb +61 -0
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/homogeneous_in.rb +0 -8
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/node.rb +111 -2
- data/lib/arel/nodes/sql_literal.rb +6 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes.rb +4 -0
- data/lib/arel/predications.rb +2 -0
- data/lib/arel/table.rb +9 -5
- data/lib/arel/visitors/mysql.rb +8 -1
- data/lib/arel/visitors/to_sql.rb +81 -17
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +16 -2
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- 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 +52 -17
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -63
@@ -4,12 +4,17 @@ module ActiveRecord
|
|
4
4
|
module Type
|
5
5
|
module Internal
|
6
6
|
module Timezone
|
7
|
+
def initialize(timezone: nil, **kwargs)
|
8
|
+
super(**kwargs)
|
9
|
+
@timezone = timezone
|
10
|
+
end
|
11
|
+
|
7
12
|
def is_utc?
|
8
|
-
|
13
|
+
default_timezone == :utc
|
9
14
|
end
|
10
15
|
|
11
16
|
def default_timezone
|
12
|
-
ActiveRecord.default_timezone
|
17
|
+
@timezone || ActiveRecord.default_timezone
|
13
18
|
end
|
14
19
|
end
|
15
20
|
end
|
@@ -14,7 +14,7 @@ module ActiveRecord
|
|
14
14
|
module ClassMethods
|
15
15
|
# Validates that the specified attributes are not present (as defined by
|
16
16
|
# Object#present?). If the attribute is an association, the associated object
|
17
|
-
# is considered
|
17
|
+
# is also considered not present if it is marked for destruction.
|
18
18
|
#
|
19
19
|
# See ActiveModel::Validations::HelperMethods.validates_absence_of for more information.
|
20
20
|
def validates_absence_of(*attr_names)
|
@@ -21,10 +21,11 @@ module ActiveRecord
|
|
21
21
|
|
22
22
|
module ClassMethods
|
23
23
|
# Validates whether the value of the specified attribute is numeric by
|
24
|
-
# trying to convert it to a float with Kernel.Float (if
|
25
|
-
# is +false+) or applying it to the regular
|
26
|
-
# (if <tt>only_integer</tt> is set to
|
27
|
-
# defaults to the column's precision
|
24
|
+
# trying to convert it to a float with +Kernel.Float+ (if
|
25
|
+
# <tt>only_integer</tt> is +false+) or applying it to the regular
|
26
|
+
# expression <tt>/\A[\+\-]?\d+\z/</tt> (if <tt>only_integer</tt> is set to
|
27
|
+
# +true+). +Kernel.Float+ precision defaults to the column's precision
|
28
|
+
# value or 15.
|
28
29
|
#
|
29
30
|
# See ActiveModel::Validations::HelperMethods.validates_numericality_of for more information.
|
30
31
|
def validates_numericality_of(*attr_names)
|
@@ -13,9 +13,8 @@ module ActiveRecord
|
|
13
13
|
|
14
14
|
module ClassMethods
|
15
15
|
# Validates that the specified attributes are not blank (as defined by
|
16
|
-
# Object#blank?)
|
17
|
-
#
|
18
|
-
# on save.
|
16
|
+
# Object#blank?). If the attribute is an association, the associated object
|
17
|
+
# is also considered blank if it is marked for destruction.
|
19
18
|
#
|
20
19
|
# class Person < ActiveRecord::Base
|
21
20
|
# has_one :face
|
@@ -25,41 +24,19 @@ module ActiveRecord
|
|
25
24
|
# The face attribute must be in the object and it cannot be blank or marked
|
26
25
|
# for destruction.
|
27
26
|
#
|
28
|
-
# If you want to validate the presence of a boolean field (where the real values
|
29
|
-
# are true and false), you will want to use
|
30
|
-
# <tt>validates_inclusion_of :field_name, in: [true, false]</tt>.
|
31
|
-
#
|
32
|
-
# This is due to the way Object#blank? handles boolean values:
|
33
|
-
# <tt>false.blank? # => true</tt>.
|
34
|
-
#
|
35
27
|
# This validator defers to the Active Model validation for presence, adding the
|
36
28
|
# check to see that an associated object is not marked for destruction. This
|
37
29
|
# prevents the parent object from validating successfully and saving, which then
|
38
30
|
# deletes the associated object, thus putting the parent object into an invalid
|
39
31
|
# state.
|
40
32
|
#
|
33
|
+
# See ActiveModel::Validations::HelperMethods.validates_presence_of for
|
34
|
+
# more information.
|
35
|
+
#
|
41
36
|
# NOTE: This validation will not fail while using it with an association
|
42
37
|
# if the latter was assigned but not valid. If you want to ensure that
|
43
38
|
# it is both present and valid, you also need to use
|
44
39
|
# {validates_associated}[rdoc-ref:Validations::ClassMethods#validates_associated].
|
45
|
-
#
|
46
|
-
# Configuration options:
|
47
|
-
# * <tt>:message</tt> - A custom error message (default is: "can't be blank").
|
48
|
-
# * <tt>:on</tt> - Specifies the contexts where this validation is active.
|
49
|
-
# Runs in all validation contexts by default +nil+. You can pass a symbol
|
50
|
-
# or an array of symbols. (e.g. <tt>on: :create</tt> or
|
51
|
-
# <tt>on: :custom_validation_context</tt> or
|
52
|
-
# <tt>on: [:create, :custom_validation_context]</tt>)
|
53
|
-
# * <tt>:if</tt> - Specifies a method, proc, or string to call to determine if
|
54
|
-
# the validation should occur (e.g. <tt>if: :allow_validation</tt>, or
|
55
|
-
# <tt>if: Proc.new { |user| user.signup_step > 2 }</tt>). The method, proc
|
56
|
-
# or string should return or evaluate to a +true+ or +false+ value.
|
57
|
-
# * <tt>:unless</tt> - Specifies a method, proc, or string to call to determine
|
58
|
-
# if the validation should not occur (e.g. <tt>unless: :skip_validation</tt>,
|
59
|
-
# or <tt>unless: Proc.new { |user| user.signup_step <= 2 }</tt>). The method,
|
60
|
-
# proc or string should return or evaluate to a +true+ or +false+ value.
|
61
|
-
# * <tt>:strict</tt> - Specifies whether validation should be strict.
|
62
|
-
# See ActiveModel::Validations#validates! for more information.
|
63
40
|
def validates_presence_of(*attr_names)
|
64
41
|
validates_with PresenceValidator, _merge_attributes(attr_names)
|
65
42
|
end
|
@@ -20,10 +20,12 @@ module ActiveRecord
|
|
20
20
|
finder_class = find_finder_class_for(record)
|
21
21
|
value = map_enum_attribute(finder_class, attribute, value)
|
22
22
|
|
23
|
+
return if record.persisted? && !validation_needed?(finder_class, record, attribute)
|
24
|
+
|
23
25
|
relation = build_relation(finder_class, attribute, value)
|
24
26
|
if record.persisted?
|
25
27
|
if finder_class.primary_key
|
26
|
-
relation = relation.where.not(finder_class.primary_key => record.id_in_database)
|
28
|
+
relation = relation.where.not(finder_class.primary_key => [record.id_in_database])
|
27
29
|
else
|
28
30
|
raise UnknownPrimaryKey.new(finder_class, "Cannot validate uniqueness for persisted record without primary key.")
|
29
31
|
end
|
@@ -64,6 +66,48 @@ module ActiveRecord
|
|
64
66
|
class_hierarchy.detect { |klass| !klass.abstract_class? }
|
65
67
|
end
|
66
68
|
|
69
|
+
def validation_needed?(klass, record, attribute)
|
70
|
+
return true if options[:conditions] || options.key?(:case_sensitive)
|
71
|
+
|
72
|
+
scope = Array(options[:scope])
|
73
|
+
attributes = scope + [attribute]
|
74
|
+
attributes = resolve_attributes(record, attributes)
|
75
|
+
|
76
|
+
return true if attributes.any? { |attr| record.attribute_changed?(attr) ||
|
77
|
+
record.read_attribute(attr).nil? }
|
78
|
+
|
79
|
+
!covered_by_unique_index?(klass, record, attribute, scope)
|
80
|
+
end
|
81
|
+
|
82
|
+
def covered_by_unique_index?(klass, record, attribute, scope)
|
83
|
+
@covered ||= self.attributes.map(&:to_s).select do |attr|
|
84
|
+
attributes = scope + [attr]
|
85
|
+
attributes = resolve_attributes(record, attributes)
|
86
|
+
|
87
|
+
klass.connection.schema_cache.indexes(klass.table_name).any? do |index|
|
88
|
+
index.unique &&
|
89
|
+
index.where.nil? &&
|
90
|
+
(index.columns - attributes).empty?
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
@covered.include?(attribute.to_s)
|
95
|
+
end
|
96
|
+
|
97
|
+
def resolve_attributes(record, attributes)
|
98
|
+
attributes.flat_map do |attribute|
|
99
|
+
reflection = record.class._reflect_on_association(attribute)
|
100
|
+
|
101
|
+
if reflection.nil?
|
102
|
+
attribute.to_s
|
103
|
+
elsif reflection.polymorphic?
|
104
|
+
[reflection.foreign_key, reflection.foreign_type]
|
105
|
+
else
|
106
|
+
reflection.foreign_key
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
67
111
|
def build_relation(klass, attribute, value)
|
68
112
|
relation = klass.unscoped
|
69
113
|
comparison = relation.bind_attribute(attribute, value) do |attr, bind|
|
@@ -221,7 +265,7 @@ module ActiveRecord
|
|
221
265
|
# When the database catches such a duplicate insertion,
|
222
266
|
# {ActiveRecord::Base#save}[rdoc-ref:Persistence#save] will raise an ActiveRecord::StatementInvalid
|
223
267
|
# exception. You can either choose to let this error propagate (which
|
224
|
-
# will result in the default Rails exception page being shown), or you
|
268
|
+
# will result in the default \Rails exception page being shown), or you
|
225
269
|
# can catch it and restart the transaction (e.g. by telling the user
|
226
270
|
# that the title already exists, and asking them to re-enter the title).
|
227
271
|
# This technique is also known as
|
@@ -236,6 +280,7 @@ module ActiveRecord
|
|
236
280
|
# The following bundled adapters throw the ActiveRecord::RecordNotUnique exception:
|
237
281
|
#
|
238
282
|
# * ActiveRecord::ConnectionAdapters::Mysql2Adapter.
|
283
|
+
# * ActiveRecord::ConnectionAdapters::TrilogyAdapter.
|
239
284
|
# * ActiveRecord::ConnectionAdapters::SQLite3Adapter.
|
240
285
|
# * ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.
|
241
286
|
def validates_uniqueness_of(*attr_names)
|
@@ -30,10 +30,12 @@ module ActiveRecord
|
|
30
30
|
|
31
31
|
# = Active Record \Validations
|
32
32
|
#
|
33
|
-
# Active Record includes the majority of its validations from ActiveModel::Validations
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
33
|
+
# Active Record includes the majority of its validations from ActiveModel::Validations.
|
34
|
+
#
|
35
|
+
# In Active Record, all validations are performed on save by default.
|
36
|
+
# Validations accept the <tt>:on</tt> argument to define the context where
|
37
|
+
# the validations are active. Active Record will pass either the context of
|
38
|
+
# <tt>:create</tt> or <tt>:update</tt> depending on whether the model is a
|
37
39
|
# {new_record?}[rdoc-ref:Persistence#new_record?].
|
38
40
|
module Validations
|
39
41
|
extend ActiveSupport::Concern
|
@@ -60,6 +62,8 @@ module ActiveRecord
|
|
60
62
|
#
|
61
63
|
# If the argument is +false+ (default is +nil+), the context is set to <tt>:create</tt> if
|
62
64
|
# {new_record?}[rdoc-ref:Persistence#new_record?] is +true+, and to <tt>:update</tt> if it is not.
|
65
|
+
# If the argument is an array of contexts, <tt>post.valid?([:create, :update])</tt>, the validations are
|
66
|
+
# run within multiple contexts.
|
63
67
|
#
|
64
68
|
# \Validations with no <tt>:on</tt> option will run no matter the context. \Validations with
|
65
69
|
# some <tt>:on</tt> option will only run in the specified context.
|
data/lib/active_record.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#--
|
4
|
-
# Copyright (c)
|
4
|
+
# Copyright (c) David Heinemeier Hansson
|
5
5
|
#
|
6
6
|
# Permission is hereby granted, free of charge, to any person obtaining
|
7
7
|
# a copy of this software and associated documentation files (the
|
@@ -30,9 +30,11 @@ require "arel"
|
|
30
30
|
require "yaml"
|
31
31
|
|
32
32
|
require "active_record/version"
|
33
|
+
require "active_record/deprecator"
|
33
34
|
require "active_model/attribute_set"
|
34
35
|
require "active_record/errors"
|
35
36
|
|
37
|
+
# :include: activerecord/README.rdoc
|
36
38
|
module ActiveRecord
|
37
39
|
extend ActiveSupport::Autoload
|
38
40
|
|
@@ -47,18 +49,22 @@ module ActiveRecord
|
|
47
49
|
autoload :Encryption
|
48
50
|
autoload :Enum
|
49
51
|
autoload :Explain
|
52
|
+
autoload :FixtureSet, "active_record/fixtures"
|
50
53
|
autoload :Inheritance
|
51
54
|
autoload :Integration
|
52
55
|
autoload :InternalMetadata
|
56
|
+
autoload :LogSubscriber
|
57
|
+
autoload :Marshalling
|
53
58
|
autoload :Migration
|
54
59
|
autoload :Migrator, "active_record/migration"
|
55
60
|
autoload :ModelSchema
|
56
61
|
autoload :NestedAttributes
|
57
62
|
autoload :NoTouching
|
63
|
+
autoload :Normalization
|
58
64
|
autoload :Persistence
|
59
65
|
autoload :QueryCache
|
60
|
-
autoload :Querying
|
61
66
|
autoload :QueryLogs
|
67
|
+
autoload :Querying
|
62
68
|
autoload :ReadonlyAttributes
|
63
69
|
autoload :RecordInvalid, "active_record/validations"
|
64
70
|
autoload :Reflection
|
@@ -68,6 +74,7 @@ module ActiveRecord
|
|
68
74
|
autoload :SchemaDumper
|
69
75
|
autoload :SchemaMigration
|
70
76
|
autoload :Scoping
|
77
|
+
autoload :SecurePassword
|
71
78
|
autoload :SecureToken
|
72
79
|
autoload :Serialization
|
73
80
|
autoload :SignedId
|
@@ -76,6 +83,7 @@ module ActiveRecord
|
|
76
83
|
autoload :TestDatabases
|
77
84
|
autoload :TestFixtures, "active_record/fixtures"
|
78
85
|
autoload :Timestamp
|
86
|
+
autoload :TokenFor
|
79
87
|
autoload :TouchLater
|
80
88
|
autoload :Transactions
|
81
89
|
autoload :Translation
|
@@ -93,7 +101,7 @@ module ActiveRecord
|
|
93
101
|
autoload :DisableJoinsAssociationRelation
|
94
102
|
autoload :FutureResult
|
95
103
|
autoload :LegacyYamlAdapter
|
96
|
-
autoload :
|
104
|
+
autoload :Promise
|
97
105
|
autoload :Relation
|
98
106
|
autoload :Result
|
99
107
|
autoload :StatementCache
|
@@ -101,17 +109,18 @@ module ActiveRecord
|
|
101
109
|
autoload :Type
|
102
110
|
|
103
111
|
autoload_under "relation" do
|
104
|
-
autoload :
|
105
|
-
autoload :FinderMethods
|
112
|
+
autoload :Batches
|
106
113
|
autoload :Calculations
|
114
|
+
autoload :Delegation
|
115
|
+
autoload :FinderMethods
|
107
116
|
autoload :PredicateBuilder
|
117
|
+
autoload :QueryMethods
|
108
118
|
autoload :SpawnMethods
|
109
|
-
autoload :Batches
|
110
|
-
autoload :Delegation
|
111
119
|
end
|
112
120
|
end
|
113
121
|
|
114
122
|
module Coders
|
123
|
+
autoload :ColumnSerializer, "active_record/coders/column_serializer"
|
115
124
|
autoload :JSON, "active_record/coders/json"
|
116
125
|
autoload :YAMLColumn, "active_record/coders/yaml_column"
|
117
126
|
end
|
@@ -165,6 +174,9 @@ module ActiveRecord
|
|
165
174
|
autoload :SQLiteDatabaseTasks, "active_record/tasks/sqlite_database_tasks"
|
166
175
|
end
|
167
176
|
|
177
|
+
singleton_class.attr_accessor :disable_prepared_statements
|
178
|
+
self.disable_prepared_statements = false
|
179
|
+
|
168
180
|
# Lazily load the schema cache. This option will load the schema cache
|
169
181
|
# when a connection is established rather than on boot. If set,
|
170
182
|
# +config.active_record.use_schema_cache_dump+ will be set to false.
|
@@ -177,9 +189,6 @@ module ActiveRecord
|
|
177
189
|
singleton_class.attr_accessor :schema_cache_ignored_tables
|
178
190
|
self.schema_cache_ignored_tables = []
|
179
191
|
|
180
|
-
singleton_class.attr_accessor :legacy_connection_handling
|
181
|
-
self.legacy_connection_handling = true
|
182
|
-
|
183
192
|
singleton_class.attr_reader :default_timezone
|
184
193
|
|
185
194
|
# Determines whether to use Time.utc (using :utc) or Time.local (using :local) when pulling
|
@@ -194,12 +203,53 @@ module ActiveRecord
|
|
194
203
|
|
195
204
|
self.default_timezone = :utc
|
196
205
|
|
206
|
+
# The action to take when database query produces warning.
|
207
|
+
# Must be one of :ignore, :log, :raise, :report, or a custom proc.
|
208
|
+
# The default is :ignore.
|
209
|
+
singleton_class.attr_reader :db_warnings_action
|
210
|
+
|
211
|
+
def self.db_warnings_action=(action)
|
212
|
+
@db_warnings_action =
|
213
|
+
case action
|
214
|
+
when :ignore
|
215
|
+
nil
|
216
|
+
when :log
|
217
|
+
->(warning) do
|
218
|
+
warning_message = "[#{warning.class}] #{warning.message}"
|
219
|
+
warning_message += " (#{warning.code})" if warning.code
|
220
|
+
ActiveRecord::Base.logger.warn(warning_message)
|
221
|
+
end
|
222
|
+
when :raise
|
223
|
+
->(warning) { raise warning }
|
224
|
+
when :report
|
225
|
+
->(warning) { Rails.error.report(warning, handled: true) }
|
226
|
+
when Proc
|
227
|
+
action
|
228
|
+
else
|
229
|
+
raise ArgumentError, "db_warnings_action must be one of :ignore, :log, :raise, :report, or a custom proc."
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
self.db_warnings_action = :ignore
|
234
|
+
|
235
|
+
# Specify allowlist of database warnings.
|
236
|
+
singleton_class.attr_accessor :db_warnings_ignore
|
237
|
+
self.db_warnings_ignore = []
|
238
|
+
|
197
239
|
singleton_class.attr_accessor :writing_role
|
198
240
|
self.writing_role = :writing
|
199
241
|
|
200
242
|
singleton_class.attr_accessor :reading_role
|
201
243
|
self.reading_role = :reading
|
202
244
|
|
245
|
+
def self.legacy_connection_handling=(_)
|
246
|
+
raise ArgumentError, <<~MSG.squish
|
247
|
+
The `legacy_connection_handling` setter was deprecated in 7.0 and removed in 7.1,
|
248
|
+
but is still defined in your configuration. Please remove this call as it no longer
|
249
|
+
has any effect."
|
250
|
+
MSG
|
251
|
+
end
|
252
|
+
|
203
253
|
# Sets the async_query_executor for an application. By default the thread pool executor
|
204
254
|
# set to +nil+ which will not run queries in the background. Applications must configure
|
205
255
|
# a thread pool executor to use this feature. Options are:
|
@@ -258,6 +308,21 @@ module ActiveRecord
|
|
258
308
|
singleton_class.attr_accessor :maintain_test_schema
|
259
309
|
self.maintain_test_schema = nil
|
260
310
|
|
311
|
+
singleton_class.attr_accessor :raise_on_assign_to_attr_readonly
|
312
|
+
self.raise_on_assign_to_attr_readonly = false
|
313
|
+
|
314
|
+
singleton_class.attr_accessor :belongs_to_required_validates_foreign_key
|
315
|
+
self.belongs_to_required_validates_foreign_key = true
|
316
|
+
|
317
|
+
singleton_class.attr_accessor :before_committed_on_all_records
|
318
|
+
self.before_committed_on_all_records = false
|
319
|
+
|
320
|
+
singleton_class.attr_accessor :run_after_transaction_callbacks_in_order_defined
|
321
|
+
self.run_after_transaction_callbacks_in_order_defined = false
|
322
|
+
|
323
|
+
singleton_class.attr_accessor :commit_transaction_on_non_local_return
|
324
|
+
self.commit_transaction_on_non_local_return = false
|
325
|
+
|
261
326
|
##
|
262
327
|
# :singleton-method:
|
263
328
|
# Specify a threshold for the size of query result sets. If the number of
|
@@ -302,6 +367,12 @@ module ActiveRecord
|
|
302
367
|
singleton_class.attr_accessor :timestamped_migrations
|
303
368
|
self.timestamped_migrations = true
|
304
369
|
|
370
|
+
##
|
371
|
+
# :singleton-method:
|
372
|
+
# Specify strategy to use for executing migrations.
|
373
|
+
singleton_class.attr_accessor :migration_strategy
|
374
|
+
self.migration_strategy = Migration::DefaultStrategy
|
375
|
+
|
305
376
|
##
|
306
377
|
# :singleton-method:
|
307
378
|
# Specify whether schema dump should happen at the end of the
|
@@ -321,12 +392,19 @@ module ActiveRecord
|
|
321
392
|
singleton_class.attr_accessor :dump_schemas
|
322
393
|
self.dump_schemas = :schema_search_path
|
323
394
|
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
395
|
+
def self.suppress_multiple_database_warning
|
396
|
+
ActiveRecord.deprecator.warn(<<-MSG.squish)
|
397
|
+
config.active_record.suppress_multiple_database_warning is deprecated and will be removed in Rails 7.2.
|
398
|
+
It no longer has any effect and should be removed from the configuration file.
|
399
|
+
MSG
|
400
|
+
end
|
401
|
+
|
402
|
+
def self.suppress_multiple_database_warning=(value)
|
403
|
+
ActiveRecord.deprecator.warn(<<-MSG.squish)
|
404
|
+
config.active_record.suppress_multiple_database_warning= is deprecated and will be removed in Rails 7.2.
|
405
|
+
It no longer has any effect and should be removed from the configuration file.
|
406
|
+
MSG
|
407
|
+
end
|
330
408
|
|
331
409
|
##
|
332
410
|
# :singleton-method:
|
@@ -337,6 +415,13 @@ module ActiveRecord
|
|
337
415
|
singleton_class.attr_accessor :verify_foreign_keys_for_fixtures
|
338
416
|
self.verify_foreign_keys_for_fixtures = false
|
339
417
|
|
418
|
+
##
|
419
|
+
# :singleton-method:
|
420
|
+
# If true, Rails will continue allowing plural association names in where clauses on singular associations
|
421
|
+
# This behavior will be removed in Rails 7.2.
|
422
|
+
singleton_class.attr_accessor :allow_deprecated_singular_associations_name
|
423
|
+
self.allow_deprecated_singular_associations_name = true
|
424
|
+
|
340
425
|
singleton_class.attr_accessor :query_transformers
|
341
426
|
self.query_transformers = []
|
342
427
|
|
@@ -362,6 +447,21 @@ module ActiveRecord
|
|
362
447
|
singleton_class.attr_accessor :yaml_column_permitted_classes
|
363
448
|
self.yaml_column_permitted_classes = [Symbol]
|
364
449
|
|
450
|
+
##
|
451
|
+
# :singleton-method:
|
452
|
+
# Controls when to generate a value for <tt>has_secure_token</tt>
|
453
|
+
# declarations. Defaults to <tt>:create</tt>.
|
454
|
+
singleton_class.attr_accessor :generate_secure_token_on
|
455
|
+
self.generate_secure_token_on = :create
|
456
|
+
|
457
|
+
def self.marshalling_format_version
|
458
|
+
Marshalling.format_version
|
459
|
+
end
|
460
|
+
|
461
|
+
def self.marshalling_format_version=(value)
|
462
|
+
Marshalling.format_version = value
|
463
|
+
end
|
464
|
+
|
365
465
|
def self.eager_load!
|
366
466
|
super
|
367
467
|
ActiveRecord::Locking.eager_load!
|
@@ -371,6 +471,11 @@ module ActiveRecord
|
|
371
471
|
ActiveRecord::ConnectionAdapters.eager_load!
|
372
472
|
ActiveRecord::Encryption.eager_load!
|
373
473
|
end
|
474
|
+
|
475
|
+
# Explicitly closes all database connections in all pools.
|
476
|
+
def self.disconnect_all!
|
477
|
+
ConnectionAdapters::PoolConfig.disconnect_all!
|
478
|
+
end
|
374
479
|
end
|
375
480
|
|
376
481
|
ActiveSupport.on_load(:active_record) do
|
data/lib/arel/errors.rb
CHANGED
data/lib/arel/factory_methods.rb
CHANGED
data/lib/arel/nodes/binary.rb
CHANGED
@@ -39,6 +39,12 @@ module Arel # :nodoc: all
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
+
class As < Binary
|
43
|
+
def to_cte
|
44
|
+
Arel::Nodes::Cte.new(left.name, right)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
42
48
|
class Between < Binary; include FetchAttribute; end
|
43
49
|
|
44
50
|
class GreaterThan < Binary
|
@@ -112,7 +118,6 @@ module Arel # :nodoc: all
|
|
112
118
|
end
|
113
119
|
|
114
120
|
%w{
|
115
|
-
As
|
116
121
|
Assignment
|
117
122
|
Join
|
118
123
|
Union
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Arel # :nodoc: all
|
4
|
+
module Nodes
|
5
|
+
class BoundSqlLiteral < NodeExpression
|
6
|
+
attr_reader :sql_with_placeholders, :positional_binds, :named_binds
|
7
|
+
|
8
|
+
def initialize(sql_with_placeholders, positional_binds, named_binds)
|
9
|
+
if !positional_binds.empty? && !named_binds.empty?
|
10
|
+
raise BindError.new("cannot mix positional and named binds", sql_with_placeholders)
|
11
|
+
elsif !positional_binds.empty?
|
12
|
+
if positional_binds.size != (expected = sql_with_placeholders.count("?"))
|
13
|
+
raise BindError.new("wrong number of bind variables (#{positional_binds.size} for #{expected})", sql_with_placeholders)
|
14
|
+
end
|
15
|
+
elsif !named_binds.empty?
|
16
|
+
tokens_in_string = sql_with_placeholders.scan(/:(?<!::)([a-zA-Z]\w*)/).flatten.map(&:to_sym).uniq
|
17
|
+
tokens_in_hash = named_binds.keys.map(&:to_sym).uniq
|
18
|
+
|
19
|
+
if !(missing = (tokens_in_string - tokens_in_hash)).empty?
|
20
|
+
if missing.size == 1
|
21
|
+
raise BindError.new("missing value for #{missing.first.inspect}", sql_with_placeholders)
|
22
|
+
else
|
23
|
+
raise BindError.new("missing values for #{missing.inspect}", sql_with_placeholders)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
@sql_with_placeholders = sql_with_placeholders
|
29
|
+
if !positional_binds.empty?
|
30
|
+
@positional_binds = positional_binds
|
31
|
+
@named_binds = nil
|
32
|
+
else
|
33
|
+
@positional_binds = nil
|
34
|
+
@named_binds = named_binds
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def hash
|
39
|
+
[self.class, sql_with_placeholders, positional_binds, named_binds].hash
|
40
|
+
end
|
41
|
+
|
42
|
+
def eql?(other)
|
43
|
+
self.class == other.class &&
|
44
|
+
sql_with_placeholders == other.sql_with_placeholders &&
|
45
|
+
positional_binds == other.positional_binds &&
|
46
|
+
named_binds == other.named_binds
|
47
|
+
end
|
48
|
+
alias :== :eql?
|
49
|
+
|
50
|
+
def +(other)
|
51
|
+
raise ArgumentError, "Expected Arel node" unless Arel.arel_node?(other)
|
52
|
+
|
53
|
+
Fragments.new([self, other])
|
54
|
+
end
|
55
|
+
|
56
|
+
def inspect
|
57
|
+
"#<#{self.class.name} #{sql_with_placeholders.inspect} #{(named_binds || positional_binds).inspect}>"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Arel # :nodoc: all
|
4
|
+
module Nodes
|
5
|
+
class Cte < Arel::Nodes::Binary
|
6
|
+
alias :name :left
|
7
|
+
alias :relation :right
|
8
|
+
attr_reader :materialized
|
9
|
+
|
10
|
+
def initialize(name, relation, materialized: nil)
|
11
|
+
super(name, relation)
|
12
|
+
@materialized = materialized
|
13
|
+
end
|
14
|
+
|
15
|
+
def hash
|
16
|
+
[name, relation, materialized].hash
|
17
|
+
end
|
18
|
+
|
19
|
+
def eql?(other)
|
20
|
+
self.class == other.class &&
|
21
|
+
self.name == other.name &&
|
22
|
+
self.relation == other.relation &&
|
23
|
+
self.materialized == other.materialized
|
24
|
+
end
|
25
|
+
alias :== :eql?
|
26
|
+
|
27
|
+
def to_cte
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_table
|
32
|
+
Arel::Table.new(name)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|