activerecord 6.1.7.8 → 7.0.8.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1582 -1018
- data/README.rdoc +3 -3
- 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 +20 -22
- data/lib/active_record/associations/collection_proxy.rb +15 -5
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/has_many_association.rb +8 -5
- 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 +23 -15
- data/lib/active_record/associations/preloader/association.rb +186 -52
- 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 +50 -14
- 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 +138 -100
- 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 +8 -6
- data/lib/active_record/attribute_methods/serialization.rb +57 -19
- 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 +19 -22
- 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 +14 -16
- data/lib/active_record/coders/yaml_column.rb +4 -8
- 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 +52 -23
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +82 -25
- data/lib/active_record/connection_adapters/abstract/transaction.rb +15 -22
- data/lib/active_record/connection_adapters/abstract_adapter.rb +144 -82
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +115 -85
- data/lib/active_record/connection_adapters/column.rb +4 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +37 -25
- data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -23
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +4 -1
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +7 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +20 -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 +19 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +20 -17
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- 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 +76 -73
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +34 -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 +40 -21
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +207 -106
- data/lib/active_record/connection_adapters/schema_cache.rb +39 -38
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +25 -19
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +33 -18
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +19 -17
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +98 -36
- data/lib/active_record/connection_adapters.rb +6 -5
- data/lib/active_record/connection_handling.rb +49 -55
- data/lib/active_record/core.rb +123 -148
- 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 +15 -32
- data/lib/active_record/delegated_type.rb +53 -12
- 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 +67 -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 +206 -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 +50 -43
- data/lib/active_record/errors.rb +67 -4
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +15 -1
- data/lib/active_record/fixture_set/table_row.rb +41 -6
- data/lib/active_record/fixture_set/table_rows.rb +4 -4
- data/lib/active_record/fixtures.rb +20 -23
- data/lib/active_record/future_result.rb +139 -0
- data/lib/active_record/gem_version.rb +5 -5
- 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 +1 -5
- data/lib/active_record/legacy_yaml_adapter.rb +2 -39
- data/lib/active_record/locking/optimistic.rb +36 -21
- data/lib/active_record/locking/pessimistic.rb +10 -4
- data/lib/active_record/log_subscriber.rb +23 -7
- data/lib/active_record/middleware/database_selector/resolver.rb +6 -10
- data/lib/active_record/middleware/database_selector.rb +18 -6
- data/lib/active_record/middleware/shard_selector.rb +60 -0
- data/lib/active_record/migration/command_recorder.rb +8 -9
- data/lib/active_record/migration/compatibility.rb +93 -46
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration.rb +167 -87
- data/lib/active_record/model_schema.rb +58 -59
- 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 +231 -61
- data/lib/active_record/query_cache.rb +2 -2
- data/lib/active_record/query_logs.rb +149 -0
- data/lib/active_record/querying.rb +16 -6
- data/lib/active_record/railtie.rb +136 -22
- data/lib/active_record/railties/controller_runtime.rb +4 -5
- data/lib/active_record/railties/databases.rake +78 -136
- data/lib/active_record/readonly_attributes.rb +11 -0
- data/lib/active_record/reflection.rb +80 -49
- data/lib/active_record/relation/batches/batch_enumerator.rb +19 -5
- data/lib/active_record/relation/batches.rb +6 -6
- data/lib/active_record/relation/calculations.rb +92 -60
- 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/association_query_value.rb +20 -1
- data/lib/active_record/relation/predicate_builder.rb +1 -6
- data/lib/active_record/relation/query_attribute.rb +28 -11
- data/lib/active_record/relation/query_methods.rb +304 -68
- 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 +189 -88
- data/lib/active_record/result.rb +23 -11
- data/lib/active_record/runtime_registry.rb +9 -13
- data/lib/active_record/sanitization.rb +17 -12
- data/lib/active_record/schema.rb +38 -23
- data/lib/active_record/schema_dumper.rb +29 -19
- data/lib/active_record/schema_migration.rb +4 -4
- data/lib/active_record/scoping/default.rb +60 -13
- data/lib/active_record/scoping/named.rb +3 -11
- data/lib/active_record/scoping.rb +64 -34
- data/lib/active_record/serialization.rb +6 -1
- data/lib/active_record/signed_id.rb +3 -3
- data/lib/active_record/store.rb +2 -2
- data/lib/active_record/suppressor.rb +11 -15
- data/lib/active_record/table_metadata.rb +6 -2
- data/lib/active_record/tasks/database_tasks.rb +127 -60
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/postgresql_database_tasks.rb +19 -13
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +9 -6
- data/lib/active_record/timestamp.rb +3 -4
- data/lib/active_record/transactions.rb +12 -17
- data/lib/active_record/translation.rb +3 -3
- 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 +9 -5
- 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 +4 -4
- data/lib/active_record/validations/presence.rb +2 -2
- data/lib/active_record/validations/uniqueness.rb +4 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +225 -27
- 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/and.rb +4 -0
- 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 +53 -9
@@ -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
|
@@ -451,7 +432,7 @@ module ActiveRecord
|
|
451
432
|
#
|
452
433
|
# == Cardinality and associations
|
453
434
|
#
|
454
|
-
# Active Record associations can be used to describe one-to-one, one-to-many and many-to-many
|
435
|
+
# Active Record associations can be used to describe one-to-one, one-to-many, and many-to-many
|
455
436
|
# relationships between models. Each model uses an association to describe its role in
|
456
437
|
# the relation. The #belongs_to association is always used in the model that has
|
457
438
|
# the foreign key.
|
@@ -605,8 +586,11 @@ module ActiveRecord
|
|
605
586
|
# has_many :birthday_events, ->(user) { where(starts_on: user.birthday) }, class_name: 'Event'
|
606
587
|
# end
|
607
588
|
#
|
608
|
-
# Note: Joining
|
609
|
-
#
|
589
|
+
# Note: Joining or eager loading such associations is not possible because
|
590
|
+
# those operations happen before instance creation. Such associations
|
591
|
+
# _can_ be preloaded, but doing so will perform N+1 queries because there
|
592
|
+
# will be a different scope for each record (similar to preloading
|
593
|
+
# polymorphic scopes).
|
610
594
|
#
|
611
595
|
# == Association callbacks
|
612
596
|
#
|
@@ -614,22 +598,30 @@ module ActiveRecord
|
|
614
598
|
# you can also define callbacks that get triggered when you add an object to or remove an
|
615
599
|
# object from an association collection.
|
616
600
|
#
|
617
|
-
# class
|
618
|
-
#
|
601
|
+
# class Firm < ActiveRecord::Base
|
602
|
+
# has_many :clients,
|
603
|
+
# dependent: :destroy,
|
604
|
+
# after_add: :congratulate_client,
|
605
|
+
# after_remove: :log_after_remove
|
606
|
+
#
|
607
|
+
# def congratulate_client(record)
|
608
|
+
# # ...
|
609
|
+
# end
|
619
610
|
#
|
620
|
-
# def
|
621
|
-
# ...
|
611
|
+
# def log_after_remove(record)
|
612
|
+
# # ...
|
622
613
|
# end
|
623
|
-
# end
|
624
614
|
#
|
625
615
|
# It's possible to stack callbacks by passing them as an array. Example:
|
626
616
|
#
|
627
|
-
# class
|
628
|
-
#
|
629
|
-
#
|
617
|
+
# class Firm < ActiveRecord::Base
|
618
|
+
# has_many :clients,
|
619
|
+
# dependent: :destroy,
|
620
|
+
# after_add: [:congratulate_client, -> (firm, record) { firm.log << "after_adding#{record.id}" }],
|
621
|
+
# after_remove: :log_after_remove
|
630
622
|
# end
|
631
623
|
#
|
632
|
-
# Possible callbacks are: +before_add+, +after_add+, +before_remove
|
624
|
+
# Possible callbacks are: +before_add+, +after_add+, +before_remove+, and +after_remove+.
|
633
625
|
#
|
634
626
|
# If any of the +before_add+ callbacks throw an exception, the object will not be
|
635
627
|
# added to the collection.
|
@@ -637,6 +629,18 @@ module ActiveRecord
|
|
637
629
|
# Similarly, if any of the +before_remove+ callbacks throw an exception, the object
|
638
630
|
# will not be removed from the collection.
|
639
631
|
#
|
632
|
+
# Note: To trigger remove callbacks, you must use +destroy+ / +destroy_all+ methods. For example:
|
633
|
+
#
|
634
|
+
# * <tt>firm.clients.destroy(client)</tt>
|
635
|
+
# * <tt>firm.clients.destroy(*clients)</tt>
|
636
|
+
# * <tt>firm.clients.destroy_all</tt>
|
637
|
+
#
|
638
|
+
# +delete+ / +delete_all+ methods like the following do *not* trigger remove callbacks:
|
639
|
+
#
|
640
|
+
# * <tt>firm.clients.delete(client)</tt>
|
641
|
+
# * <tt>firm.clients.delete(*clients)</tt>
|
642
|
+
# * <tt>firm.clients.delete_all</tt>
|
643
|
+
#
|
640
644
|
# == Association extensions
|
641
645
|
#
|
642
646
|
# The proxy objects that control the access to associations can be extended through anonymous
|
@@ -780,9 +784,10 @@ module ActiveRecord
|
|
780
784
|
# inverse detection only works on #has_many, #has_one, and
|
781
785
|
# #belongs_to associations.
|
782
786
|
#
|
783
|
-
# <tt>:foreign_key</tt> and <tt>:through</tt> options on the associations
|
784
|
-
#
|
785
|
-
#
|
787
|
+
# <tt>:foreign_key</tt> and <tt>:through</tt> options on the associations
|
788
|
+
# will also prevent the association's inverse from being found automatically,
|
789
|
+
# as will a custom scopes in some cases. See further details in the
|
790
|
+
# {Active Record Associations guide}[https://guides.rubyonrails.org/association_basics.html#bi-directional-associations].
|
786
791
|
#
|
787
792
|
# The automatic guessing of the inverse association uses a heuristic based
|
788
793
|
# on the name of the class, so it may not work for all associations,
|
@@ -1330,7 +1335,7 @@ module ActiveRecord
|
|
1330
1335
|
# === Extensions
|
1331
1336
|
#
|
1332
1337
|
# The +extension+ argument allows you to pass a block into a has_many
|
1333
|
-
# association. This is useful for adding new finders, creators and other
|
1338
|
+
# association. This is useful for adding new finders, creators, and other
|
1334
1339
|
# factory-type methods to be used as part of the association.
|
1335
1340
|
#
|
1336
1341
|
# Extension examples:
|
@@ -1410,6 +1415,11 @@ module ActiveRecord
|
|
1410
1415
|
# join model. This allows associated records to be built which will automatically create
|
1411
1416
|
# the appropriate join model records when they are saved. (See the 'Association Join Models'
|
1412
1417
|
# section above.)
|
1418
|
+
# [:disable_joins]
|
1419
|
+
# Specifies whether joins should be skipped for an association. If set to true, two or more queries
|
1420
|
+
# will be generated. Note that in some cases, if order or limit is applied, it will be done in-memory
|
1421
|
+
# due to database limitations. This option is only applicable on <tt>has_many :through</tt> associations as
|
1422
|
+
# +has_many+ alone do not perform a join.
|
1413
1423
|
# [:source]
|
1414
1424
|
# Specifies the source association name used by #has_many <tt>:through</tt> queries.
|
1415
1425
|
# Only use it if the name cannot be inferred from the association.
|
@@ -1439,7 +1449,8 @@ module ActiveRecord
|
|
1439
1449
|
# Useful for defining methods on associations, especially when they should be shared between multiple
|
1440
1450
|
# association objects.
|
1441
1451
|
# [:strict_loading]
|
1442
|
-
#
|
1452
|
+
# When set to +true+, enforces strict loading every time the associated record is loaded through this
|
1453
|
+
# association.
|
1443
1454
|
# [:ensuring_owner_was]
|
1444
1455
|
# Specifies an instance method to be called on the owner. The method must return true in order for the
|
1445
1456
|
# associated records to be deleted in a background job.
|
@@ -1453,6 +1464,7 @@ module ActiveRecord
|
|
1453
1464
|
# has_many :tags, as: :taggable
|
1454
1465
|
# has_many :reports, -> { readonly }
|
1455
1466
|
# has_many :subscribers, through: :subscriptions, source: :user
|
1467
|
+
# has_many :subscribers, through: :subscriptions, disable_joins: true
|
1456
1468
|
# has_many :comments, strict_loading: true
|
1457
1469
|
def has_many(name, scope = nil, **options, &extension)
|
1458
1470
|
reflection = Builder::HasMany.build(self, name, scope, options, &extension)
|
@@ -1558,8 +1570,21 @@ module ActiveRecord
|
|
1558
1570
|
# source reflection. You can only use a <tt>:through</tt> query through a #has_one
|
1559
1571
|
# or #belongs_to association on the join model.
|
1560
1572
|
#
|
1573
|
+
# If the association on the join model is a #belongs_to, the collection can be modified
|
1574
|
+
# and the records on the <tt>:through</tt> model will be automatically created and removed
|
1575
|
+
# as appropriate. Otherwise, the collection is read-only, so you should manipulate the
|
1576
|
+
# <tt>:through</tt> association directly.
|
1577
|
+
#
|
1561
1578
|
# 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
|
1579
|
+
# a good idea to set the <tt>:inverse_of</tt> option on the source association on the
|
1580
|
+
# join model. This allows associated records to be built which will automatically create
|
1581
|
+
# the appropriate join model records when they are saved. (See the 'Association Join Models'
|
1582
|
+
# section above.)
|
1583
|
+
# [:disable_joins]
|
1584
|
+
# Specifies whether joins should be skipped for an association. If set to true, two or more queries
|
1585
|
+
# will be generated. Note that in some cases, if order or limit is applied, it will be done in-memory
|
1586
|
+
# due to database limitations. This option is only applicable on <tt>has_one :through</tt> associations as
|
1587
|
+
# +has_one+ alone does not perform a join.
|
1563
1588
|
# [:source]
|
1564
1589
|
# Specifies the source association name used by #has_one <tt>:through</tt> queries.
|
1565
1590
|
# Only use it if the name cannot be inferred from the association.
|
@@ -1578,6 +1603,12 @@ module ActiveRecord
|
|
1578
1603
|
#
|
1579
1604
|
# Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets
|
1580
1605
|
# <tt>:autosave</tt> to <tt>true</tt>.
|
1606
|
+
# [:touch]
|
1607
|
+
# If true, the associated object will be touched (the +updated_at+ / +updated_on+ attributes set to current time)
|
1608
|
+
# when this record is either saved or destroyed. If you specify a symbol, that attribute
|
1609
|
+
# will be updated with the current time in addition to the +updated_at+ / +updated_on+ attribute.
|
1610
|
+
# Please note that no validation will be performed when touching, and only the +after_touch+,
|
1611
|
+
# +after_commit+, and +after_rollback+ callbacks will be executed.
|
1581
1612
|
# [:inverse_of]
|
1582
1613
|
# Specifies the name of the #belongs_to association on the associated object
|
1583
1614
|
# that is the inverse of this #has_one association.
|
@@ -1601,6 +1632,7 @@ module ActiveRecord
|
|
1601
1632
|
# has_one :attachment, as: :attachable
|
1602
1633
|
# has_one :boss, -> { readonly }
|
1603
1634
|
# has_one :club, through: :membership
|
1635
|
+
# has_one :club, through: :membership, disable_joins: true
|
1604
1636
|
# has_one :primary_address, -> { where(primary: true) }, through: :addressables, source: :addressable
|
1605
1637
|
# has_one :credit_card, required: true
|
1606
1638
|
# has_one :credit_card, strict_loading: true
|
@@ -1637,6 +1669,10 @@ module ActiveRecord
|
|
1637
1669
|
# if the record is invalid.
|
1638
1670
|
# [reload_association]
|
1639
1671
|
# Returns the associated object, forcing a database read.
|
1672
|
+
# [association_changed?]
|
1673
|
+
# Returns true if a new associate object has been assigned and the next save will update the foreign key.
|
1674
|
+
# [association_previously_changed?]
|
1675
|
+
# Returns true if the previous save updated the association to reference a new associate object.
|
1640
1676
|
#
|
1641
1677
|
# === Example
|
1642
1678
|
#
|
@@ -1647,6 +1683,8 @@ module ActiveRecord
|
|
1647
1683
|
# * <tt>Post#create_author</tt> (similar to <tt>post.author = Author.new; post.author.save; post.author</tt>)
|
1648
1684
|
# * <tt>Post#create_author!</tt> (similar to <tt>post.author = Author.new; post.author.save!; post.author</tt>)
|
1649
1685
|
# * <tt>Post#reload_author</tt>
|
1686
|
+
# * <tt>Post#author_changed?</tt>
|
1687
|
+
# * <tt>Post#author_previously_changed?</tt>
|
1650
1688
|
# The declaration can also include an +options+ hash to specialize the behavior of the association.
|
1651
1689
|
#
|
1652
1690
|
# === Scopes
|
@@ -1718,11 +1756,11 @@ module ActiveRecord
|
|
1718
1756
|
# Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for
|
1719
1757
|
# sets <tt>:autosave</tt> to <tt>true</tt>.
|
1720
1758
|
# [:touch]
|
1721
|
-
# If true, the associated object will be touched (the updated_at/
|
1759
|
+
# If true, the associated object will be touched (the +updated_at+ / +updated_on+ attributes set to current time)
|
1722
1760
|
# when this record is either saved or destroyed. If you specify a symbol, that attribute
|
1723
|
-
# will be updated with the current time in addition to the updated_at/
|
1724
|
-
# Please note that
|
1725
|
-
# +after_commit
|
1761
|
+
# will be updated with the current time in addition to the +updated_at+ / +updated_on+ attribute.
|
1762
|
+
# Please note that no validation will be performed when touching, and only the +after_touch+,
|
1763
|
+
# +after_commit+, and +after_rollback+ callbacks will be executed.
|
1726
1764
|
# [:inverse_of]
|
1727
1765
|
# Specifies the name of the #has_one or #has_many association on the associated
|
1728
1766
|
# object that is the inverse of this #belongs_to association.
|
@@ -1780,7 +1818,7 @@ module ActiveRecord
|
|
1780
1818
|
# The join table should not have a primary key or a model associated with it. You must manually generate the
|
1781
1819
|
# join table with a migration such as this:
|
1782
1820
|
#
|
1783
|
-
# class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration[
|
1821
|
+
# class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration[7.0]
|
1784
1822
|
# def change
|
1785
1823
|
# create_join_table :developers, :projects
|
1786
1824
|
# end
|
@@ -1875,7 +1913,7 @@ module ActiveRecord
|
|
1875
1913
|
#
|
1876
1914
|
# The +extension+ argument allows you to pass a block into a
|
1877
1915
|
# has_and_belongs_to_many association. This is useful for adding new
|
1878
|
-
# finders, creators and other factory-type methods to be used as part of
|
1916
|
+
# finders, creators, and other factory-type methods to be used as part of
|
1879
1917
|
# the association.
|
1880
1918
|
#
|
1881
1919
|
# Extension examples:
|
@@ -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)
|