activerecord 8.0.2.1 → 8.1.0.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +459 -421
- data/README.rdoc +2 -2
- data/lib/active_record/association_relation.rb +1 -1
- data/lib/active_record/associations/association.rb +1 -1
- data/lib/active_record/associations/belongs_to_association.rb +9 -1
- data/lib/active_record/associations/builder/association.rb +16 -5
- data/lib/active_record/associations/builder/belongs_to.rb +17 -4
- data/lib/active_record/associations/builder/collection_association.rb +7 -3
- data/lib/active_record/associations/builder/has_one.rb +1 -1
- data/lib/active_record/associations/builder/singular_association.rb +33 -5
- data/lib/active_record/associations/collection_association.rb +3 -3
- data/lib/active_record/associations/collection_proxy.rb +22 -4
- data/lib/active_record/associations/deprecation.rb +88 -0
- data/lib/active_record/associations/errors.rb +3 -0
- data/lib/active_record/associations/join_dependency.rb +2 -0
- data/lib/active_record/associations/preloader/branch.rb +1 -0
- data/lib/active_record/associations.rb +159 -21
- data/lib/active_record/attribute_methods/query.rb +34 -0
- data/lib/active_record/attribute_methods/serialization.rb +17 -4
- data/lib/active_record/attributes.rb +38 -24
- data/lib/active_record/base.rb +0 -1
- data/lib/active_record/coders/json.rb +14 -5
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +2 -4
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +15 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +51 -12
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +384 -49
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +26 -30
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +19 -1
- data/lib/active_record/connection_adapters/abstract/quoting.rb +15 -24
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +7 -2
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +26 -34
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +89 -23
- data/lib/active_record/connection_adapters/abstract/transaction.rb +16 -3
- data/lib/active_record/connection_adapters/abstract_adapter.rb +67 -13
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +43 -11
- data/lib/active_record/connection_adapters/column.rb +17 -4
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +4 -4
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +42 -5
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +26 -4
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +27 -22
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +18 -16
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +21 -10
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +8 -21
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +65 -30
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +74 -38
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +12 -7
- data/lib/active_record/connection_adapters/schema_cache.rb +2 -2
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +39 -27
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +0 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +4 -13
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +56 -32
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +4 -3
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +1 -1
- data/lib/active_record/connection_adapters.rb +1 -0
- data/lib/active_record/connection_handling.rb +1 -1
- data/lib/active_record/core.rb +12 -9
- data/lib/active_record/counter_cache.rb +33 -8
- data/lib/active_record/database_configurations/database_config.rb +5 -1
- data/lib/active_record/database_configurations/hash_config.rb +56 -9
- data/lib/active_record/database_configurations/url_config.rb +13 -3
- data/lib/active_record/database_configurations.rb +7 -3
- data/lib/active_record/delegated_type.rb +2 -2
- data/lib/active_record/dynamic_matchers.rb +54 -69
- data/lib/active_record/encryption/encryptable_record.rb +5 -5
- data/lib/active_record/encryption/encrypted_attribute_type.rb +2 -2
- data/lib/active_record/encryption/encryptor.rb +27 -25
- data/lib/active_record/encryption/scheme.rb +1 -1
- data/lib/active_record/enum.rb +37 -20
- data/lib/active_record/errors.rb +20 -4
- data/lib/active_record/explain_registry.rb +0 -1
- data/lib/active_record/filter_attribute_handler.rb +73 -0
- data/lib/active_record/fixture_set/table_row.rb +19 -2
- data/lib/active_record/fixtures.rb +2 -2
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +1 -1
- data/lib/active_record/insert_all.rb +12 -7
- data/lib/active_record/locking/optimistic.rb +7 -0
- data/lib/active_record/locking/pessimistic.rb +5 -0
- data/lib/active_record/log_subscriber.rb +1 -5
- data/lib/active_record/middleware/shard_selector.rb +34 -17
- data/lib/active_record/migration/command_recorder.rb +14 -1
- data/lib/active_record/migration/compatibility.rb +34 -24
- data/lib/active_record/migration/default_schema_versions_formatter.rb +30 -0
- data/lib/active_record/migration.rb +31 -21
- data/lib/active_record/model_schema.rb +10 -7
- data/lib/active_record/nested_attributes.rb +2 -0
- data/lib/active_record/persistence.rb +34 -3
- data/lib/active_record/query_cache.rb +22 -15
- data/lib/active_record/query_logs.rb +7 -7
- data/lib/active_record/querying.rb +4 -4
- data/lib/active_record/railtie.rb +34 -5
- data/lib/active_record/railties/databases.rake +23 -19
- data/lib/active_record/railties/job_checkpoints.rb +15 -0
- data/lib/active_record/railties/job_runtime.rb +10 -11
- data/lib/active_record/reflection.rb +42 -3
- data/lib/active_record/relation/batches.rb +26 -12
- data/lib/active_record/relation/calculations.rb +35 -25
- data/lib/active_record/relation/delegation.rb +0 -1
- data/lib/active_record/relation/finder_methods.rb +37 -21
- data/lib/active_record/relation/merger.rb +2 -2
- data/lib/active_record/relation/predicate_builder.rb +2 -2
- data/lib/active_record/relation/query_attribute.rb +3 -1
- data/lib/active_record/relation/query_methods.rb +43 -33
- data/lib/active_record/relation/spawn_methods.rb +6 -6
- data/lib/active_record/relation/where_clause.rb +7 -10
- data/lib/active_record/relation.rb +37 -15
- data/lib/active_record/result.rb +44 -21
- data/lib/active_record/sanitization.rb +2 -0
- data/lib/active_record/schema_dumper.rb +12 -10
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/secure_token.rb +3 -3
- data/lib/active_record/signed_id.rb +46 -18
- data/lib/active_record/statement_cache.rb +13 -9
- data/lib/active_record/store.rb +44 -19
- data/lib/active_record/tasks/abstract_tasks.rb +76 -0
- data/lib/active_record/tasks/database_tasks.rb +24 -35
- data/lib/active_record/tasks/mysql_database_tasks.rb +3 -40
- data/lib/active_record/tasks/postgresql_database_tasks.rb +14 -40
- data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -26
- data/lib/active_record/test_databases.rb +11 -3
- data/lib/active_record/test_fixtures.rb +27 -2
- data/lib/active_record/testing/query_assertions.rb +8 -2
- data/lib/active_record/timestamp.rb +4 -2
- data/lib/active_record/transaction.rb +2 -5
- data/lib/active_record/transactions.rb +34 -10
- data/lib/active_record/type/hash_lookup_type_map.rb +2 -1
- data/lib/active_record/type/internal/timezone.rb +7 -0
- data/lib/active_record/type/json.rb +15 -2
- data/lib/active_record/type/serialized.rb +11 -4
- data/lib/active_record/type/type_map.rb +1 -1
- data/lib/active_record/type_caster/connection.rb +2 -1
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record.rb +68 -5
- data/lib/arel/alias_predication.rb +2 -0
- data/lib/arel/crud.rb +8 -11
- data/lib/arel/delete_manager.rb +5 -0
- data/lib/arel/nodes/count.rb +2 -2
- data/lib/arel/nodes/delete_statement.rb +4 -2
- data/lib/arel/nodes/function.rb +4 -10
- data/lib/arel/nodes/named_function.rb +2 -2
- data/lib/arel/nodes/node.rb +1 -1
- data/lib/arel/nodes/update_statement.rb +4 -2
- data/lib/arel/nodes.rb +0 -2
- data/lib/arel/select_manager.rb +13 -4
- data/lib/arel/update_manager.rb +5 -0
- data/lib/arel/visitors/dot.rb +2 -3
- data/lib/arel/visitors/postgresql.rb +55 -0
- data/lib/arel/visitors/sqlite.rb +55 -8
- data/lib/arel/visitors/to_sql.rb +5 -21
- data/lib/arel.rb +3 -1
- metadata +13 -9
- data/lib/active_record/normalization.rb +0 -163
@@ -39,6 +39,8 @@ module ActiveRecord
|
|
39
39
|
autoload :AssociationScope
|
40
40
|
autoload :DisableJoinsAssociationScope
|
41
41
|
autoload :AliasTracker
|
42
|
+
|
43
|
+
autoload :Deprecation
|
42
44
|
end
|
43
45
|
|
44
46
|
def self.eager_load!
|
@@ -79,7 +81,7 @@ module ActiveRecord
|
|
79
81
|
|
80
82
|
# Returns the specified association instance if it exists, +nil+ otherwise.
|
81
83
|
def association_instance_get(name)
|
82
|
-
@association_cache[name]
|
84
|
+
(@association_cache ||= {})[name]
|
83
85
|
end
|
84
86
|
|
85
87
|
# Set the specified association instance.
|
@@ -87,6 +89,14 @@ module ActiveRecord
|
|
87
89
|
@association_cache[name] = association
|
88
90
|
end
|
89
91
|
|
92
|
+
def deprecated_associations_api_guard(association, method_name)
|
93
|
+
Deprecation.guard(association.reflection) { "the method #{method_name} was invoked" }
|
94
|
+
end
|
95
|
+
|
96
|
+
def report_deprecated_association(reflection, context:)
|
97
|
+
Deprecation.report(reflection, context: context)
|
98
|
+
end
|
99
|
+
|
90
100
|
# = Active Record \Associations
|
91
101
|
#
|
92
102
|
# \Associations are a set of macro-like class methods for tying objects together through
|
@@ -1020,6 +1030,116 @@ module ActiveRecord
|
|
1020
1030
|
# associated records themselves, you can always do something along the lines of
|
1021
1031
|
# <tt>person.tasks.each(&:destroy)</tt>.
|
1022
1032
|
#
|
1033
|
+
# == Deprecated Associations
|
1034
|
+
#
|
1035
|
+
# Associations can be marked as deprecated by passing <tt>deprecated: true</tt>:
|
1036
|
+
#
|
1037
|
+
# has_many :posts, deprecated: true
|
1038
|
+
#
|
1039
|
+
# When a deprecated association is used, a warning is issued using the
|
1040
|
+
# Active Record logger, though more options are available via
|
1041
|
+
# configuration.
|
1042
|
+
#
|
1043
|
+
# The message includes some context that helps understand the deprecated
|
1044
|
+
# usage:
|
1045
|
+
#
|
1046
|
+
# The association Author#posts is deprecated, the method post_ids was invoked (...)
|
1047
|
+
# The association Author#posts is deprecated, referenced in query to preload records (...)
|
1048
|
+
#
|
1049
|
+
# The dots in the examples above would have the application-level spot
|
1050
|
+
# where usage occurred, to help locate what triggered the warning. That
|
1051
|
+
# location is computed using the Active Record backtrace cleaner.
|
1052
|
+
#
|
1053
|
+
# === What is considered to be usage?
|
1054
|
+
#
|
1055
|
+
# * Invocation of any association methods like +posts+, <tt>posts=</tt>,
|
1056
|
+
# etc.
|
1057
|
+
#
|
1058
|
+
# * If the association accepts nested attributes, assignment to those
|
1059
|
+
# attributes.
|
1060
|
+
#
|
1061
|
+
# * If the association is a through association and some of its nested
|
1062
|
+
# associations are deprecated, you'll get warnings for them whenever the
|
1063
|
+
# top-level through is used. This is so regardless of whether the
|
1064
|
+
# through itself is deprecated.
|
1065
|
+
#
|
1066
|
+
# * Execution of queries that refer to the association. Think execution of
|
1067
|
+
# <tt>eager_load(:posts)</tt>, <tt>joins(author: :posts)</tt>, etc.
|
1068
|
+
#
|
1069
|
+
# * If the association has a +:dependent+ option, destroying the
|
1070
|
+
# associated record issues warnings (because that has a side-effect that
|
1071
|
+
# would not happen if the association was removed).
|
1072
|
+
#
|
1073
|
+
# * If the association has a +:touch+ option, saving or destroying the
|
1074
|
+
# record issues a warning (because that has a side-effect that would not
|
1075
|
+
# happen if the association was removed).
|
1076
|
+
#
|
1077
|
+
# === Things that do NOT issue warnings
|
1078
|
+
#
|
1079
|
+
# The rationale behind most of the following edge cases is that Active
|
1080
|
+
# Record accesses associations lazily, when used. Before that, the
|
1081
|
+
# reference to the association is basically just a Ruby symbol.
|
1082
|
+
#
|
1083
|
+
# * If +posts+ is deprecated, <tt>has_many :comments, through: :posts</tt>
|
1084
|
+
# does not warn. Usage of the +comments+ association reports usage of
|
1085
|
+
# +posts+, as we explained above, but the definition of the +has_many+
|
1086
|
+
# itself does not.
|
1087
|
+
#
|
1088
|
+
# * Similarly, <tt>accepts_nested_attributes_for :posts</tt> does not
|
1089
|
+
# warn. Assignment to the posts attributes warns, as explained above,
|
1090
|
+
# but the +accepts_nested_attributes_for+ call itself does not.
|
1091
|
+
#
|
1092
|
+
# * Same if an association declares to be inverse of a deprecated one, the
|
1093
|
+
# macro itself does not warn.
|
1094
|
+
#
|
1095
|
+
# * In the same line, the declaration <tt>validates_associated :posts</tt>
|
1096
|
+
# does not warn by itself, though access is reported when the validation
|
1097
|
+
# runs.
|
1098
|
+
#
|
1099
|
+
# * Relation query methods like <tt>Author.includes(:posts)</tt> do not
|
1100
|
+
# warn by themselves. At that point, that is a relation that internally
|
1101
|
+
# stores a symbol for later use. As explained in the previous section,
|
1102
|
+
# you get a warning when/if the query is executed.
|
1103
|
+
#
|
1104
|
+
# * Access to the reflection object of the association as in
|
1105
|
+
# <tt>Author.reflect_on_association(:posts)</tt> or
|
1106
|
+
# <tt>Author.reflect_on_all_associations</tt> does not warn.
|
1107
|
+
#
|
1108
|
+
# === Configuration
|
1109
|
+
#
|
1110
|
+
# Reporting deprecated usage can be configured:
|
1111
|
+
#
|
1112
|
+
# config.active_record.deprecated_associations_options = { ... }
|
1113
|
+
#
|
1114
|
+
# If present, this has to be a hash with keys +:mode+ and/or +:backtrace+.
|
1115
|
+
#
|
1116
|
+
# ==== Mode
|
1117
|
+
#
|
1118
|
+
# * In +:warn+ mode, usage issues a warning that includes the
|
1119
|
+
# application-level place where the access happened, if any. This is the
|
1120
|
+
# default mode.
|
1121
|
+
#
|
1122
|
+
# * In +:raise+ mode, usage raises an
|
1123
|
+
# ActiveRecord::DeprecatedAssociationError with a similar message and a
|
1124
|
+
# clean backtrace in the exception object.
|
1125
|
+
#
|
1126
|
+
# * In +:notify+ mode, a <tt>deprecated_association.active_record</tt>
|
1127
|
+
# Active Support notification is published. The event payload has the
|
1128
|
+
# association reflection (+:reflection+), the application-level location
|
1129
|
+
# (+:location+) where the access happened (a Thread::Backtrace::Location
|
1130
|
+
# object, or +nil+), and a deprecation message (+:message+).
|
1131
|
+
#
|
1132
|
+
# ==== Backtrace
|
1133
|
+
#
|
1134
|
+
# If +:backtrace+ is true, warnings include a clean backtrace in the message
|
1135
|
+
# and notifications have a +:backtrace+ key in the payload with an array
|
1136
|
+
# of clean Thread::Backtrace::Location objects. Exceptions always get a
|
1137
|
+
# clean stack trace set.
|
1138
|
+
#
|
1139
|
+
# Clean backtraces are computed using the Active Record backtrace cleaner.
|
1140
|
+
# In Rails applications, that is by the default the same as
|
1141
|
+
# <tt>Rails.backtrace_cleaner</tt>.
|
1142
|
+
#
|
1023
1143
|
# == Type safety with ActiveRecord::AssociationTypeMismatch
|
1024
1144
|
#
|
1025
1145
|
# If you attempt to assign an object to an association that doesn't match the inferred
|
@@ -1208,8 +1328,10 @@ module ActiveRecord
|
|
1208
1328
|
# [+:as+]
|
1209
1329
|
# Specifies a polymorphic interface (See #belongs_to).
|
1210
1330
|
# [+:through+]
|
1211
|
-
# Specifies an association through which to perform the query.
|
1212
|
-
#
|
1331
|
+
# Specifies an association through which to perform the query.
|
1332
|
+
#
|
1333
|
+
# This can be any other type of association, including other <tt>:through</tt> associations,
|
1334
|
+
# but it cannot be a polymorphic association. Options for <tt>:class_name</tt>,
|
1213
1335
|
# <tt>:primary_key</tt> and <tt>:foreign_key</tt> are ignored, as the association uses the
|
1214
1336
|
# source reflection.
|
1215
1337
|
#
|
@@ -1285,6 +1407,9 @@ module ActiveRecord
|
|
1285
1407
|
# Defines an {association callback}[rdoc-ref:Associations::ClassMethods@Association+callbacks] that gets triggered <b>before an object is removed</b> from the association collection.
|
1286
1408
|
# [:after_remove]
|
1287
1409
|
# Defines an {association callback}[rdoc-ref:Associations::ClassMethods@Association+callbacks] that gets triggered <b>after an object is removed</b> from the association collection.
|
1410
|
+
# [+:deprecated+]
|
1411
|
+
# If true, marks the association as deprecated. Usage of deprecated associations is reported.
|
1412
|
+
# Please, check the class documentation above for details.
|
1288
1413
|
#
|
1289
1414
|
# Option examples:
|
1290
1415
|
# has_many :comments, -> { order("posted_on") }
|
@@ -1301,7 +1426,7 @@ module ActiveRecord
|
|
1301
1426
|
# has_many :comments, index_errors: :nested_attributes_order
|
1302
1427
|
def has_many(name, scope = nil, **options, &extension)
|
1303
1428
|
reflection = Builder::HasMany.build(self, name, scope, options, &extension)
|
1304
|
-
Reflection.add_reflection
|
1429
|
+
Reflection.add_reflection(self, name, reflection)
|
1305
1430
|
end
|
1306
1431
|
|
1307
1432
|
# Specifies a one-to-one association with another class. This method
|
@@ -1411,10 +1536,12 @@ module ActiveRecord
|
|
1411
1536
|
# [+:as+]
|
1412
1537
|
# Specifies a polymorphic interface (See #belongs_to).
|
1413
1538
|
# [+:through+]
|
1414
|
-
# Specifies
|
1415
|
-
#
|
1416
|
-
#
|
1417
|
-
#
|
1539
|
+
# Specifies an association through which to perform the query.
|
1540
|
+
#
|
1541
|
+
# The through association must be a +has_one+, <tt>has_one :through</tt>, or non-polymorphic +belongs_to+.
|
1542
|
+
# That is, a non-polymorphic singular association. Options for <tt>:class_name</tt>, <tt>:primary_key</tt>,
|
1543
|
+
# and <tt>:foreign_key</tt> are ignored, as the association uses the source reflection. You can only
|
1544
|
+
# use a <tt>:through</tt> query through a #has_one or #belongs_to association on the join model.
|
1418
1545
|
#
|
1419
1546
|
# If the association on the join model is a #belongs_to, the collection can be modified
|
1420
1547
|
# and the records on the <tt>:through</tt> model will be automatically created and removed
|
@@ -1480,12 +1607,15 @@ module ActiveRecord
|
|
1480
1607
|
# Serves as a composite foreign key. Defines the list of columns to be used to query the associated object.
|
1481
1608
|
# This is an optional option. By default Rails will attempt to derive the value automatically.
|
1482
1609
|
# When the value is set the Array size must match associated model's primary key or +query_constraints+ size.
|
1610
|
+
# [+:deprecated+]
|
1611
|
+
# If true, marks the association as deprecated. Usage of deprecated associations is reported.
|
1612
|
+
# Please, check the class documentation above for details.
|
1483
1613
|
#
|
1484
1614
|
# Option examples:
|
1485
1615
|
# has_one :credit_card, dependent: :destroy # destroys the associated credit card
|
1486
1616
|
# has_one :credit_card, dependent: :nullify # updates the associated records foreign
|
1487
1617
|
# # key value to NULL rather than destroying it
|
1488
|
-
# has_one :last_comment, -> { order('posted_on') }, class_name: "Comment"
|
1618
|
+
# has_one :last_comment, -> { order('posted_on desc') }, class_name: "Comment"
|
1489
1619
|
# has_one :project_manager, -> { where(role: 'project_manager') }, class_name: "Person"
|
1490
1620
|
# has_one :attachment, as: :attachable
|
1491
1621
|
# has_one :boss, -> { readonly }
|
@@ -1497,7 +1627,7 @@ module ActiveRecord
|
|
1497
1627
|
# has_one :employment_record_book, query_constraints: [:organization_id, :employee_id]
|
1498
1628
|
def has_one(name, scope = nil, **options)
|
1499
1629
|
reflection = Builder::HasOne.build(self, name, scope, options)
|
1500
|
-
Reflection.add_reflection
|
1630
|
+
Reflection.add_reflection(self, name, reflection)
|
1501
1631
|
end
|
1502
1632
|
|
1503
1633
|
# Specifies a one-to-one association with another class. This method
|
@@ -1576,7 +1706,9 @@ module ActiveRecord
|
|
1576
1706
|
# [+:class_name+]
|
1577
1707
|
# Specify the class name of the association. Use it only if that name can't be inferred
|
1578
1708
|
# from the association name. So <tt>belongs_to :author</tt> will by default be linked to the Author class, but
|
1579
|
-
# if the real class name is Person, you'll have to specify it with this option.
|
1709
|
+
# if the real class name is Person, you'll have to specify it with this option. +:class_name+
|
1710
|
+
# is not supported in polymorphic associations, since in that case the class name of the
|
1711
|
+
# associated record is stored in the type column.
|
1580
1712
|
# [+:foreign_key+]
|
1581
1713
|
# Specify the foreign key used for the association. By default this is guessed to be the name
|
1582
1714
|
# of the association with an "_id" suffix. So a class that defines a <tt>belongs_to :person</tt>
|
@@ -1670,6 +1802,9 @@ module ActiveRecord
|
|
1670
1802
|
# Serves as a composite foreign key. Defines the list of columns to be used to query the associated object.
|
1671
1803
|
# This is an optional option. By default Rails will attempt to derive the value automatically.
|
1672
1804
|
# When the value is set the Array size must match associated model's primary key or +query_constraints+ size.
|
1805
|
+
# [+:deprecated+]
|
1806
|
+
# If true, marks the association as deprecated. Usage of deprecated associations is reported.
|
1807
|
+
# Please, check the class documentation above for details.
|
1673
1808
|
#
|
1674
1809
|
# Option examples:
|
1675
1810
|
# belongs_to :firm, foreign_key: "client_of"
|
@@ -1688,7 +1823,7 @@ module ActiveRecord
|
|
1688
1823
|
# belongs_to :note, query_constraints: [:organization_id, :note_id]
|
1689
1824
|
def belongs_to(name, scope = nil, **options)
|
1690
1825
|
reflection = Builder::BelongsTo.build(self, name, scope, options)
|
1691
|
-
Reflection.add_reflection
|
1826
|
+
Reflection.add_reflection(self, name, reflection)
|
1692
1827
|
end
|
1693
1828
|
|
1694
1829
|
# Specifies a many-to-many relationship with another class. This associates two classes via an
|
@@ -1708,7 +1843,7 @@ module ActiveRecord
|
|
1708
1843
|
# The join table should not have a primary key or a model associated with it. You must manually generate the
|
1709
1844
|
# join table with a migration such as this:
|
1710
1845
|
#
|
1711
|
-
# class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration[8.
|
1846
|
+
# class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration[8.1]
|
1712
1847
|
# def change
|
1713
1848
|
# create_join_table :developers, :projects
|
1714
1849
|
# end
|
@@ -1859,6 +1994,9 @@ module ActiveRecord
|
|
1859
1994
|
# <tt>:autosave</tt> to <tt>true</tt>.
|
1860
1995
|
# [+:strict_loading+]
|
1861
1996
|
# Enforces strict loading every time an associated record is loaded through this association.
|
1997
|
+
# [+:deprecated+]
|
1998
|
+
# If true, marks the association as deprecated. Usage of deprecated associations is reported.
|
1999
|
+
# Please, check the class documentation above for details.
|
1862
2000
|
#
|
1863
2001
|
# Option examples:
|
1864
2002
|
# has_and_belongs_to_many :projects
|
@@ -1870,17 +2008,17 @@ module ActiveRecord
|
|
1870
2008
|
def has_and_belongs_to_many(name, scope = nil, **options, &extension)
|
1871
2009
|
habtm_reflection = ActiveRecord::Reflection::HasAndBelongsToManyReflection.new(name, scope, options, self)
|
1872
2010
|
|
1873
|
-
builder = Builder::HasAndBelongsToMany.new
|
2011
|
+
builder = Builder::HasAndBelongsToMany.new(name, self, options)
|
1874
2012
|
|
1875
2013
|
join_model = builder.through_model
|
1876
2014
|
|
1877
|
-
const_set
|
1878
|
-
private_constant
|
2015
|
+
const_set(join_model.name, join_model)
|
2016
|
+
private_constant(join_model.name)
|
1879
2017
|
|
1880
|
-
middle_reflection = builder.middle_reflection
|
2018
|
+
middle_reflection = builder.middle_reflection(join_model)
|
1881
2019
|
|
1882
|
-
Builder::HasMany.define_callbacks
|
1883
|
-
Reflection.add_reflection
|
2020
|
+
Builder::HasMany.define_callbacks(self, middle_reflection)
|
2021
|
+
Reflection.add_reflection(self, middle_reflection.name, middle_reflection)
|
1884
2022
|
middle_reflection.parent_reflection = habtm_reflection
|
1885
2023
|
|
1886
2024
|
include Module.new {
|
@@ -1897,8 +2035,8 @@ module ActiveRecord
|
|
1897
2035
|
hm_options[:through] = middle_reflection.name
|
1898
2036
|
hm_options[:source] = join_model.right_reflection.name
|
1899
2037
|
|
1900
|
-
[:before_add, :after_add, :before_remove, :after_remove, :autosave, :validate, :join_table, :class_name, :extend, :strict_loading].each do |k|
|
1901
|
-
hm_options[k] = options[k] if options.key?
|
2038
|
+
[:before_add, :after_add, :before_remove, :after_remove, :autosave, :validate, :join_table, :class_name, :extend, :strict_loading, :deprecated].each do |k|
|
2039
|
+
hm_options[k] = options[k] if options.key?(k)
|
1902
2040
|
end
|
1903
2041
|
|
1904
2042
|
has_many name, scope, **hm_options, &extension
|
@@ -3,6 +3,38 @@
|
|
3
3
|
module ActiveRecord
|
4
4
|
module AttributeMethods
|
5
5
|
# = Active Record Attribute Methods \Query
|
6
|
+
#
|
7
|
+
# Adds query methods for attributes that return either +true+ or +false+
|
8
|
+
# depending on the attribute type and value.
|
9
|
+
#
|
10
|
+
# For Boolean attributes this will return +true+ if the value is present
|
11
|
+
# and return +false+ otherwise:
|
12
|
+
#
|
13
|
+
# class Product < ActiveRecord::Base
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# product = Product.new(archived: false)
|
17
|
+
# product.archived? # => false
|
18
|
+
# product.archived = true
|
19
|
+
# product.archived? # => true
|
20
|
+
#
|
21
|
+
# For Numeric attributes this will return +true+ if the value is a non-zero
|
22
|
+
# number and return +false+ otherwise:
|
23
|
+
#
|
24
|
+
# product.inventory_count = 0
|
25
|
+
# product.inventory_count? # => false
|
26
|
+
# product.inventory_count = 1
|
27
|
+
# product.inventory_count? # => true
|
28
|
+
#
|
29
|
+
# For other attributes it will return +true+ if the value is present
|
30
|
+
# and return +false+ otherwise:
|
31
|
+
#
|
32
|
+
# product.name = nil
|
33
|
+
# product.name? # => false
|
34
|
+
# product.name = " "
|
35
|
+
# product.name? # => false
|
36
|
+
# product.name = "Orange"
|
37
|
+
# product.name? # => true
|
6
38
|
module Query
|
7
39
|
extend ActiveSupport::Concern
|
8
40
|
|
@@ -10,6 +42,8 @@ module ActiveRecord
|
|
10
42
|
attribute_method_suffix "?", parameters: false
|
11
43
|
end
|
12
44
|
|
45
|
+
# Returns +true+ or +false+ for the attribute identified by +attr_name+,
|
46
|
+
# depending on the attribute type and value.
|
13
47
|
def query_attribute(attr_name)
|
14
48
|
value = self.public_send(attr_name)
|
15
49
|
|
@@ -51,6 +51,16 @@ module ActiveRecord
|
|
51
51
|
# ActiveRecord::SerializationTypeMismatch error.
|
52
52
|
# * If the column is +NULL+ or starting from a new record, the default value
|
53
53
|
# will set to +type.new+
|
54
|
+
# * +comparable+ - Specify whether the deserialized object is safely comparable
|
55
|
+
# for the purpose of detecting changes. Defaults to +false+
|
56
|
+
# When set to +false+ the old and new values will be compared by their serialized
|
57
|
+
# representation (e.g. JSON or YAML), which can sometimes cause two objects that are
|
58
|
+
# semantically equal to be considered different.
|
59
|
+
# For instance two hashes with the same keys and values but a different order have a
|
60
|
+
# different serialized representation, but are semantically equal once deserialized.
|
61
|
+
# If set to +true+ the comparison will be done on the deserialized object.
|
62
|
+
# This options should only be enabled if the +type+ is known to have
|
63
|
+
# a proper <tt>==</tt> method that deeply compare the objects.
|
54
64
|
# * +yaml+ - Optional. Yaml specific options. The allowed config is:
|
55
65
|
# * +:permitted_classes+ - +Array+ with the permitted classes.
|
56
66
|
# * +:unsafe_load+ - Unsafely load YAML blobs, allow YAML to load any class.
|
@@ -130,7 +140,7 @@ module ActiveRecord
|
|
130
140
|
# silently cast unsupported types to +String+:
|
131
141
|
#
|
132
142
|
# >> JSON.parse(JSON.dump(Struct.new(:foo)))
|
133
|
-
# => "#<Class:0x000000013090b4c0>"
|
143
|
+
# # => "#<Class:0x000000013090b4c0>"
|
134
144
|
#
|
135
145
|
# ==== Examples
|
136
146
|
#
|
@@ -180,7 +190,7 @@ module ActiveRecord
|
|
180
190
|
# serialize :preferences, coder: Rot13JSON
|
181
191
|
# end
|
182
192
|
#
|
183
|
-
def serialize(attr_name, coder: nil, type: Object, yaml: {}, **options)
|
193
|
+
def serialize(attr_name, coder: nil, type: Object, comparable: false, yaml: {}, **options)
|
184
194
|
coder ||= default_column_serializer
|
185
195
|
unless coder
|
186
196
|
raise ArgumentError, <<~MSG.squish
|
@@ -200,7 +210,7 @@ module ActiveRecord
|
|
200
210
|
end
|
201
211
|
|
202
212
|
cast_type = cast_type.subtype if Type::Serialized === cast_type
|
203
|
-
Type::Serialized.new(cast_type, column_serializer)
|
213
|
+
Type::Serialized.new(cast_type, column_serializer, comparable: comparable)
|
204
214
|
end
|
205
215
|
end
|
206
216
|
|
@@ -209,7 +219,10 @@ module ActiveRecord
|
|
209
219
|
# When ::JSON is used, force it to go through the Active Support JSON encoder
|
210
220
|
# to ensure special objects (e.g. Active Record models) are dumped correctly
|
211
221
|
# using the #as_json hook.
|
212
|
-
|
222
|
+
|
223
|
+
if coder == ::JSON || coder == Coders::JSON
|
224
|
+
coder = Coders::JSON.new
|
225
|
+
end
|
213
226
|
|
214
227
|
if coder == ::YAML || coder == Coders::YAMLColumn
|
215
228
|
Coders::YAMLColumn.new(attr_name, type, **(yaml || {}))
|
@@ -7,6 +7,7 @@ module ActiveRecord
|
|
7
7
|
module Attributes
|
8
8
|
extend ActiveSupport::Concern
|
9
9
|
include ActiveModel::AttributeRegistration
|
10
|
+
include ActiveModel::Attributes::Normalization
|
10
11
|
|
11
12
|
# = Active Record \Attributes
|
12
13
|
module ClassMethods
|
@@ -21,28 +22,34 @@ module ActiveRecord
|
|
21
22
|
# your domain objects across much of Active Record, without having to
|
22
23
|
# rely on implementation details or monkey patching.
|
23
24
|
#
|
24
|
-
#
|
25
|
-
# column which this will persist to.
|
25
|
+
# ==== Parameters
|
26
26
|
#
|
27
|
-
# +
|
28
|
-
#
|
29
|
-
#
|
30
|
-
# Otherwise, the type will be ActiveModel::Type::Value.
|
31
|
-
# See the examples below for more information about providing custom type objects.
|
27
|
+
# [+name+]
|
28
|
+
# The name of the methods to define attribute methods for, and the
|
29
|
+
# column which this will persist to.
|
32
30
|
#
|
33
|
-
#
|
31
|
+
# [+cast_type+]
|
32
|
+
# A symbol such as +:string+ or +:integer+, or a type object to be used
|
33
|
+
# for this attribute. If this parameter is not passed, the previously
|
34
|
+
# defined type (if any) will be used. Otherwise, the type will be
|
35
|
+
# ActiveModel::Type::Value. See the examples below for more information
|
36
|
+
# about providing custom type objects.
|
34
37
|
#
|
35
|
-
#
|
38
|
+
# ==== Options
|
36
39
|
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
+
# [+:default+]
|
41
|
+
# The default value to use when no value is provided. If this option is
|
42
|
+
# not passed, the previously defined default value (if any) on the
|
43
|
+
# superclass or in the schema will be used. Otherwise, the default will
|
44
|
+
# be +nil+.
|
40
45
|
#
|
41
|
-
#
|
42
|
-
#
|
46
|
+
# [+:array+]
|
47
|
+
# (PostgreSQL only) Specifies that the type should be an array. See the
|
48
|
+
# examples below.
|
43
49
|
#
|
44
|
-
#
|
45
|
-
#
|
50
|
+
# [+:range+]
|
51
|
+
# (PostgreSQL only) Specifies that the type should be a range. See the
|
52
|
+
# examples below.
|
46
53
|
#
|
47
54
|
# When using a symbol for +cast_type+, extra options are forwarded to the
|
48
55
|
# constructor of the type object.
|
@@ -217,17 +224,22 @@ module ActiveRecord
|
|
217
224
|
# is provided so it can be used by plugin authors, application code
|
218
225
|
# should probably use ClassMethods#attribute.
|
219
226
|
#
|
220
|
-
#
|
227
|
+
# ==== Parameters
|
228
|
+
#
|
229
|
+
# [+name+]
|
230
|
+
# The name of the attribute being defined. Expected to be a +String+.
|
221
231
|
#
|
222
|
-
# +cast_type+
|
232
|
+
# [+cast_type+]
|
233
|
+
# The type object to use for this attribute.
|
223
234
|
#
|
224
|
-
# +default+
|
225
|
-
#
|
226
|
-
#
|
227
|
-
# will be
|
235
|
+
# [+default+]
|
236
|
+
# The default value to use when no value is provided. If this option
|
237
|
+
# is not passed, the previous default value (if any) will be used.
|
238
|
+
# Otherwise, the default will be +nil+. A proc can also be passed, and
|
239
|
+
# will be called once each time a new value is needed.
|
228
240
|
#
|
229
|
-
# +user_provided_default+
|
230
|
-
# +cast+ or +deserialize+.
|
241
|
+
# [+user_provided_default+]
|
242
|
+
# Whether the default value should be cast using +cast+ or +deserialize+.
|
231
243
|
def define_attribute(
|
232
244
|
name,
|
233
245
|
cast_type,
|
@@ -240,6 +252,7 @@ module ActiveRecord
|
|
240
252
|
|
241
253
|
def _default_attributes # :nodoc:
|
242
254
|
@default_attributes ||= begin
|
255
|
+
# TODO: Remove the need for a connection after we release 8.1.
|
243
256
|
attributes_hash = with_connection do |connection|
|
244
257
|
columns_hash.transform_values do |column|
|
245
258
|
ActiveModel::Attribute.from_database(column.name, column.default, type_for_column(connection, column))
|
@@ -299,6 +312,7 @@ module ActiveRecord
|
|
299
312
|
end
|
300
313
|
|
301
314
|
def type_for_column(connection, column)
|
315
|
+
# TODO: Remove the need for a connection after we release 8.1.
|
302
316
|
hook_attribute_type(column.name, super)
|
303
317
|
end
|
304
318
|
end
|
data/lib/active_record/base.rb
CHANGED
@@ -1,14 +1,23 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/json"
|
4
|
+
|
3
5
|
module ActiveRecord
|
4
6
|
module Coders # :nodoc:
|
5
|
-
|
6
|
-
|
7
|
-
|
7
|
+
class JSON # :nodoc:
|
8
|
+
DEFAULT_OPTIONS = { escape: false }.freeze
|
9
|
+
|
10
|
+
def initialize(options = nil)
|
11
|
+
@options = options ? DEFAULT_OPTIONS.merge(options) : DEFAULT_OPTIONS
|
12
|
+
@encoder = ActiveSupport::JSON::Encoding.json_encoder.new(options)
|
13
|
+
end
|
14
|
+
|
15
|
+
def dump(obj)
|
16
|
+
@encoder.encode(obj)
|
8
17
|
end
|
9
18
|
|
10
|
-
def
|
11
|
-
ActiveSupport::JSON.decode(json) unless json.blank?
|
19
|
+
def load(json)
|
20
|
+
ActiveSupport::JSON.decode(json, @options) unless json.blank?
|
12
21
|
end
|
13
22
|
end
|
14
23
|
end
|
@@ -158,9 +158,7 @@ module ActiveRecord
|
|
158
158
|
each_connection_pool(role).any?(&:active_connection?)
|
159
159
|
end
|
160
160
|
|
161
|
-
# Returns any connections in use by the current thread back to the pool
|
162
|
-
# and also returns connections to the pool cached by threads that are no
|
163
|
-
# longer alive.
|
161
|
+
# Returns any connections in use by the current thread back to the pool.
|
164
162
|
def clear_active_connections!(role = nil)
|
165
163
|
each_connection_pool(role).each do |pool|
|
166
164
|
pool.release_connection
|
@@ -168,7 +166,7 @@ module ActiveRecord
|
|
168
166
|
end
|
169
167
|
end
|
170
168
|
|
171
|
-
# Clears
|
169
|
+
# Clears reloadable connection caches in all connection pools.
|
172
170
|
#
|
173
171
|
# See ConnectionPool#clear_reloadable_connections! for details.
|
174
172
|
def clear_reloadable_connections!(role = nil)
|
@@ -40,6 +40,14 @@ module ActiveRecord
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
+
# Add +element+ to the back of the queue. Never blocks.
|
44
|
+
def add_back(element)
|
45
|
+
synchronize do
|
46
|
+
@queue.unshift element
|
47
|
+
@cond.signal
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
43
51
|
# If +element+ is in the queue, remove and return it, or +nil+.
|
44
52
|
def delete(element)
|
45
53
|
synchronize do
|
@@ -54,6 +62,13 @@ module ActiveRecord
|
|
54
62
|
end
|
55
63
|
end
|
56
64
|
|
65
|
+
# Number of elements in the queue.
|
66
|
+
def size
|
67
|
+
synchronize do
|
68
|
+
@queue.size
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
57
72
|
# Remove the head of the queue.
|
58
73
|
#
|
59
74
|
# If +timeout+ is not given, remove and return the head of the
|