activerecord 6.1.4.1 → 7.0.1
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 +1132 -936
- 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 +118 -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 +6 -21
- 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 +34 -9
- 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 +37 -23
- data/lib/active_record/connection_adapters/mysql/quoting.rb +35 -21
- 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 +29 -18
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +205 -105
- 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 +2 -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 +6 -6
- 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 +243 -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_dumper.rb +10 -3
- 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 +59 -14
@@ -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,6 +283,7 @@ 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
|
|
@@ -305,7 +293,7 @@ module ActiveRecord
|
|
305
293
|
end
|
306
294
|
|
307
295
|
# Returns the association instance for the given name, instantiating it if it doesn't already exist
|
308
|
-
def association(name)
|
296
|
+
def association(name) # :nodoc:
|
309
297
|
association = association_instance_get(name)
|
310
298
|
|
311
299
|
if association.nil?
|
@@ -328,17 +316,7 @@ module ActiveRecord
|
|
328
316
|
super
|
329
317
|
end
|
330
318
|
|
331
|
-
def reload(*) # :nodoc:
|
332
|
-
clear_association_cache
|
333
|
-
super
|
334
|
-
end
|
335
|
-
|
336
319
|
private
|
337
|
-
# Clears out the association cache.
|
338
|
-
def clear_association_cache
|
339
|
-
@association_cache.clear if persisted?
|
340
|
-
end
|
341
|
-
|
342
320
|
def init_internals
|
343
321
|
@association_cache = {}
|
344
322
|
super
|
@@ -398,6 +376,8 @@ module ActiveRecord
|
|
398
376
|
# create_other(attributes={}) | X | | X
|
399
377
|
# create_other!(attributes={}) | X | | X
|
400
378
|
# reload_other | X | X | X
|
379
|
+
# other_changed? | X | X |
|
380
|
+
# other_previously_changed? | X | X |
|
401
381
|
#
|
402
382
|
# === Collection associations (one-to-many / many-to-many)
|
403
383
|
# | | | has_many
|
@@ -614,19 +594,27 @@ module ActiveRecord
|
|
614
594
|
# you can also define callbacks that get triggered when you add an object to or remove an
|
615
595
|
# object from an association collection.
|
616
596
|
#
|
617
|
-
# class
|
618
|
-
#
|
597
|
+
# class Firm < ActiveRecord::Base
|
598
|
+
# has_many :clients,
|
599
|
+
# dependent: :destroy,
|
600
|
+
# after_add: :congratulate_client,
|
601
|
+
# after_remove: :log_after_remove
|
619
602
|
#
|
620
|
-
# def
|
621
|
-
# ...
|
603
|
+
# def congratulate_client(record)
|
604
|
+
# # ...
|
605
|
+
# end
|
606
|
+
#
|
607
|
+
# def log_after_remove(record)
|
608
|
+
# # ...
|
622
609
|
# end
|
623
|
-
# end
|
624
610
|
#
|
625
611
|
# It's possible to stack callbacks by passing them as an array. Example:
|
626
612
|
#
|
627
|
-
# class
|
628
|
-
#
|
629
|
-
#
|
613
|
+
# class Firm < ActiveRecord::Base
|
614
|
+
# has_many :clients,
|
615
|
+
# dependent: :destroy,
|
616
|
+
# after_add: [:congratulate_client, -> (firm, record) { firm.log << "after_adding#{record.id}" }],
|
617
|
+
# after_remove: :log_after_remove
|
630
618
|
# end
|
631
619
|
#
|
632
620
|
# Possible callbacks are: +before_add+, +after_add+, +before_remove+ and +after_remove+.
|
@@ -637,6 +625,18 @@ module ActiveRecord
|
|
637
625
|
# Similarly, if any of the +before_remove+ callbacks throw an exception, the object
|
638
626
|
# will not be removed from the collection.
|
639
627
|
#
|
628
|
+
# Note: To trigger remove callbacks, you must use +destroy+ / +destroy_all+ methods. For example:
|
629
|
+
#
|
630
|
+
# * <tt>firm.clients.destroy(client)</tt>
|
631
|
+
# * <tt>firm.clients.destroy(*clients)</tt>
|
632
|
+
# * <tt>firm.clients.destroy_all</tt>
|
633
|
+
#
|
634
|
+
# +delete+ / +delete_all+ methods like the following do *not* trigger remove callbacks:
|
635
|
+
#
|
636
|
+
# * <tt>firm.clients.delete(client)</tt>
|
637
|
+
# * <tt>firm.clients.delete(*clients)</tt>
|
638
|
+
# * <tt>firm.clients.delete_all</tt>
|
639
|
+
#
|
640
640
|
# == Association extensions
|
641
641
|
#
|
642
642
|
# The proxy objects that control the access to associations can be extended through anonymous
|
@@ -780,9 +780,10 @@ module ActiveRecord
|
|
780
780
|
# inverse detection only works on #has_many, #has_one, and
|
781
781
|
# #belongs_to associations.
|
782
782
|
#
|
783
|
-
# <tt>:foreign_key</tt> and <tt>:through</tt> options on the associations
|
784
|
-
#
|
785
|
-
#
|
783
|
+
# <tt>:foreign_key</tt> and <tt>:through</tt> options on the associations
|
784
|
+
# will also prevent the association's inverse from being found automatically,
|
785
|
+
# as will a custom scopes in some cases. See further details in the
|
786
|
+
# {Active Record Associations guide}[https://guides.rubyonrails.org/association_basics.html#bi-directional-associations].
|
786
787
|
#
|
787
788
|
# The automatic guessing of the inverse association uses a heuristic based
|
788
789
|
# on the name of the class, so it may not work for all associations,
|
@@ -1410,6 +1411,11 @@ module ActiveRecord
|
|
1410
1411
|
# join model. This allows associated records to be built which will automatically create
|
1411
1412
|
# the appropriate join model records when they are saved. (See the 'Association Join Models'
|
1412
1413
|
# section above.)
|
1414
|
+
# [:disable_joins]
|
1415
|
+
# Specifies whether joins should be skipped for an association. If set to true, two or more queries
|
1416
|
+
# will be generated. Note that in some cases, if order or limit is applied, it will be done in-memory
|
1417
|
+
# due to database limitations. This option is only applicable on `has_many :through` associations as
|
1418
|
+
# `has_many` alone do not perform a join.
|
1413
1419
|
# [:source]
|
1414
1420
|
# Specifies the source association name used by #has_many <tt>:through</tt> queries.
|
1415
1421
|
# Only use it if the name cannot be inferred from the association.
|
@@ -1439,7 +1445,8 @@ module ActiveRecord
|
|
1439
1445
|
# Useful for defining methods on associations, especially when they should be shared between multiple
|
1440
1446
|
# association objects.
|
1441
1447
|
# [:strict_loading]
|
1442
|
-
#
|
1448
|
+
# When set to +true+, enforces strict loading every time the associated record is loaded through this
|
1449
|
+
# association.
|
1443
1450
|
# [:ensuring_owner_was]
|
1444
1451
|
# Specifies an instance method to be called on the owner. The method must return true in order for the
|
1445
1452
|
# associated records to be deleted in a background job.
|
@@ -1453,6 +1460,7 @@ module ActiveRecord
|
|
1453
1460
|
# has_many :tags, as: :taggable
|
1454
1461
|
# has_many :reports, -> { readonly }
|
1455
1462
|
# has_many :subscribers, through: :subscriptions, source: :user
|
1463
|
+
# has_many :subscribers, through: :subscriptions, disable_joins: true
|
1456
1464
|
# has_many :comments, strict_loading: true
|
1457
1465
|
def has_many(name, scope = nil, **options, &extension)
|
1458
1466
|
reflection = Builder::HasMany.build(self, name, scope, options, &extension)
|
@@ -1558,8 +1566,21 @@ module ActiveRecord
|
|
1558
1566
|
# source reflection. You can only use a <tt>:through</tt> query through a #has_one
|
1559
1567
|
# or #belongs_to association on the join model.
|
1560
1568
|
#
|
1569
|
+
# If the association on the join model is a #belongs_to, the collection can be modified
|
1570
|
+
# and the records on the <tt>:through</tt> model will be automatically created and removed
|
1571
|
+
# as appropriate. Otherwise, the collection is read-only, so you should manipulate the
|
1572
|
+
# <tt>:through</tt> association directly.
|
1573
|
+
#
|
1561
1574
|
# 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
|
1575
|
+
# a good idea to set the <tt>:inverse_of</tt> option on the source association on the
|
1576
|
+
# join model. This allows associated records to be built which will automatically create
|
1577
|
+
# the appropriate join model records when they are saved. (See the 'Association Join Models'
|
1578
|
+
# section above.)
|
1579
|
+
# [:disable_joins]
|
1580
|
+
# Specifies whether joins should be skipped for an association. If set to true, two or more queries
|
1581
|
+
# will be generated. Note that in some cases, if order or limit is applied, it will be done in-memory
|
1582
|
+
# due to database limitations. This option is only applicable on `has_one :through` associations as
|
1583
|
+
# `has_one` alone does not perform a join.
|
1563
1584
|
# [:source]
|
1564
1585
|
# Specifies the source association name used by #has_one <tt>:through</tt> queries.
|
1565
1586
|
# Only use it if the name cannot be inferred from the association.
|
@@ -1601,6 +1622,7 @@ module ActiveRecord
|
|
1601
1622
|
# has_one :attachment, as: :attachable
|
1602
1623
|
# has_one :boss, -> { readonly }
|
1603
1624
|
# has_one :club, through: :membership
|
1625
|
+
# has_one :club, through: :membership, disable_joins: true
|
1604
1626
|
# has_one :primary_address, -> { where(primary: true) }, through: :addressables, source: :addressable
|
1605
1627
|
# has_one :credit_card, required: true
|
1606
1628
|
# has_one :credit_card, strict_loading: true
|
@@ -1637,6 +1659,10 @@ module ActiveRecord
|
|
1637
1659
|
# if the record is invalid.
|
1638
1660
|
# [reload_association]
|
1639
1661
|
# Returns the associated object, forcing a database read.
|
1662
|
+
# [association_changed?]
|
1663
|
+
# Returns true if a new associate object has been assigned and the next save will update the foreign key.
|
1664
|
+
# [association_previously_changed?]
|
1665
|
+
# Returns true if the previous save updated the association to reference a new associate object.
|
1640
1666
|
#
|
1641
1667
|
# === Example
|
1642
1668
|
#
|
@@ -1647,6 +1673,8 @@ module ActiveRecord
|
|
1647
1673
|
# * <tt>Post#create_author</tt> (similar to <tt>post.author = Author.new; post.author.save; post.author</tt>)
|
1648
1674
|
# * <tt>Post#create_author!</tt> (similar to <tt>post.author = Author.new; post.author.save!; post.author</tt>)
|
1649
1675
|
# * <tt>Post#reload_author</tt>
|
1676
|
+
# * <tt>Post#author_changed?</tt>
|
1677
|
+
# * <tt>Post#author_previously_changed?</tt>
|
1650
1678
|
# The declaration can also include an +options+ hash to specialize the behavior of the association.
|
1651
1679
|
#
|
1652
1680
|
# === Scopes
|
@@ -1780,7 +1808,7 @@ module ActiveRecord
|
|
1780
1808
|
# The join table should not have a primary key or a model associated with it. You must manually generate the
|
1781
1809
|
# join table with a migration such as this:
|
1782
1810
|
#
|
1783
|
-
# class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration[
|
1811
|
+
# class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration[7.0]
|
1784
1812
|
# def change
|
1785
1813
|
# create_join_table :developers, :projects
|
1786
1814
|
# 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
|