activerecord 6.1.4 → 7.0.0.rc1
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 +1049 -977
- 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/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 +90 -82
- 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 +69 -18
- 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 +35 -23
- data/lib/active_record/connection_adapters/mysql/quoting.rb +35 -21
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +4 -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 +19 -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 +28 -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 +27 -16
- 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 +25 -19
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +15 -16
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +4 -2
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -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 +83 -1
- 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 +40 -36
- 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 +235 -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 +171 -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 +0 -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 +116 -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
- metadata +56 -13
@@ -16,15 +16,45 @@ module ActiveRecord
|
|
16
16
|
end
|
17
17
|
|
18
18
|
module ClassMethods
|
19
|
-
# If you have an attribute that needs to be saved to the database as
|
20
|
-
# object, and retrieved
|
21
|
-
# attribute using this method and
|
22
|
-
#
|
23
|
-
# serialized object must be of that class on assignment and retrieval.
|
24
|
-
# Otherwise SerializationTypeMismatch will be raised.
|
19
|
+
# If you have an attribute that needs to be saved to the database as a
|
20
|
+
# serialized object, and retrieved by deserializing into the same object,
|
21
|
+
# then specify the name of that attribute using this method and serialization
|
22
|
+
# will be handled automatically.
|
25
23
|
#
|
26
|
-
#
|
27
|
-
#
|
24
|
+
# The serialization format may be YAML, JSON, or any custom format using a
|
25
|
+
# custom coder class.
|
26
|
+
#
|
27
|
+
# === Serialization formats
|
28
|
+
#
|
29
|
+
# serialize attr_name [, class_name_or_coder]
|
30
|
+
#
|
31
|
+
# | | database storage |
|
32
|
+
# class_name_or_coder | attribute read/write type | serialized | NULL |
|
33
|
+
# ---------------------+---------------------------+------------+--------+
|
34
|
+
# <not given> | any value that supports | YAML | |
|
35
|
+
# | .to_yaml | | |
|
36
|
+
# | | | |
|
37
|
+
# Array | Array ** | YAML | [] |
|
38
|
+
# | | | |
|
39
|
+
# Hash | Hash ** | YAML | {} |
|
40
|
+
# | | | |
|
41
|
+
# JSON | any value that supports | JSON | |
|
42
|
+
# | .to_json | | |
|
43
|
+
# | | | |
|
44
|
+
# <custom coder class> | any value supported by | custom | custom |
|
45
|
+
# | the custom coder class | | |
|
46
|
+
#
|
47
|
+
# ** If +class_name_or_coder+ is +Array+ or +Hash+, values retrieved will
|
48
|
+
# always be of that type, and any value assigned must be of that type or
|
49
|
+
# +SerializationTypeMismatch+ will be raised.
|
50
|
+
#
|
51
|
+
# ==== Custom coders
|
52
|
+
# A custom coder class or module may be given. This must have +self.load+
|
53
|
+
# and +self.dump+ class/module methods. <tt>self.dump(object)</tt> will be called
|
54
|
+
# to serialize an object and should return the serialized value to be
|
55
|
+
# stored in the database (+nil+ to store as +NULL+). <tt>self.load(string)</tt>
|
56
|
+
# will be called to reverse the process and load (unserialize) from the
|
57
|
+
# database.
|
28
58
|
#
|
29
59
|
# Keep in mind that database adapters handle certain serialization tasks
|
30
60
|
# for you. For instance: +json+ and +jsonb+ types in PostgreSQL will be
|
@@ -38,8 +68,9 @@ module ActiveRecord
|
|
38
68
|
# ==== Parameters
|
39
69
|
#
|
40
70
|
# * +attr_name+ - The field name that should be serialized.
|
41
|
-
# * +class_name_or_coder+ - Optional,
|
42
|
-
# or a
|
71
|
+
# * +class_name_or_coder+ - Optional, may be be +Array+ or +Hash+ or
|
72
|
+
# +JSON+ or a custom coder class or module which responds to +.load+
|
73
|
+
# and +.dump+. See table above.
|
43
74
|
#
|
44
75
|
# ==== Options
|
45
76
|
#
|
@@ -49,7 +80,7 @@ module ActiveRecord
|
|
49
80
|
#
|
50
81
|
# ==== Example
|
51
82
|
#
|
52
|
-
# # Serialize a preferences attribute.
|
83
|
+
# # Serialize a preferences attribute using YAML coder.
|
53
84
|
# class User < ActiveRecord::Base
|
54
85
|
# serialize :preferences
|
55
86
|
# end
|
@@ -63,6 +94,28 @@ module ActiveRecord
|
|
63
94
|
# class User < ActiveRecord::Base
|
64
95
|
# serialize :preferences, Hash
|
65
96
|
# end
|
97
|
+
#
|
98
|
+
# # Serialize preferences using a custom coder.
|
99
|
+
# class Rot13JSON
|
100
|
+
# def self.rot13(string)
|
101
|
+
# string.tr("a-zA-Z", "n-za-mN-ZA-M")
|
102
|
+
# end
|
103
|
+
#
|
104
|
+
# # returns serialized string that will be stored in the database
|
105
|
+
# def self.dump(object)
|
106
|
+
# ActiveSupport::JSON.encode(object).rot13
|
107
|
+
# end
|
108
|
+
#
|
109
|
+
# # reverses the above, turning the serialized string from the database
|
110
|
+
# # back into its original value
|
111
|
+
# def self.load(string)
|
112
|
+
# ActiveSupport::JSON.decode(string.rot13)
|
113
|
+
# end
|
114
|
+
# end
|
115
|
+
#
|
116
|
+
# class User < ActiveRecord::Base
|
117
|
+
# serialize :preferences, Rot13JSON
|
118
|
+
# end
|
66
119
|
def serialize(attr_name, class_name_or_coder = Object, **options)
|
67
120
|
# When ::JSON is used, force it to go through the Active Support JSON encoder
|
68
121
|
# to ensure special objects (e.g. Active Record models) are dumped correctly
|
@@ -75,11 +128,12 @@ module ActiveRecord
|
|
75
128
|
Coders::YAMLColumn.new(attr_name, class_name_or_coder)
|
76
129
|
end
|
77
130
|
|
78
|
-
|
131
|
+
attribute(attr_name, **options) do |cast_type|
|
79
132
|
if type_incompatible_with_serialize?(cast_type, class_name_or_coder)
|
80
133
|
raise ColumnNotSerializableError.new(attr_name, cast_type)
|
81
134
|
end
|
82
135
|
|
136
|
+
cast_type = cast_type.subtype if Type::Serialized === cast_type
|
83
137
|
Type::Serialized.new(cast_type, coder)
|
84
138
|
end
|
85
139
|
end
|
@@ -25,6 +25,8 @@ module ActiveRecord
|
|
25
25
|
rescue ArgumentError
|
26
26
|
nil
|
27
27
|
end
|
28
|
+
elsif value.respond_to?(:infinite?) && value.infinite?
|
29
|
+
value
|
28
30
|
else
|
29
31
|
map_avoiding_infinite_recursion(super) { |v| cast(v) }
|
30
32
|
end
|
@@ -36,7 +38,7 @@ module ActiveRecord
|
|
36
38
|
|
37
39
|
if value.acts_like?(:time)
|
38
40
|
value.in_time_zone
|
39
|
-
elsif value.
|
41
|
+
elsif value.respond_to?(:infinite?) && value.infinite?
|
40
42
|
value
|
41
43
|
else
|
42
44
|
map_avoiding_infinite_recursion(value) { |v| convert_time_to_time_zone(v) }
|
@@ -61,8 +63,7 @@ module ActiveRecord
|
|
61
63
|
extend ActiveSupport::Concern
|
62
64
|
|
63
65
|
included do
|
64
|
-
|
65
|
-
|
66
|
+
class_attribute :time_zone_aware_attributes, instance_writer: false, default: false
|
66
67
|
class_attribute :skip_time_zone_conversion_for_attributes, instance_writer: false, default: []
|
67
68
|
class_attribute :time_zone_aware_types, instance_writer: false, default: [ :datetime, :time ]
|
68
69
|
end
|
@@ -6,7 +6,7 @@ module ActiveRecord
|
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
8
|
included do
|
9
|
-
attribute_method_suffix "="
|
9
|
+
attribute_method_suffix "=", parameters: "value"
|
10
10
|
end
|
11
11
|
|
12
12
|
module ClassMethods # :nodoc:
|
@@ -15,10 +15,12 @@ module ActiveRecord
|
|
15
15
|
ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
|
16
16
|
owner, name, writer: true,
|
17
17
|
) do |temp_method_name, attr_name_expr|
|
18
|
-
owner
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
owner.define_cached_method("#{name}=", as: temp_method_name, namespace: :active_record) do |batch|
|
19
|
+
batch <<
|
20
|
+
"def #{temp_method_name}(value)" <<
|
21
|
+
" _write_attribute(#{attr_name_expr}, value)" <<
|
22
|
+
"end"
|
23
|
+
end
|
22
24
|
end
|
23
25
|
end
|
24
26
|
end
|
@@ -42,11 +44,6 @@ module ActiveRecord
|
|
42
44
|
|
43
45
|
alias :attribute= :_write_attribute
|
44
46
|
private :attribute=
|
45
|
-
|
46
|
-
private
|
47
|
-
def write_attribute_without_type_cast(attr_name, value)
|
48
|
-
@attributes.write_cast_value(attr_name, value)
|
49
|
-
end
|
50
47
|
end
|
51
48
|
end
|
52
49
|
end
|
@@ -23,7 +23,7 @@ module ActiveRecord
|
|
23
23
|
|
24
24
|
RESTRICTED_CLASS_METHODS = %w(private public protected allocate new name parent superclass)
|
25
25
|
|
26
|
-
class GeneratedAttributeMethods < Module
|
26
|
+
class GeneratedAttributeMethods < Module # :nodoc:
|
27
27
|
include Mutex_m
|
28
28
|
end
|
29
29
|
|
@@ -39,7 +39,7 @@ module ActiveRecord
|
|
39
39
|
end
|
40
40
|
|
41
41
|
module ClassMethods
|
42
|
-
def inherited(child_class)
|
42
|
+
def inherited(child_class) # :nodoc:
|
43
43
|
child_class.initialize_generated_modules
|
44
44
|
super
|
45
45
|
end
|
@@ -267,9 +267,8 @@ module ActiveRecord
|
|
267
267
|
|
268
268
|
# Returns an <tt>#inspect</tt>-like string for the value of the
|
269
269
|
# attribute +attr_name+. String attributes are truncated up to 50
|
270
|
-
# characters
|
271
|
-
#
|
272
|
-
# <tt>#inspect</tt> without modification.
|
270
|
+
# characters. Other attributes return the value of <tt>#inspect</tt>
|
271
|
+
# without modification.
|
273
272
|
#
|
274
273
|
# person = Person.create!(name: 'David Heinemeier Hansson ' * 3)
|
275
274
|
#
|
@@ -277,7 +276,7 @@ module ActiveRecord
|
|
277
276
|
# # => "\"David Heinemeier Hansson David Heinemeier Hansson ...\""
|
278
277
|
#
|
279
278
|
# person.attribute_for_inspect(:created_at)
|
280
|
-
# # => "\"2012-10-22 00:15:07\""
|
279
|
+
# # => "\"2012-10-22 00:15:07.000000000 +0000\""
|
281
280
|
#
|
282
281
|
# person.attribute_for_inspect(:tag_ids)
|
283
282
|
# # => "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]"
|
@@ -385,25 +384,25 @@ module ActiveRecord
|
|
385
384
|
end
|
386
385
|
|
387
386
|
def attributes_with_values(attribute_names)
|
388
|
-
attribute_names.index_with
|
389
|
-
_read_attribute(name)
|
390
|
-
end
|
387
|
+
attribute_names.index_with { |name| @attributes[name] }
|
391
388
|
end
|
392
389
|
|
393
|
-
# Filters the primary keys
|
390
|
+
# Filters the primary keys, readonly attributes and virtual columns from the attribute names.
|
394
391
|
def attributes_for_update(attribute_names)
|
395
392
|
attribute_names &= self.class.column_names
|
396
393
|
attribute_names.delete_if do |name|
|
397
|
-
self.class.readonly_attribute?(name)
|
394
|
+
self.class.readonly_attribute?(name) ||
|
395
|
+
column_for_attribute(name).virtual?
|
398
396
|
end
|
399
397
|
end
|
400
398
|
|
401
|
-
# Filters out the primary keys, from the attribute names, when the primary
|
399
|
+
# Filters out the virtual columns and also primary keys, from the attribute names, when the primary
|
402
400
|
# key is to be generated (e.g. the id attribute has no value).
|
403
401
|
def attributes_for_create(attribute_names)
|
404
402
|
attribute_names &= self.class.column_names
|
405
403
|
attribute_names.delete_if do |name|
|
406
|
-
pk_attribute?(name) && id.nil?
|
404
|
+
(pk_attribute?(name) && id.nil?) ||
|
405
|
+
column_for_attribute(name).virtual?
|
407
406
|
end
|
408
407
|
end
|
409
408
|
|
@@ -414,7 +413,7 @@ module ActiveRecord
|
|
414
413
|
inspected_value = if value.is_a?(String) && value.length > 50
|
415
414
|
"#{value[0, 50]}...".inspect
|
416
415
|
elsif value.is_a?(Date) || value.is_a?(Time)
|
417
|
-
%("#{value.
|
416
|
+
%("#{value.to_formatted_s(:inspect)}")
|
418
417
|
else
|
419
418
|
value.inspect
|
420
419
|
end
|
@@ -12,9 +12,6 @@ module ActiveRecord
|
|
12
12
|
end
|
13
13
|
|
14
14
|
module ClassMethods
|
15
|
-
##
|
16
|
-
# :call-seq: attribute(name, cast_type = nil, **options)
|
17
|
-
#
|
18
15
|
# Defines an attribute with a type on this model. It will override the
|
19
16
|
# type of existing attributes if needed. This allows control over how
|
20
17
|
# values are converted to and from SQL when assigned to a model. It also
|
@@ -208,14 +205,31 @@ module ActiveRecord
|
|
208
205
|
# tracking is performed. The methods +changed?+ and +changed_in_place?+
|
209
206
|
# will be called from ActiveModel::Dirty. See the documentation for those
|
210
207
|
# methods in ActiveModel::Type::Value for more details.
|
211
|
-
def attribute(name, cast_type = nil, **options
|
208
|
+
def attribute(name, cast_type = nil, default: NO_DEFAULT_PROVIDED, **options)
|
212
209
|
name = name.to_s
|
210
|
+
name = attribute_aliases[name] || name
|
211
|
+
|
213
212
|
reload_schema_from_cache
|
214
213
|
|
214
|
+
case cast_type
|
215
|
+
when Symbol
|
216
|
+
cast_type = Type.lookup(cast_type, **options, adapter: Type.adapter_name_from(self))
|
217
|
+
when nil
|
218
|
+
if (prev_cast_type, prev_default = attributes_to_define_after_schema_loads[name])
|
219
|
+
default = prev_default if default == NO_DEFAULT_PROVIDED
|
220
|
+
else
|
221
|
+
prev_cast_type = -> subtype { subtype }
|
222
|
+
end
|
223
|
+
|
224
|
+
cast_type = if block_given?
|
225
|
+
-> subtype { yield Proc === prev_cast_type ? prev_cast_type[subtype] : prev_cast_type }
|
226
|
+
else
|
227
|
+
prev_cast_type
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
215
231
|
self.attributes_to_define_after_schema_loads =
|
216
|
-
attributes_to_define_after_schema_loads.merge(
|
217
|
-
name => [cast_type || block, options]
|
218
|
-
)
|
232
|
+
attributes_to_define_after_schema_loads.merge(name => [cast_type, default])
|
219
233
|
end
|
220
234
|
|
221
235
|
# This is the low level API which sits beneath +attribute+. It only
|
@@ -248,8 +262,9 @@ module ActiveRecord
|
|
248
262
|
|
249
263
|
def load_schema! # :nodoc:
|
250
264
|
super
|
251
|
-
attributes_to_define_after_schema_loads.each do |name, (
|
252
|
-
|
265
|
+
attributes_to_define_after_schema_loads.each do |name, (cast_type, default)|
|
266
|
+
cast_type = cast_type[type_for_attribute(name)] if Proc === cast_type
|
267
|
+
define_attribute(name, cast_type, default: default)
|
253
268
|
end
|
254
269
|
end
|
255
270
|
|
@@ -272,32 +287,6 @@ module ActiveRecord
|
|
272
287
|
end
|
273
288
|
_default_attributes[name] = default_attribute
|
274
289
|
end
|
275
|
-
|
276
|
-
def decorate_attribute_type(attr_name, **default)
|
277
|
-
type, options = attributes_to_define_after_schema_loads[attr_name]
|
278
|
-
|
279
|
-
default.with_defaults!(default: options[:default]) if options&.key?(:default)
|
280
|
-
|
281
|
-
attribute(attr_name, **default) do |cast_type|
|
282
|
-
if type && !type.is_a?(Proc)
|
283
|
-
cast_type = _lookup_cast_type(attr_name, type, options)
|
284
|
-
end
|
285
|
-
|
286
|
-
yield cast_type
|
287
|
-
end
|
288
|
-
end
|
289
|
-
|
290
|
-
def _lookup_cast_type(name, type, options)
|
291
|
-
case type
|
292
|
-
when Symbol
|
293
|
-
adapter_name = ActiveRecord::Type.adapter_name_from(self)
|
294
|
-
ActiveRecord::Type.lookup(type, **options.except(:default), adapter: adapter_name)
|
295
|
-
when Proc
|
296
|
-
type[type_for_attribute(name)]
|
297
|
-
else
|
298
|
-
type || type_for_attribute(name)
|
299
|
-
end
|
300
|
-
end
|
301
290
|
end
|
302
291
|
end
|
303
292
|
end
|
@@ -138,7 +138,7 @@ module ActiveRecord
|
|
138
138
|
module AutosaveAssociation
|
139
139
|
extend ActiveSupport::Concern
|
140
140
|
|
141
|
-
module AssociationBuilderExtension
|
141
|
+
module AssociationBuilderExtension # :nodoc:
|
142
142
|
def self.build(model, reflection)
|
143
143
|
model.send(:add_autosave_association_callbacks, reflection)
|
144
144
|
end
|
@@ -150,25 +150,10 @@ module ActiveRecord
|
|
150
150
|
|
151
151
|
included do
|
152
152
|
Associations::Builder::Association.extensions << AssociationBuilderExtension
|
153
|
-
mattr_accessor :index_nested_attribute_errors, instance_writer: false, default: false
|
154
153
|
end
|
155
154
|
|
156
155
|
module ClassMethods # :nodoc:
|
157
156
|
private
|
158
|
-
if Module.method(:method_defined?).arity == 1 # MRI 2.5 and older
|
159
|
-
using Module.new {
|
160
|
-
refine Module do
|
161
|
-
def method_defined?(method, inherit = true)
|
162
|
-
if inherit
|
163
|
-
super(method)
|
164
|
-
else
|
165
|
-
instance_methods(false).include?(method.to_sym)
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
}
|
170
|
-
end
|
171
|
-
|
172
157
|
def define_non_cyclic_method(name, &block)
|
173
158
|
return if method_defined?(name, false)
|
174
159
|
|
@@ -210,7 +195,7 @@ module ActiveRecord
|
|
210
195
|
after_create save_method
|
211
196
|
after_update save_method
|
212
197
|
elsif reflection.has_one?
|
213
|
-
|
198
|
+
define_non_cyclic_method(save_method) { save_has_one_association(reflection) }
|
214
199
|
# Configures two callbacks instead of a single after_save so that
|
215
200
|
# the model may rely on their execution order relative to its
|
216
201
|
# own callbacks.
|
@@ -349,7 +334,7 @@ module ActiveRecord
|
|
349
334
|
|
350
335
|
unless valid = record.valid?(context)
|
351
336
|
if reflection.options[:autosave]
|
352
|
-
indexed_attribute = !index.nil? && (reflection.options[:index_errors] || ActiveRecord
|
337
|
+
indexed_attribute = !index.nil? && (reflection.options[:index_errors] || ActiveRecord.index_nested_attribute_errors)
|
353
338
|
|
354
339
|
record.errors.group_by_attribute.each { |attribute, errors|
|
355
340
|
attribute = normalize_reflection_attribute(indexed_attribute, reflection, index, attribute)
|
@@ -419,6 +404,8 @@ module ActiveRecord
|
|
419
404
|
saved = true
|
420
405
|
|
421
406
|
if autosave != false && (new_record_before_save || record.new_record?)
|
407
|
+
association.set_inverse_instance(record)
|
408
|
+
|
422
409
|
if autosave
|
423
410
|
saved = association.insert_record(record, false)
|
424
411
|
elsif !reflection.nested?
|
@@ -462,9 +449,7 @@ module ActiveRecord
|
|
462
449
|
if (autosave && record.changed_for_autosave?) || record_changed?(reflection, record, key)
|
463
450
|
unless reflection.through_reflection
|
464
451
|
record[reflection.foreign_key] = key
|
465
|
-
|
466
|
-
record.association(inverse_reflection.name).inversed_from(self)
|
467
|
-
end
|
452
|
+
association.set_inverse_instance(record)
|
468
453
|
end
|
469
454
|
|
470
455
|
saved = record.save(validate: !autosave)
|
data/lib/active_record/base.rb
CHANGED
@@ -12,7 +12,7 @@ require "active_record/attributes"
|
|
12
12
|
require "active_record/type_caster"
|
13
13
|
require "active_record/database_configurations"
|
14
14
|
|
15
|
-
module ActiveRecord
|
15
|
+
module ActiveRecord # :nodoc:
|
16
16
|
# = Active Record
|
17
17
|
#
|
18
18
|
# Active Record objects don't specify their attributes directly, but rather infer them from
|
@@ -137,6 +137,23 @@ module ActiveRecord #:nodoc:
|
|
137
137
|
# anonymous = User.new(name: "")
|
138
138
|
# anonymous.name? # => false
|
139
139
|
#
|
140
|
+
# Query methods will also respect any overwrites of default accessors:
|
141
|
+
#
|
142
|
+
# class User
|
143
|
+
# # Has admin boolean column
|
144
|
+
# def admin
|
145
|
+
# false
|
146
|
+
# end
|
147
|
+
# end
|
148
|
+
#
|
149
|
+
# user.update(admin: true)
|
150
|
+
#
|
151
|
+
# user.read_attribute(:admin) # => true, gets the column value
|
152
|
+
# user[:admin] # => true, also gets the column value
|
153
|
+
#
|
154
|
+
# user.admin # => false, due to the getter overwrite
|
155
|
+
# user.admin? # => false, due to the getter overwrite
|
156
|
+
#
|
140
157
|
# == Accessing attributes before they have been typecasted
|
141
158
|
#
|
142
159
|
# Sometimes you want to be able to read the raw attribute data without having the column-determined
|
@@ -310,6 +327,7 @@ module ActiveRecord #:nodoc:
|
|
310
327
|
include SecureToken
|
311
328
|
include SignedId
|
312
329
|
include Suppressor
|
330
|
+
include Encryption::EncryptableRecord
|
313
331
|
end
|
314
332
|
|
315
333
|
ActiveSupport.run_load_hooks(:active_record, Base)
|
@@ -432,7 +432,7 @@ module ActiveRecord
|
|
432
432
|
define_model_callbacks :save, :create, :update, :destroy
|
433
433
|
end
|
434
434
|
|
435
|
-
def destroy
|
435
|
+
def destroy # :nodoc:
|
436
436
|
@_destroy_callback_already_called ||= false
|
437
437
|
return if @_destroy_callback_already_called
|
438
438
|
@_destroy_callback_already_called = true
|
@@ -444,7 +444,7 @@ module ActiveRecord
|
|
444
444
|
@_destroy_callback_already_called = false
|
445
445
|
end
|
446
446
|
|
447
|
-
def touch(*, **)
|
447
|
+
def touch(*, **) # :nodoc:
|
448
448
|
_run_touch_callbacks { super }
|
449
449
|
end
|
450
450
|
|