activerecord 6.1.4.6 → 7.0.2.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1188 -932
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/lib/active_record/aggregations.rb +1 -1
- data/lib/active_record/association_relation.rb +0 -10
- data/lib/active_record/associations/association.rb +33 -17
- data/lib/active_record/associations/association_scope.rb +1 -3
- data/lib/active_record/associations/belongs_to_association.rb +15 -4
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
- data/lib/active_record/associations/builder/association.rb +8 -2
- data/lib/active_record/associations/builder/belongs_to.rb +19 -6
- data/lib/active_record/associations/builder/collection_association.rb +10 -3
- data/lib/active_record/associations/builder/has_many.rb +3 -2
- data/lib/active_record/associations/builder/has_one.rb +2 -1
- data/lib/active_record/associations/builder/singular_association.rb +2 -2
- data/lib/active_record/associations/collection_association.rb +34 -27
- data/lib/active_record/associations/collection_proxy.rb +8 -3
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +2 -1
- data/lib/active_record/associations/has_one_association.rb +10 -7
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency.rb +6 -2
- data/lib/active_record/associations/preloader/association.rb +187 -55
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +147 -0
- data/lib/active_record/associations/preloader/through_association.rb +49 -13
- data/lib/active_record/associations/preloader.rb +39 -113
- data/lib/active_record/associations/singular_association.rb +8 -2
- data/lib/active_record/associations/through_association.rb +3 -3
- data/lib/active_record/associations.rb +119 -90
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +1 -1
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -2
- data/lib/active_record/attribute_methods/dirty.rb +49 -16
- data/lib/active_record/attribute_methods/primary_key.rb +2 -2
- data/lib/active_record/attribute_methods/query.rb +2 -2
- data/lib/active_record/attribute_methods/read.rb +7 -5
- data/lib/active_record/attribute_methods/serialization.rb +66 -12
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -3
- data/lib/active_record/attribute_methods/write.rb +7 -10
- data/lib/active_record/attribute_methods.rb +13 -14
- data/lib/active_record/attributes.rb +24 -35
- data/lib/active_record/autosave_association.rb +8 -23
- data/lib/active_record/base.rb +19 -1
- data/lib/active_record/callbacks.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +292 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +209 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +76 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +47 -561
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +0 -17
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +46 -22
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +24 -12
- data/lib/active_record/connection_adapters/abstract/quoting.rb +42 -72
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -17
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +38 -13
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +78 -22
- data/lib/active_record/connection_adapters/abstract/transaction.rb +15 -22
- data/lib/active_record/connection_adapters/abstract_adapter.rb +149 -74
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +97 -81
- data/lib/active_record/connection_adapters/column.rb +4 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +38 -24
- data/lib/active_record/connection_adapters/mysql/quoting.rb +35 -21
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +7 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +5 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -6
- data/lib/active_record/connection_adapters/pool_config.rb +7 -7
- data/lib/active_record/connection_adapters/postgresql/column.rb +17 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +21 -12
- 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/range.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +50 -50
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +32 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +21 -1
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +22 -1
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +35 -19
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +207 -107
- data/lib/active_record/connection_adapters/schema_cache.rb +29 -4
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +27 -19
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +28 -16
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +16 -14
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +89 -30
- data/lib/active_record/connection_adapters.rb +6 -5
- data/lib/active_record/connection_handling.rb +47 -53
- data/lib/active_record/core.rb +122 -132
- data/lib/active_record/database_configurations/connection_url_resolver.rb +3 -1
- data/lib/active_record/database_configurations/database_config.rb +12 -9
- data/lib/active_record/database_configurations/hash_config.rb +63 -5
- data/lib/active_record/database_configurations/url_config.rb +2 -2
- data/lib/active_record/database_configurations.rb +16 -32
- data/lib/active_record/delegated_type.rb +52 -11
- data/lib/active_record/destroy_association_async_job.rb +1 -1
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +1 -1
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +98 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +44 -0
- data/lib/active_record/encryption/configurable.rb +61 -0
- data/lib/active_record/encryption/context.rb +35 -0
- data/lib/active_record/encryption/contexts.rb +72 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +12 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +208 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +140 -0
- data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
- data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
- data/lib/active_record/encryption/encryptor.rb +155 -0
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
- data/lib/active_record/encryption/errors.rb +15 -0
- data/lib/active_record/encryption/extended_deterministic_queries.rb +160 -0
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
- data/lib/active_record/encryption/key.rb +28 -0
- data/lib/active_record/encryption/key_generator.rb +42 -0
- data/lib/active_record/encryption/key_provider.rb +46 -0
- data/lib/active_record/encryption/message.rb +33 -0
- data/lib/active_record/encryption/message_serializer.rb +90 -0
- data/lib/active_record/encryption/null_encryptor.rb +21 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
- data/lib/active_record/encryption/scheme.rb +99 -0
- data/lib/active_record/encryption.rb +55 -0
- data/lib/active_record/enum.rb +49 -42
- data/lib/active_record/errors.rb +67 -4
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/fixture_set/file.rb +15 -1
- data/lib/active_record/fixture_set/table_row.rb +41 -6
- data/lib/active_record/fixture_set/table_rows.rb +4 -4
- data/lib/active_record/fixtures.rb +17 -20
- data/lib/active_record/future_result.rb +139 -0
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +55 -17
- data/lib/active_record/insert_all.rb +80 -14
- data/lib/active_record/integration.rb +4 -3
- data/lib/active_record/internal_metadata.rb +3 -5
- data/lib/active_record/legacy_yaml_adapter.rb +2 -39
- data/lib/active_record/locking/optimistic.rb +10 -9
- data/lib/active_record/locking/pessimistic.rb +9 -3
- data/lib/active_record/log_subscriber.rb +14 -3
- data/lib/active_record/middleware/database_selector/resolver.rb +6 -10
- data/lib/active_record/middleware/database_selector.rb +8 -3
- data/lib/active_record/middleware/shard_selector.rb +60 -0
- data/lib/active_record/migration/command_recorder.rb +4 -4
- data/lib/active_record/migration/compatibility.rb +107 -3
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration.rb +109 -79
- data/lib/active_record/model_schema.rb +45 -58
- data/lib/active_record/nested_attributes.rb +13 -12
- data/lib/active_record/no_touching.rb +3 -3
- data/lib/active_record/null_relation.rb +2 -6
- data/lib/active_record/persistence.rb +219 -52
- data/lib/active_record/query_cache.rb +2 -2
- data/lib/active_record/query_logs.rb +138 -0
- data/lib/active_record/querying.rb +15 -5
- data/lib/active_record/railtie.rb +127 -17
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +66 -129
- data/lib/active_record/readonly_attributes.rb +11 -0
- data/lib/active_record/reflection.rb +67 -50
- data/lib/active_record/relation/batches/batch_enumerator.rb +19 -5
- data/lib/active_record/relation/batches.rb +3 -3
- data/lib/active_record/relation/calculations.rb +43 -38
- data/lib/active_record/relation/delegation.rb +7 -7
- data/lib/active_record/relation/finder_methods.rb +31 -35
- data/lib/active_record/relation/merger.rb +20 -13
- data/lib/active_record/relation/predicate_builder.rb +1 -6
- data/lib/active_record/relation/query_attribute.rb +5 -11
- data/lib/active_record/relation/query_methods.rb +249 -61
- data/lib/active_record/relation/record_fetch_warning.rb +7 -9
- data/lib/active_record/relation/spawn_methods.rb +2 -2
- data/lib/active_record/relation/where_clause.rb +10 -19
- data/lib/active_record/relation.rb +184 -84
- data/lib/active_record/result.rb +17 -7
- data/lib/active_record/runtime_registry.rb +9 -13
- data/lib/active_record/sanitization.rb +11 -7
- data/lib/active_record/schema.rb +38 -23
- data/lib/active_record/schema_dumper.rb +25 -19
- data/lib/active_record/schema_migration.rb +4 -4
- data/lib/active_record/scoping/default.rb +61 -12
- data/lib/active_record/scoping/named.rb +3 -11
- data/lib/active_record/scoping.rb +64 -34
- data/lib/active_record/serialization.rb +1 -1
- data/lib/active_record/signed_id.rb +1 -1
- data/lib/active_record/suppressor.rb +11 -15
- data/lib/active_record/tasks/database_tasks.rb +120 -58
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/postgresql_database_tasks.rb +19 -12
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +4 -4
- data/lib/active_record/timestamp.rb +3 -4
- data/lib/active_record/transactions.rb +9 -14
- data/lib/active_record/translation.rb +2 -2
- data/lib/active_record/type/adapter_specific_registry.rb +32 -7
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
- data/lib/active_record/type/internal/timezone.rb +2 -2
- data/lib/active_record/type/serialized.rb +1 -1
- data/lib/active_record/type/type_map.rb +17 -20
- data/lib/active_record/type.rb +1 -2
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record/validations/uniqueness.rb +1 -1
- data/lib/active_record.rb +204 -28
- data/lib/arel/attributes/attribute.rb +0 -8
- data/lib/arel/crud.rb +28 -22
- data/lib/arel/delete_manager.rb +18 -4
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +2 -3
- data/lib/arel/nodes/casted.rb +1 -1
- data/lib/arel/nodes/delete_statement.rb +12 -13
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/function.rb +1 -0
- data/lib/arel/nodes/insert_statement.rb +2 -2
- data/lib/arel/nodes/select_core.rb +2 -2
- data/lib/arel/nodes/select_statement.rb +2 -2
- data/lib/arel/nodes/update_statement.rb +8 -3
- data/lib/arel/nodes.rb +1 -0
- data/lib/arel/predications.rb +11 -3
- data/lib/arel/select_manager.rb +10 -4
- data/lib/arel/table.rb +0 -1
- data/lib/arel/tree_manager.rb +0 -12
- data/lib/arel/update_manager.rb +18 -4
- data/lib/arel/visitors/dot.rb +80 -90
- data/lib/arel/visitors/mysql.rb +8 -2
- data/lib/arel/visitors/postgresql.rb +0 -10
- data/lib/arel/visitors/to_sql.rb +58 -2
- data/lib/arel.rb +2 -1
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- 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 +56 -11
@@ -1,11 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/core_ext/enumerable"
|
4
|
-
require "active_support/core_ext/string/conversions"
|
5
|
-
|
6
3
|
module ActiveRecord
|
7
|
-
class AssociationNotFoundError < ConfigurationError
|
4
|
+
class AssociationNotFoundError < ConfigurationError # :nodoc:
|
8
5
|
attr_reader :record, :association_name
|
6
|
+
|
9
7
|
def initialize(record = nil, association_name = nil)
|
10
8
|
@record = record
|
11
9
|
@association_name = association_name
|
@@ -16,32 +14,25 @@ module ActiveRecord
|
|
16
14
|
end
|
17
15
|
end
|
18
16
|
|
19
|
-
|
20
|
-
|
21
|
-
@error = error
|
22
|
-
end
|
17
|
+
if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
|
18
|
+
include DidYouMean::Correctable
|
23
19
|
|
24
20
|
def corrections
|
25
|
-
if
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
}.reverse.first(4)
|
21
|
+
if record && association_name
|
22
|
+
@corrections ||= begin
|
23
|
+
maybe_these = record.class.reflections.keys
|
24
|
+
DidYouMean::SpellChecker.new(dictionary: maybe_these).correct(association_name)
|
25
|
+
end
|
31
26
|
else
|
32
27
|
[]
|
33
28
|
end
|
34
29
|
end
|
35
30
|
end
|
36
|
-
|
37
|
-
# We may not have DYM, and DYM might not let us register error handlers
|
38
|
-
if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
|
39
|
-
DidYouMean.correct_error(self, Correction)
|
40
|
-
end
|
41
31
|
end
|
42
32
|
|
43
|
-
class InverseOfAssociationNotFoundError < ActiveRecordError
|
33
|
+
class InverseOfAssociationNotFoundError < ActiveRecordError # :nodoc:
|
44
34
|
attr_reader :reflection, :associated_class
|
35
|
+
|
45
36
|
def initialize(reflection = nil, associated_class = nil)
|
46
37
|
if reflection
|
47
38
|
@reflection = reflection
|
@@ -52,31 +43,35 @@ module ActiveRecord
|
|
52
43
|
end
|
53
44
|
end
|
54
45
|
|
55
|
-
|
56
|
-
|
57
|
-
@error = error
|
58
|
-
end
|
46
|
+
if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
|
47
|
+
include DidYouMean::Correctable
|
59
48
|
|
60
49
|
def corrections
|
61
|
-
if
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
}.reverse.first(4)
|
50
|
+
if reflection && associated_class
|
51
|
+
@corrections ||= begin
|
52
|
+
maybe_these = associated_class.reflections.keys
|
53
|
+
DidYouMean::SpellChecker.new(dictionary: maybe_these).correct(reflection.options[:inverse_of].to_s)
|
54
|
+
end
|
67
55
|
else
|
68
56
|
[]
|
69
57
|
end
|
70
58
|
end
|
71
59
|
end
|
60
|
+
end
|
72
61
|
|
73
|
-
|
74
|
-
|
75
|
-
|
62
|
+
class InverseOfAssociationRecursiveError < ActiveRecordError # :nodoc:
|
63
|
+
attr_reader :reflection
|
64
|
+
def initialize(reflection = nil)
|
65
|
+
if reflection
|
66
|
+
@reflection = reflection
|
67
|
+
super("Inverse association #{reflection.name} (#{reflection.options[:inverse_of].inspect} in #{reflection.class_name}) is recursive.")
|
68
|
+
else
|
69
|
+
super("Inverse association is recursive.")
|
70
|
+
end
|
76
71
|
end
|
77
72
|
end
|
78
73
|
|
79
|
-
class HasManyThroughAssociationNotFoundError < ActiveRecordError
|
74
|
+
class HasManyThroughAssociationNotFoundError < ActiveRecordError # :nodoc:
|
80
75
|
attr_reader :owner_class, :reflection
|
81
76
|
|
82
77
|
def initialize(owner_class = nil, reflection = nil)
|
@@ -89,32 +84,24 @@ module ActiveRecord
|
|
89
84
|
end
|
90
85
|
end
|
91
86
|
|
92
|
-
|
93
|
-
|
94
|
-
@error = error
|
95
|
-
end
|
87
|
+
if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
|
88
|
+
include DidYouMean::Correctable
|
96
89
|
|
97
90
|
def corrections
|
98
|
-
if
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
}.reverse.first(4)
|
91
|
+
if owner_class && reflection
|
92
|
+
@corrections ||= begin
|
93
|
+
maybe_these = owner_class.reflections.keys
|
94
|
+
maybe_these -= [reflection.name.to_s] # remove failing reflection
|
95
|
+
DidYouMean::SpellChecker.new(dictionary: maybe_these).correct(reflection.options[:through].to_s)
|
96
|
+
end
|
105
97
|
else
|
106
98
|
[]
|
107
99
|
end
|
108
100
|
end
|
109
101
|
end
|
110
|
-
|
111
|
-
# We may not have DYM, and DYM might not let us register error handlers
|
112
|
-
if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
|
113
|
-
DidYouMean.correct_error(self, Correction)
|
114
|
-
end
|
115
102
|
end
|
116
103
|
|
117
|
-
class HasManyThroughAssociationPolymorphicSourceError < ActiveRecordError
|
104
|
+
class HasManyThroughAssociationPolymorphicSourceError < ActiveRecordError # :nodoc:
|
118
105
|
def initialize(owner_class_name = nil, reflection = nil, source_reflection = nil)
|
119
106
|
if owner_class_name && reflection && source_reflection
|
120
107
|
super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' on the polymorphic object '#{source_reflection.class_name}##{source_reflection.name}' without 'source_type'. Try adding 'source_type: \"#{reflection.name.to_s.classify}\"' to 'has_many :through' definition.")
|
@@ -124,7 +111,7 @@ module ActiveRecord
|
|
124
111
|
end
|
125
112
|
end
|
126
113
|
|
127
|
-
class HasManyThroughAssociationPolymorphicThroughError < ActiveRecordError
|
114
|
+
class HasManyThroughAssociationPolymorphicThroughError < ActiveRecordError # :nodoc:
|
128
115
|
def initialize(owner_class_name = nil, reflection = nil)
|
129
116
|
if owner_class_name && reflection
|
130
117
|
super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' which goes through the polymorphic association '#{owner_class_name}##{reflection.through_reflection.name}'.")
|
@@ -134,7 +121,7 @@ module ActiveRecord
|
|
134
121
|
end
|
135
122
|
end
|
136
123
|
|
137
|
-
class HasManyThroughAssociationPointlessSourceTypeError < ActiveRecordError
|
124
|
+
class HasManyThroughAssociationPointlessSourceTypeError < ActiveRecordError # :nodoc:
|
138
125
|
def initialize(owner_class_name = nil, reflection = nil, source_reflection = nil)
|
139
126
|
if owner_class_name && reflection && source_reflection
|
140
127
|
super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' with a :source_type option if the '#{reflection.through_reflection.class_name}##{source_reflection.name}' is not polymorphic. Try removing :source_type on your association.")
|
@@ -144,7 +131,7 @@ module ActiveRecord
|
|
144
131
|
end
|
145
132
|
end
|
146
133
|
|
147
|
-
class HasOneThroughCantAssociateThroughCollection < ActiveRecordError
|
134
|
+
class HasOneThroughCantAssociateThroughCollection < ActiveRecordError # :nodoc:
|
148
135
|
def initialize(owner_class_name = nil, reflection = nil, through_reflection = nil)
|
149
136
|
if owner_class_name && reflection && through_reflection
|
150
137
|
super("Cannot have a has_one :through association '#{owner_class_name}##{reflection.name}' where the :through association '#{owner_class_name}##{through_reflection.name}' is a collection. Specify a has_one or belongs_to association in the :through option instead.")
|
@@ -154,7 +141,7 @@ module ActiveRecord
|
|
154
141
|
end
|
155
142
|
end
|
156
143
|
|
157
|
-
class HasOneAssociationPolymorphicThroughError < ActiveRecordError
|
144
|
+
class HasOneAssociationPolymorphicThroughError < ActiveRecordError # :nodoc:
|
158
145
|
def initialize(owner_class_name = nil, reflection = nil)
|
159
146
|
if owner_class_name && reflection
|
160
147
|
super("Cannot have a has_one :through association '#{owner_class_name}##{reflection.name}' which goes through the polymorphic association '#{owner_class_name}##{reflection.through_reflection.name}'.")
|
@@ -164,7 +151,7 @@ module ActiveRecord
|
|
164
151
|
end
|
165
152
|
end
|
166
153
|
|
167
|
-
class HasManyThroughSourceAssociationNotFoundError < ActiveRecordError
|
154
|
+
class HasManyThroughSourceAssociationNotFoundError < ActiveRecordError # :nodoc:
|
168
155
|
def initialize(reflection = nil)
|
169
156
|
if reflection
|
170
157
|
through_reflection = reflection.through_reflection
|
@@ -177,7 +164,7 @@ module ActiveRecord
|
|
177
164
|
end
|
178
165
|
end
|
179
166
|
|
180
|
-
class HasManyThroughOrderError < ActiveRecordError
|
167
|
+
class HasManyThroughOrderError < ActiveRecordError # :nodoc:
|
181
168
|
def initialize(owner_class_name = nil, reflection = nil, through_reflection = nil)
|
182
169
|
if owner_class_name && reflection && through_reflection
|
183
170
|
super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' which goes through '#{owner_class_name}##{through_reflection.name}' before the through association is defined.")
|
@@ -187,7 +174,7 @@ module ActiveRecord
|
|
187
174
|
end
|
188
175
|
end
|
189
176
|
|
190
|
-
class ThroughCantAssociateThroughHasOneOrManyReflection < ActiveRecordError
|
177
|
+
class ThroughCantAssociateThroughHasOneOrManyReflection < ActiveRecordError # :nodoc:
|
191
178
|
def initialize(owner = nil, reflection = nil)
|
192
179
|
if owner && reflection
|
193
180
|
super("Cannot modify association '#{owner.class.name}##{reflection.name}' because the source reflection class '#{reflection.source_reflection.class_name}' is associated to '#{reflection.through_reflection.class_name}' via :#{reflection.source_reflection.macro}.")
|
@@ -212,13 +199,13 @@ module ActiveRecord
|
|
212
199
|
end
|
213
200
|
end
|
214
201
|
|
215
|
-
class HasManyThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection
|
202
|
+
class HasManyThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection # :nodoc:
|
216
203
|
end
|
217
204
|
|
218
|
-
class HasOneThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection
|
205
|
+
class HasOneThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection # :nodoc:
|
219
206
|
end
|
220
207
|
|
221
|
-
class ThroughNestedAssociationsAreReadonly < ActiveRecordError
|
208
|
+
class ThroughNestedAssociationsAreReadonly < ActiveRecordError # :nodoc:
|
222
209
|
def initialize(owner = nil, reflection = nil)
|
223
210
|
if owner && reflection
|
224
211
|
super("Cannot modify association '#{owner.class.name}##{reflection.name}' because it goes through more than one other association.")
|
@@ -228,10 +215,10 @@ module ActiveRecord
|
|
228
215
|
end
|
229
216
|
end
|
230
217
|
|
231
|
-
class HasManyThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly
|
218
|
+
class HasManyThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly # :nodoc:
|
232
219
|
end
|
233
220
|
|
234
|
-
class HasOneThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly
|
221
|
+
class HasOneThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly # :nodoc:
|
235
222
|
end
|
236
223
|
|
237
224
|
# This error is raised when trying to eager load a polymorphic association using a JOIN.
|
@@ -250,7 +237,7 @@ module ActiveRecord
|
|
250
237
|
# This error is raised when trying to destroy a parent instance in N:1 or 1:1 associations
|
251
238
|
# (has_many, has_one) when there is at least 1 child associated instance.
|
252
239
|
# ex: if @project.tasks.size > 0, DeleteRestrictionError will be raised when trying to destroy @project
|
253
|
-
class DeleteRestrictionError < ActiveRecordError
|
240
|
+
class DeleteRestrictionError < ActiveRecordError # :nodoc:
|
254
241
|
def initialize(name = nil)
|
255
242
|
if name
|
256
243
|
super("Cannot delete record because of dependent #{name}")
|
@@ -274,7 +261,7 @@ module ActiveRecord
|
|
274
261
|
autoload :CollectionProxy
|
275
262
|
autoload :ThroughAssociation
|
276
263
|
|
277
|
-
module Builder
|
264
|
+
module Builder # :nodoc:
|
278
265
|
autoload :Association, "active_record/associations/builder/association"
|
279
266
|
autoload :SingularAssociation, "active_record/associations/builder/singular_association"
|
280
267
|
autoload :CollectionAssociation, "active_record/associations/builder/collection_association"
|
@@ -296,16 +283,18 @@ module ActiveRecord
|
|
296
283
|
autoload :Preloader
|
297
284
|
autoload :JoinDependency
|
298
285
|
autoload :AssociationScope
|
286
|
+
autoload :DisableJoinsAssociationScope
|
299
287
|
autoload :AliasTracker
|
300
288
|
end
|
301
289
|
|
302
290
|
def self.eager_load!
|
303
291
|
super
|
304
292
|
Preloader.eager_load!
|
293
|
+
JoinDependency.eager_load!
|
305
294
|
end
|
306
295
|
|
307
296
|
# Returns the association instance for the given name, instantiating it if it doesn't already exist
|
308
|
-
def association(name)
|
297
|
+
def association(name) # :nodoc:
|
309
298
|
association = association_instance_get(name)
|
310
299
|
|
311
300
|
if association.nil?
|
@@ -328,17 +317,7 @@ module ActiveRecord
|
|
328
317
|
super
|
329
318
|
end
|
330
319
|
|
331
|
-
def reload(*) # :nodoc:
|
332
|
-
clear_association_cache
|
333
|
-
super
|
334
|
-
end
|
335
|
-
|
336
320
|
private
|
337
|
-
# Clears out the association cache.
|
338
|
-
def clear_association_cache
|
339
|
-
@association_cache.clear if persisted?
|
340
|
-
end
|
341
|
-
|
342
321
|
def init_internals
|
343
322
|
@association_cache = {}
|
344
323
|
super
|
@@ -398,6 +377,8 @@ module ActiveRecord
|
|
398
377
|
# create_other(attributes={}) | X | | X
|
399
378
|
# create_other!(attributes={}) | X | | X
|
400
379
|
# reload_other | X | X | X
|
380
|
+
# other_changed? | X | X |
|
381
|
+
# other_previously_changed? | X | X |
|
401
382
|
#
|
402
383
|
# === Collection associations (one-to-many / many-to-many)
|
403
384
|
# | | | has_many
|
@@ -614,19 +595,27 @@ module ActiveRecord
|
|
614
595
|
# you can also define callbacks that get triggered when you add an object to or remove an
|
615
596
|
# object from an association collection.
|
616
597
|
#
|
617
|
-
# class
|
618
|
-
#
|
598
|
+
# class Firm < ActiveRecord::Base
|
599
|
+
# has_many :clients,
|
600
|
+
# dependent: :destroy,
|
601
|
+
# after_add: :congratulate_client,
|
602
|
+
# after_remove: :log_after_remove
|
619
603
|
#
|
620
|
-
# def
|
621
|
-
# ...
|
604
|
+
# def congratulate_client(record)
|
605
|
+
# # ...
|
606
|
+
# end
|
607
|
+
#
|
608
|
+
# def log_after_remove(record)
|
609
|
+
# # ...
|
622
610
|
# end
|
623
|
-
# end
|
624
611
|
#
|
625
612
|
# It's possible to stack callbacks by passing them as an array. Example:
|
626
613
|
#
|
627
|
-
# class
|
628
|
-
#
|
629
|
-
#
|
614
|
+
# class Firm < ActiveRecord::Base
|
615
|
+
# has_many :clients,
|
616
|
+
# dependent: :destroy,
|
617
|
+
# after_add: [:congratulate_client, -> (firm, record) { firm.log << "after_adding#{record.id}" }],
|
618
|
+
# after_remove: :log_after_remove
|
630
619
|
# end
|
631
620
|
#
|
632
621
|
# Possible callbacks are: +before_add+, +after_add+, +before_remove+ and +after_remove+.
|
@@ -637,6 +626,18 @@ module ActiveRecord
|
|
637
626
|
# Similarly, if any of the +before_remove+ callbacks throw an exception, the object
|
638
627
|
# will not be removed from the collection.
|
639
628
|
#
|
629
|
+
# Note: To trigger remove callbacks, you must use +destroy+ / +destroy_all+ methods. For example:
|
630
|
+
#
|
631
|
+
# * <tt>firm.clients.destroy(client)</tt>
|
632
|
+
# * <tt>firm.clients.destroy(*clients)</tt>
|
633
|
+
# * <tt>firm.clients.destroy_all</tt>
|
634
|
+
#
|
635
|
+
# +delete+ / +delete_all+ methods like the following do *not* trigger remove callbacks:
|
636
|
+
#
|
637
|
+
# * <tt>firm.clients.delete(client)</tt>
|
638
|
+
# * <tt>firm.clients.delete(*clients)</tt>
|
639
|
+
# * <tt>firm.clients.delete_all</tt>
|
640
|
+
#
|
640
641
|
# == Association extensions
|
641
642
|
#
|
642
643
|
# The proxy objects that control the access to associations can be extended through anonymous
|
@@ -780,9 +781,10 @@ module ActiveRecord
|
|
780
781
|
# inverse detection only works on #has_many, #has_one, and
|
781
782
|
# #belongs_to associations.
|
782
783
|
#
|
783
|
-
# <tt>:foreign_key</tt> and <tt>:through</tt> options on the associations
|
784
|
-
#
|
785
|
-
#
|
784
|
+
# <tt>:foreign_key</tt> and <tt>:through</tt> options on the associations
|
785
|
+
# will also prevent the association's inverse from being found automatically,
|
786
|
+
# as will a custom scopes in some cases. See further details in the
|
787
|
+
# {Active Record Associations guide}[https://guides.rubyonrails.org/association_basics.html#bi-directional-associations].
|
786
788
|
#
|
787
789
|
# The automatic guessing of the inverse association uses a heuristic based
|
788
790
|
# on the name of the class, so it may not work for all associations,
|
@@ -1410,6 +1412,11 @@ module ActiveRecord
|
|
1410
1412
|
# join model. This allows associated records to be built which will automatically create
|
1411
1413
|
# the appropriate join model records when they are saved. (See the 'Association Join Models'
|
1412
1414
|
# section above.)
|
1415
|
+
# [:disable_joins]
|
1416
|
+
# Specifies whether joins should be skipped for an association. If set to true, two or more queries
|
1417
|
+
# will be generated. Note that in some cases, if order or limit is applied, it will be done in-memory
|
1418
|
+
# due to database limitations. This option is only applicable on `has_many :through` associations as
|
1419
|
+
# `has_many` alone do not perform a join.
|
1413
1420
|
# [:source]
|
1414
1421
|
# Specifies the source association name used by #has_many <tt>:through</tt> queries.
|
1415
1422
|
# Only use it if the name cannot be inferred from the association.
|
@@ -1439,7 +1446,8 @@ module ActiveRecord
|
|
1439
1446
|
# Useful for defining methods on associations, especially when they should be shared between multiple
|
1440
1447
|
# association objects.
|
1441
1448
|
# [:strict_loading]
|
1442
|
-
#
|
1449
|
+
# When set to +true+, enforces strict loading every time the associated record is loaded through this
|
1450
|
+
# association.
|
1443
1451
|
# [:ensuring_owner_was]
|
1444
1452
|
# Specifies an instance method to be called on the owner. The method must return true in order for the
|
1445
1453
|
# associated records to be deleted in a background job.
|
@@ -1453,6 +1461,7 @@ module ActiveRecord
|
|
1453
1461
|
# has_many :tags, as: :taggable
|
1454
1462
|
# has_many :reports, -> { readonly }
|
1455
1463
|
# has_many :subscribers, through: :subscriptions, source: :user
|
1464
|
+
# has_many :subscribers, through: :subscriptions, disable_joins: true
|
1456
1465
|
# has_many :comments, strict_loading: true
|
1457
1466
|
def has_many(name, scope = nil, **options, &extension)
|
1458
1467
|
reflection = Builder::HasMany.build(self, name, scope, options, &extension)
|
@@ -1558,8 +1567,21 @@ module ActiveRecord
|
|
1558
1567
|
# source reflection. You can only use a <tt>:through</tt> query through a #has_one
|
1559
1568
|
# or #belongs_to association on the join model.
|
1560
1569
|
#
|
1570
|
+
# If the association on the join model is a #belongs_to, the collection can be modified
|
1571
|
+
# and the records on the <tt>:through</tt> model will be automatically created and removed
|
1572
|
+
# as appropriate. Otherwise, the collection is read-only, so you should manipulate the
|
1573
|
+
# <tt>:through</tt> association directly.
|
1574
|
+
#
|
1561
1575
|
# If you are going to modify the association (rather than just read from it), then it is
|
1562
|
-
# a good idea to set the <tt>:inverse_of</tt> option
|
1576
|
+
# a good idea to set the <tt>:inverse_of</tt> option on the source association on the
|
1577
|
+
# join model. This allows associated records to be built which will automatically create
|
1578
|
+
# the appropriate join model records when they are saved. (See the 'Association Join Models'
|
1579
|
+
# section above.)
|
1580
|
+
# [:disable_joins]
|
1581
|
+
# Specifies whether joins should be skipped for an association. If set to true, two or more queries
|
1582
|
+
# will be generated. Note that in some cases, if order or limit is applied, it will be done in-memory
|
1583
|
+
# due to database limitations. This option is only applicable on `has_one :through` associations as
|
1584
|
+
# `has_one` alone does not perform a join.
|
1563
1585
|
# [:source]
|
1564
1586
|
# Specifies the source association name used by #has_one <tt>:through</tt> queries.
|
1565
1587
|
# Only use it if the name cannot be inferred from the association.
|
@@ -1601,6 +1623,7 @@ module ActiveRecord
|
|
1601
1623
|
# has_one :attachment, as: :attachable
|
1602
1624
|
# has_one :boss, -> { readonly }
|
1603
1625
|
# has_one :club, through: :membership
|
1626
|
+
# has_one :club, through: :membership, disable_joins: true
|
1604
1627
|
# has_one :primary_address, -> { where(primary: true) }, through: :addressables, source: :addressable
|
1605
1628
|
# has_one :credit_card, required: true
|
1606
1629
|
# has_one :credit_card, strict_loading: true
|
@@ -1637,6 +1660,10 @@ module ActiveRecord
|
|
1637
1660
|
# if the record is invalid.
|
1638
1661
|
# [reload_association]
|
1639
1662
|
# Returns the associated object, forcing a database read.
|
1663
|
+
# [association_changed?]
|
1664
|
+
# Returns true if a new associate object has been assigned and the next save will update the foreign key.
|
1665
|
+
# [association_previously_changed?]
|
1666
|
+
# Returns true if the previous save updated the association to reference a new associate object.
|
1640
1667
|
#
|
1641
1668
|
# === Example
|
1642
1669
|
#
|
@@ -1647,6 +1674,8 @@ module ActiveRecord
|
|
1647
1674
|
# * <tt>Post#create_author</tt> (similar to <tt>post.author = Author.new; post.author.save; post.author</tt>)
|
1648
1675
|
# * <tt>Post#create_author!</tt> (similar to <tt>post.author = Author.new; post.author.save!; post.author</tt>)
|
1649
1676
|
# * <tt>Post#reload_author</tt>
|
1677
|
+
# * <tt>Post#author_changed?</tt>
|
1678
|
+
# * <tt>Post#author_previously_changed?</tt>
|
1650
1679
|
# The declaration can also include an +options+ hash to specialize the behavior of the association.
|
1651
1680
|
#
|
1652
1681
|
# === Scopes
|
@@ -1780,7 +1809,7 @@ module ActiveRecord
|
|
1780
1809
|
# The join table should not have a primary key or a model associated with it. You must manually generate the
|
1781
1810
|
# join table with a migration such as this:
|
1782
1811
|
#
|
1783
|
-
# class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration[
|
1812
|
+
# class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration[7.0]
|
1784
1813
|
# def change
|
1785
1814
|
# create_join_table :developers, :projects
|
1786
1815
|
# end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
class AsynchronousQueriesTracker # :nodoc:
|
5
|
+
module NullSession # :nodoc:
|
6
|
+
class << self
|
7
|
+
def active?
|
8
|
+
true
|
9
|
+
end
|
10
|
+
|
11
|
+
def finalize
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Session # :nodoc:
|
17
|
+
def initialize
|
18
|
+
@active = true
|
19
|
+
end
|
20
|
+
|
21
|
+
def active?
|
22
|
+
@active
|
23
|
+
end
|
24
|
+
|
25
|
+
def finalize
|
26
|
+
@active = false
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class << self
|
31
|
+
def install_executor_hooks(executor = ActiveSupport::Executor)
|
32
|
+
executor.register_hook(self)
|
33
|
+
end
|
34
|
+
|
35
|
+
def run
|
36
|
+
ActiveRecord::Base.asynchronous_queries_tracker.start_session
|
37
|
+
end
|
38
|
+
|
39
|
+
def complete(asynchronous_queries_tracker)
|
40
|
+
asynchronous_queries_tracker.finalize_session
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
attr_reader :current_session
|
45
|
+
|
46
|
+
def initialize
|
47
|
+
@current_session = NullSession
|
48
|
+
end
|
49
|
+
|
50
|
+
def start_session
|
51
|
+
@current_session = Session.new
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
def finalize_session
|
56
|
+
@current_session.finalize
|
57
|
+
@current_session = NullSession
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -46,7 +46,7 @@ module ActiveRecord
|
|
46
46
|
def execute_callstack_for_multiparameter_attributes(callstack)
|
47
47
|
errors = []
|
48
48
|
callstack.each do |name, values_with_empty_parameters|
|
49
|
-
if values_with_empty_parameters.each_value.all?(
|
49
|
+
if values_with_empty_parameters.each_value.all?(NilClass)
|
50
50
|
values = nil
|
51
51
|
else
|
52
52
|
values = values_with_empty_parameters
|
@@ -29,8 +29,8 @@ module ActiveRecord
|
|
29
29
|
extend ActiveSupport::Concern
|
30
30
|
|
31
31
|
included do
|
32
|
-
attribute_method_suffix "_before_type_cast", "_for_database"
|
33
|
-
attribute_method_suffix "_came_from_user?"
|
32
|
+
attribute_method_suffix "_before_type_cast", "_for_database", parameters: false
|
33
|
+
attribute_method_suffix "_came_from_user?", parameters: false
|
34
34
|
end
|
35
35
|
|
36
36
|
# Returns the value of the attribute identified by +attr_name+ before
|
@@ -66,6 +66,11 @@ module ActiveRecord
|
|
66
66
|
@attributes.values_before_type_cast
|
67
67
|
end
|
68
68
|
|
69
|
+
# Returns a hash of attributes for assignment to the database.
|
70
|
+
def attributes_for_database
|
71
|
+
@attributes.values_for_database
|
72
|
+
end
|
73
|
+
|
69
74
|
private
|
70
75
|
# Dispatch target for <tt>*_before_type_cast</tt> attribute methods.
|
71
76
|
def attribute_before_type_cast(attr_name)
|
@@ -14,16 +14,43 @@ module ActiveRecord
|
|
14
14
|
raise "You cannot include Dirty after Timestamp"
|
15
15
|
end
|
16
16
|
|
17
|
-
class_attribute :
|
17
|
+
class_attribute :partial_updates, instance_writer: false, default: true
|
18
|
+
class_attribute :partial_inserts, instance_writer: false, default: true
|
18
19
|
|
19
20
|
# Attribute methods for "changed in last call to save?"
|
20
|
-
attribute_method_affix(prefix: "saved_change_to_", suffix: "?")
|
21
|
-
attribute_method_prefix("saved_change_to_")
|
22
|
-
attribute_method_suffix("_before_last_save")
|
21
|
+
attribute_method_affix(prefix: "saved_change_to_", suffix: "?", parameters: "**options")
|
22
|
+
attribute_method_prefix("saved_change_to_", parameters: false)
|
23
|
+
attribute_method_suffix("_before_last_save", parameters: false)
|
23
24
|
|
24
25
|
# Attribute methods for "will change if I call save?"
|
25
|
-
attribute_method_affix(prefix: "will_save_change_to_", suffix: "?")
|
26
|
-
attribute_method_suffix("_change_to_be_saved", "_in_database")
|
26
|
+
attribute_method_affix(prefix: "will_save_change_to_", suffix: "?", parameters: "**options")
|
27
|
+
attribute_method_suffix("_change_to_be_saved", "_in_database", parameters: false)
|
28
|
+
end
|
29
|
+
|
30
|
+
module ClassMethods
|
31
|
+
def partial_writes
|
32
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
33
|
+
ActiveRecord::Base.partial_writes is deprecated and will be removed in Rails 7.1.
|
34
|
+
Use `partial_updates` and `partial_inserts` instead.
|
35
|
+
MSG
|
36
|
+
partial_updates && partial_inserts
|
37
|
+
end
|
38
|
+
|
39
|
+
def partial_writes?
|
40
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
41
|
+
`ActiveRecord::Base.partial_writes?` is deprecated and will be removed in Rails 7.1.
|
42
|
+
Use `partial_updates?` and `partial_inserts?` instead.
|
43
|
+
MSG
|
44
|
+
partial_updates? && partial_inserts?
|
45
|
+
end
|
46
|
+
|
47
|
+
def partial_writes=(value)
|
48
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
49
|
+
`ActiveRecord::Base.partial_writes=` is deprecated and will be removed in Rails 7.1.
|
50
|
+
Use `partial_updates=` and `partial_inserts=` instead.
|
51
|
+
MSG
|
52
|
+
self.partial_updates = self.partial_inserts = value
|
53
|
+
end
|
27
54
|
end
|
28
55
|
|
29
56
|
# <tt>reload</tt> the record and clears changed attributes.
|
@@ -156,12 +183,6 @@ module ActiveRecord
|
|
156
183
|
end
|
157
184
|
|
158
185
|
private
|
159
|
-
def write_attribute_without_type_cast(attr_name, value)
|
160
|
-
result = super
|
161
|
-
clear_attribute_change(attr_name)
|
162
|
-
result
|
163
|
-
end
|
164
|
-
|
165
186
|
def _touch_row(attribute_names, time)
|
166
187
|
@_touch_attr_names = Set.new(attribute_names)
|
167
188
|
|
@@ -191,20 +212,32 @@ module ActiveRecord
|
|
191
212
|
@_touch_attr_names, @_skip_dirty_tracking = nil, nil
|
192
213
|
end
|
193
214
|
|
194
|
-
def _update_record(attribute_names =
|
215
|
+
def _update_record(attribute_names = attribute_names_for_partial_updates)
|
195
216
|
affected_rows = super
|
196
217
|
changes_applied
|
197
218
|
affected_rows
|
198
219
|
end
|
199
220
|
|
200
|
-
def _create_record(attribute_names =
|
221
|
+
def _create_record(attribute_names = attribute_names_for_partial_inserts)
|
201
222
|
id = super
|
202
223
|
changes_applied
|
203
224
|
id
|
204
225
|
end
|
205
226
|
|
206
|
-
def
|
207
|
-
|
227
|
+
def attribute_names_for_partial_updates
|
228
|
+
partial_updates? ? changed_attribute_names_to_save : attribute_names
|
229
|
+
end
|
230
|
+
|
231
|
+
def attribute_names_for_partial_inserts
|
232
|
+
if partial_inserts?
|
233
|
+
changed_attribute_names_to_save
|
234
|
+
else
|
235
|
+
attribute_names.reject do |attr_name|
|
236
|
+
if column_for_attribute(attr_name).default_function
|
237
|
+
!attribute_changed?(attr_name)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
208
241
|
end
|
209
242
|
end
|
210
243
|
end
|
@@ -78,7 +78,7 @@ module ActiveRecord
|
|
78
78
|
@quoted_primary_key ||= connection.quote_column_name(primary_key)
|
79
79
|
end
|
80
80
|
|
81
|
-
def reset_primary_key
|
81
|
+
def reset_primary_key # :nodoc:
|
82
82
|
if base_class?
|
83
83
|
self.primary_key = get_primary_key(base_class.name)
|
84
84
|
else
|
@@ -86,7 +86,7 @@ module ActiveRecord
|
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
89
|
-
def get_primary_key(base_name)
|
89
|
+
def get_primary_key(base_name) # :nodoc:
|
90
90
|
if base_name && primary_key_prefix_type == :table_name
|
91
91
|
base_name.foreign_key(false)
|
92
92
|
elsif base_name && primary_key_prefix_type == :table_name_with_underscore
|