activerecord 7.1.5.2 → 8.1.2.1
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 +567 -2443
- data/README.rdoc +16 -16
- data/examples/performance.rb +2 -2
- data/lib/active_record/association_relation.rb +3 -2
- data/lib/active_record/associations/alias_tracker.rb +31 -23
- data/lib/active_record/associations/association.rb +43 -12
- data/lib/active_record/associations/belongs_to_association.rb +31 -8
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
- data/lib/active_record/associations/builder/association.rb +23 -11
- data/lib/active_record/associations/builder/belongs_to.rb +18 -4
- data/lib/active_record/associations/builder/collection_association.rb +7 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +2 -2
- data/lib/active_record/associations/builder/has_many.rb +3 -4
- data/lib/active_record/associations/builder/has_one.rb +3 -4
- data/lib/active_record/associations/builder/singular_association.rb +33 -5
- data/lib/active_record/associations/collection_association.rb +17 -9
- data/lib/active_record/associations/collection_proxy.rb +36 -5
- data/lib/active_record/associations/deprecation.rb +88 -0
- data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
- data/lib/active_record/associations/errors.rb +268 -0
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +10 -3
- data/lib/active_record/associations/join_dependency/join_association.rb +1 -1
- data/lib/active_record/associations/join_dependency.rb +4 -2
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +4 -3
- data/lib/active_record/associations/preloader/batch.rb +7 -1
- data/lib/active_record/associations/preloader/branch.rb +8 -1
- data/lib/active_record/associations/preloader/through_association.rb +1 -3
- data/lib/active_record/associations/singular_association.rb +14 -3
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +250 -315
- data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
- data/lib/active_record/attribute_assignment.rb +0 -2
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/primary_key.rb +25 -61
- data/lib/active_record/attribute_methods/query.rb +34 -0
- data/lib/active_record/attribute_methods/read.rb +1 -13
- data/lib/active_record/attribute_methods/serialization.rb +20 -27
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +19 -20
- data/lib/active_record/attribute_methods.rb +71 -75
- data/lib/active_record/attributes.rb +96 -68
- data/lib/active_record/autosave_association.rb +93 -58
- data/lib/active_record/base.rb +5 -7
- data/lib/active_record/callbacks.rb +1 -1
- data/lib/active_record/coders/json.rb +14 -5
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +50 -126
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +16 -4
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +52 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +681 -135
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +165 -86
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +226 -78
- data/lib/active_record/connection_adapters/abstract/quoting.rb +79 -114
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +11 -7
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +37 -36
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +136 -34
- data/lib/active_record/connection_adapters/abstract/transaction.rb +163 -68
- data/lib/active_record/connection_adapters/abstract_adapter.rb +197 -129
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +112 -63
- data/lib/active_record/connection_adapters/column.rb +17 -4
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +11 -3
- data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -57
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +41 -10
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +79 -46
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +97 -101
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +14 -33
- data/lib/active_record/connection_adapters/pool_config.rb +14 -13
- data/lib/active_record/connection_adapters/postgresql/column.rb +4 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +98 -44
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +79 -68
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +9 -17
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +44 -41
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +69 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +155 -75
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +104 -121
- data/lib/active_record/connection_adapters/schema_cache.rb +126 -133
- data/lib/active_record/connection_adapters/sqlite3/column.rb +14 -1
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +91 -95
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +57 -54
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +13 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +43 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +38 -15
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +231 -111
- data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +40 -69
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +19 -65
- data/lib/active_record/connection_adapters.rb +66 -0
- data/lib/active_record/connection_handling.rb +88 -46
- data/lib/active_record/core.rb +142 -58
- data/lib/active_record/counter_cache.rb +52 -18
- data/lib/active_record/database_configurations/connection_url_resolver.rb +9 -2
- data/lib/active_record/database_configurations/database_config.rb +28 -5
- data/lib/active_record/database_configurations/hash_config.rb +103 -41
- data/lib/active_record/database_configurations/url_config.rb +30 -1
- data/lib/active_record/database_configurations.rb +8 -4
- data/lib/active_record/delegated_type.rb +43 -19
- data/lib/active_record/dynamic_matchers.rb +56 -71
- data/lib/active_record/encryption/config.rb +3 -1
- data/lib/active_record/encryption/encryptable_record.rb +12 -12
- data/lib/active_record/encryption/encrypted_attribute_type.rb +35 -6
- data/lib/active_record/encryption/encryptor.rb +58 -22
- data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
- data/lib/active_record/encryption/key_provider.rb +1 -1
- data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +4 -0
- data/lib/active_record/encryption/null_encryptor.rb +4 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
- data/lib/active_record/encryption/scheme.rb +9 -2
- data/lib/active_record/enum.rb +57 -36
- data/lib/active_record/errors.rb +76 -26
- data/lib/active_record/explain.rb +14 -25
- data/lib/active_record/explain_registry.rb +51 -2
- 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 +39 -35
- data/lib/active_record/future_result.rb +21 -13
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +5 -3
- data/lib/active_record/insert_all.rb +28 -20
- data/lib/active_record/integration.rb +4 -1
- data/lib/active_record/internal_metadata.rb +48 -34
- data/lib/active_record/locking/optimistic.rb +15 -7
- data/lib/active_record/locking/pessimistic.rb +5 -0
- data/lib/active_record/log_subscriber.rb +3 -34
- data/lib/active_record/message_pack.rb +1 -1
- data/lib/active_record/middleware/shard_selector.rb +34 -17
- data/lib/active_record/migration/command_recorder.rb +46 -14
- data/lib/active_record/migration/compatibility.rb +40 -25
- data/lib/active_record/migration/default_schema_versions_formatter.rb +30 -0
- data/lib/active_record/migration/default_strategy.rb +4 -5
- data/lib/active_record/migration/pending_migration_connection.rb +2 -2
- data/lib/active_record/migration.rb +119 -103
- data/lib/active_record/model_schema.rb +66 -78
- data/lib/active_record/nested_attributes.rb +17 -9
- data/lib/active_record/persistence.rb +161 -454
- data/lib/active_record/query_cache.rb +33 -15
- data/lib/active_record/query_logs.rb +106 -39
- data/lib/active_record/query_logs_formatter.rb +17 -28
- data/lib/active_record/querying.rb +28 -16
- data/lib/active_record/railtie.rb +61 -74
- data/lib/active_record/railties/controller_runtime.rb +19 -5
- data/lib/active_record/railties/databases.rake +64 -78
- 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 +147 -53
- data/lib/active_record/relation/batches/batch_enumerator.rb +19 -5
- data/lib/active_record/relation/batches.rb +153 -73
- data/lib/active_record/relation/calculations.rb +146 -96
- data/lib/active_record/relation/delegation.rb +30 -23
- data/lib/active_record/relation/finder_methods.rb +64 -34
- data/lib/active_record/relation/merger.rb +12 -14
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +19 -11
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +8 -8
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
- data/lib/active_record/relation/predicate_builder.rb +25 -10
- data/lib/active_record/relation/query_attribute.rb +4 -2
- data/lib/active_record/relation/query_methods.rb +351 -124
- data/lib/active_record/relation/spawn_methods.rb +9 -25
- data/lib/active_record/relation/where_clause.rb +17 -30
- data/lib/active_record/relation.rb +590 -124
- data/lib/active_record/result.rb +131 -59
- data/lib/active_record/runtime_registry.rb +44 -21
- data/lib/active_record/sanitization.rb +33 -25
- data/lib/active_record/schema.rb +8 -6
- data/lib/active_record/schema_dumper.rb +66 -31
- data/lib/active_record/schema_migration.rb +31 -14
- data/lib/active_record/scoping/named.rb +6 -2
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/secure_token.rb +3 -3
- data/lib/active_record/signed_id.rb +68 -20
- data/lib/active_record/statement_cache.rb +29 -25
- data/lib/active_record/store.rb +51 -22
- data/lib/active_record/structured_event_subscriber.rb +85 -0
- data/lib/active_record/table_metadata.rb +7 -33
- data/lib/active_record/tasks/abstract_tasks.rb +76 -0
- data/lib/active_record/tasks/database_tasks.rb +118 -90
- data/lib/active_record/tasks/mysql_database_tasks.rb +3 -42
- data/lib/active_record/tasks/postgresql_database_tasks.rb +14 -40
- data/lib/active_record/tasks/sqlite_database_tasks.rb +17 -28
- data/lib/active_record/test_databases.rb +14 -4
- data/lib/active_record/test_fixtures.rb +123 -89
- data/lib/active_record/testing/query_assertions.rb +127 -0
- data/lib/active_record/timestamp.rb +6 -4
- data/lib/active_record/token_for.rb +22 -12
- data/lib/active_record/touch_later.rb +1 -1
- data/lib/active_record/transaction.rb +129 -0
- data/lib/active_record/transactions.rb +97 -18
- data/lib/active_record/translation.rb +0 -2
- 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 +12 -7
- data/lib/active_record/type/type_map.rb +1 -1
- data/lib/active_record/type_caster/connection.rb +5 -4
- data/lib/active_record/validations/associated.rb +10 -4
- data/lib/active_record/validations/uniqueness.rb +23 -18
- data/lib/active_record/validations.rb +4 -1
- data/lib/active_record.rb +203 -59
- data/lib/arel/alias_predication.rb +3 -1
- data/lib/arel/collectors/bind.rb +4 -2
- data/lib/arel/collectors/composite.rb +7 -0
- data/lib/arel/collectors/sql_string.rb +2 -2
- data/lib/arel/collectors/substitute_binds.rb +3 -3
- data/lib/arel/crud.rb +8 -11
- data/lib/arel/delete_manager.rb +5 -0
- data/lib/arel/nodes/binary.rb +1 -7
- data/lib/arel/nodes/bound_sql_literal.rb +9 -5
- 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/{and.rb → nary.rb} +5 -2
- data/lib/arel/nodes/node.rb +6 -5
- data/lib/arel/nodes/sql_literal.rb +8 -1
- data/lib/arel/nodes/update_statement.rb +4 -2
- data/lib/arel/nodes.rb +2 -4
- data/lib/arel/predications.rb +1 -1
- data/lib/arel/select_manager.rb +14 -5
- data/lib/arel/table.rb +3 -7
- data/lib/arel/tree_manager.rb +3 -2
- data/lib/arel/update_manager.rb +7 -1
- data/lib/arel/visitors/dot.rb +3 -3
- data/lib/arel/visitors/mysql.rb +9 -4
- data/lib/arel/visitors/postgresql.rb +56 -12
- data/lib/arel/visitors/sqlite.rb +80 -8
- data/lib/arel/visitors/to_sql.rb +34 -37
- data/lib/arel.rb +10 -4
- data/lib/rails/generators/active_record/application_record/USAGE +1 -1
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
- metadata +23 -14
- data/lib/active_record/explain_subscriber.rb +0 -34
- data/lib/active_record/normalization.rb +0 -167
- data/lib/active_record/relation/record_fetch_warning.rb +0 -49
|
@@ -48,7 +48,7 @@ module ActiveRecord
|
|
|
48
48
|
# way of creating a namespace for tables in a shared database. By default, the prefix is the
|
|
49
49
|
# empty string.
|
|
50
50
|
#
|
|
51
|
-
# If you are
|
|
51
|
+
# If you are organizing your models within modules you can add a prefix to the models within
|
|
52
52
|
# a namespace by defining a singleton method in the parent module called table_name_prefix which
|
|
53
53
|
# returns your chosen prefix.
|
|
54
54
|
|
|
@@ -65,7 +65,7 @@ module ActiveRecord
|
|
|
65
65
|
# Works like +table_name_prefix=+, but appends instead of prepends (set to "_basecamp" gives "projects_basecamp",
|
|
66
66
|
# "people_basecamp"). By default, the suffix is the empty string.
|
|
67
67
|
#
|
|
68
|
-
# If you are
|
|
68
|
+
# If you are organizing your models within modules, you can add a suffix to the models within
|
|
69
69
|
# a namespace by defining a singleton method in the parent module called table_name_suffix which
|
|
70
70
|
# returns your chosen suffix.
|
|
71
71
|
|
|
@@ -113,17 +113,19 @@ module ActiveRecord
|
|
|
113
113
|
# :singleton-method: implicit_order_column
|
|
114
114
|
# :call-seq: implicit_order_column
|
|
115
115
|
#
|
|
116
|
-
# The name of the column records are ordered by if no explicit order clause
|
|
116
|
+
# The name of the column(s) records are ordered by if no explicit order clause
|
|
117
117
|
# is used during an ordered finder call. If not set the primary key is used.
|
|
118
118
|
|
|
119
119
|
##
|
|
120
120
|
# :singleton-method: implicit_order_column=
|
|
121
121
|
# :call-seq: implicit_order_column=(column_name)
|
|
122
122
|
#
|
|
123
|
-
# Sets the column to sort records by when no explicit order clause is used
|
|
124
|
-
# during an ordered finder call. Useful
|
|
125
|
-
# auto-incrementing integer
|
|
126
|
-
#
|
|
123
|
+
# Sets the column(s) to sort records by when no explicit order clause is used
|
|
124
|
+
# during an ordered finder call. Useful for models where the primary key isn't an
|
|
125
|
+
# auto-incrementing integer (such as UUID).
|
|
126
|
+
#
|
|
127
|
+
# By default, records are subsorted by primary key to ensure deterministic results.
|
|
128
|
+
# To disable this subsort behavior, set `implicit_order_column` to `["column_name", nil]`.
|
|
127
129
|
|
|
128
130
|
##
|
|
129
131
|
# :singleton-method: immutable_strings_by_default=
|
|
@@ -146,6 +148,11 @@ module ActiveRecord
|
|
|
146
148
|
# your own model for something else, you can set +inheritance_column+:
|
|
147
149
|
#
|
|
148
150
|
# self.inheritance_column = 'zoink'
|
|
151
|
+
#
|
|
152
|
+
# If you wish to disable single-table inheritance altogether you can set
|
|
153
|
+
# +inheritance_column+ to +nil+
|
|
154
|
+
#
|
|
155
|
+
# self.inheritance_column = nil
|
|
149
156
|
|
|
150
157
|
##
|
|
151
158
|
# :singleton-method: inheritance_column=
|
|
@@ -174,6 +181,7 @@ module ActiveRecord
|
|
|
174
181
|
self.protected_environments = ["production"]
|
|
175
182
|
|
|
176
183
|
self.ignored_columns = [].freeze
|
|
184
|
+
self.only_columns = [].freeze
|
|
177
185
|
|
|
178
186
|
delegate :type_for_attribute, :column_for_attribute, to: :class
|
|
179
187
|
|
|
@@ -271,15 +279,14 @@ module ActiveRecord
|
|
|
271
279
|
end
|
|
272
280
|
|
|
273
281
|
@table_name = value
|
|
274
|
-
@quoted_table_name = nil
|
|
275
282
|
@arel_table = nil
|
|
276
|
-
@sequence_name = nil unless
|
|
283
|
+
@sequence_name = nil unless @explicit_sequence_name
|
|
277
284
|
@predicate_builder = nil
|
|
278
285
|
end
|
|
279
286
|
|
|
280
|
-
# Returns a quoted version of the table name
|
|
287
|
+
# Returns a quoted version of the table name.
|
|
281
288
|
def quoted_table_name
|
|
282
|
-
|
|
289
|
+
adapter_class.quote_table_name(table_name)
|
|
283
290
|
end
|
|
284
291
|
|
|
285
292
|
# Computes the table name, (re)sets it internally, and returns it.
|
|
@@ -328,6 +335,12 @@ module ActiveRecord
|
|
|
328
335
|
@ignored_columns || superclass.ignored_columns
|
|
329
336
|
end
|
|
330
337
|
|
|
338
|
+
# The list of columns names the model should allow. Only columns are used to define
|
|
339
|
+
# attribute accessors, and are referenced in SQL queries.
|
|
340
|
+
def only_columns
|
|
341
|
+
@only_columns || superclass.only_columns
|
|
342
|
+
end
|
|
343
|
+
|
|
331
344
|
# Sets the columns names the model should ignore. Ignored columns won't have attribute
|
|
332
345
|
# accessors defined, and won't be referenced in SQL queries.
|
|
333
346
|
#
|
|
@@ -360,10 +373,17 @@ module ActiveRecord
|
|
|
360
373
|
# user = Project.create!(name: "First Project")
|
|
361
374
|
# user.category # => raises NoMethodError
|
|
362
375
|
def ignored_columns=(columns)
|
|
376
|
+
check_model_columns(@only_columns.present?)
|
|
363
377
|
reload_schema_from_cache
|
|
364
378
|
@ignored_columns = columns.map(&:to_s).freeze
|
|
365
379
|
end
|
|
366
380
|
|
|
381
|
+
def only_columns=(columns)
|
|
382
|
+
check_model_columns(@ignored_columns.present?)
|
|
383
|
+
reload_schema_from_cache
|
|
384
|
+
@only_columns = columns.map(&:to_s).freeze
|
|
385
|
+
end
|
|
386
|
+
|
|
367
387
|
def sequence_name
|
|
368
388
|
if base_class?
|
|
369
389
|
@sequence_name ||= reset_sequence_name
|
|
@@ -374,7 +394,7 @@ module ActiveRecord
|
|
|
374
394
|
|
|
375
395
|
def reset_sequence_name # :nodoc:
|
|
376
396
|
@explicit_sequence_name = false
|
|
377
|
-
@sequence_name =
|
|
397
|
+
@sequence_name = with_connection { |c| c.default_sequence_name(table_name, primary_key) }
|
|
378
398
|
end
|
|
379
399
|
|
|
380
400
|
# Sets the name of the sequence to use when generating ids to the given
|
|
@@ -399,39 +419,37 @@ module ActiveRecord
|
|
|
399
419
|
# Determines if the primary key values should be selected from their
|
|
400
420
|
# corresponding sequence before the insert statement.
|
|
401
421
|
def prefetch_primary_key?
|
|
402
|
-
|
|
422
|
+
with_connection { |c| c.prefetch_primary_key?(table_name) }
|
|
403
423
|
end
|
|
404
424
|
|
|
405
425
|
# Returns the next value that will be used as the primary key on
|
|
406
426
|
# an insert statement.
|
|
407
427
|
def next_sequence_value
|
|
408
|
-
|
|
428
|
+
with_connection { |c| c.next_sequence_value(sequence_name) }
|
|
409
429
|
end
|
|
410
430
|
|
|
411
431
|
# Indicates whether the table associated with this class exists
|
|
412
432
|
def table_exists?
|
|
413
|
-
|
|
433
|
+
schema_cache.data_source_exists?(table_name)
|
|
414
434
|
end
|
|
415
435
|
|
|
416
436
|
def attributes_builder # :nodoc:
|
|
417
|
-
|
|
437
|
+
@attributes_builder ||= begin
|
|
418
438
|
defaults = _default_attributes.except(*(column_names - [primary_key]))
|
|
419
|
-
|
|
439
|
+
ActiveModel::AttributeSet::Builder.new(attribute_types, defaults)
|
|
420
440
|
end
|
|
421
|
-
@attributes_builder
|
|
422
441
|
end
|
|
423
442
|
|
|
424
443
|
def columns_hash # :nodoc:
|
|
425
|
-
load_schema
|
|
444
|
+
load_schema unless @columns_hash
|
|
426
445
|
@columns_hash
|
|
427
446
|
end
|
|
428
447
|
|
|
429
448
|
def columns
|
|
430
|
-
load_schema
|
|
431
449
|
@columns ||= columns_hash.values.freeze
|
|
432
450
|
end
|
|
433
451
|
|
|
434
|
-
def _returning_columns_for_insert # :nodoc:
|
|
452
|
+
def _returning_columns_for_insert(connection) # :nodoc:
|
|
435
453
|
@_returning_columns_for_insert ||= begin
|
|
436
454
|
auto_populated_columns = columns.filter_map do |c|
|
|
437
455
|
c.name if connection.return_value_after_insert?(c)
|
|
@@ -441,37 +459,10 @@ module ActiveRecord
|
|
|
441
459
|
end
|
|
442
460
|
end
|
|
443
461
|
|
|
444
|
-
def attribute_types # :nodoc:
|
|
445
|
-
load_schema
|
|
446
|
-
@attribute_types ||= Hash.new(Type.default_value)
|
|
447
|
-
end
|
|
448
|
-
|
|
449
462
|
def yaml_encoder # :nodoc:
|
|
450
463
|
@yaml_encoder ||= ActiveModel::AttributeSet::YAMLEncoder.new(attribute_types)
|
|
451
464
|
end
|
|
452
465
|
|
|
453
|
-
# Returns the type of the attribute with the given name, after applying
|
|
454
|
-
# all modifiers. This method is the only valid source of information for
|
|
455
|
-
# anything related to the types of a model's attributes. This method will
|
|
456
|
-
# access the database and load the model's schema if it is required.
|
|
457
|
-
#
|
|
458
|
-
# The return value of this method will implement the interface described
|
|
459
|
-
# by ActiveModel::Type::Value (though the object itself may not subclass
|
|
460
|
-
# it).
|
|
461
|
-
#
|
|
462
|
-
# +attr_name+ The name of the attribute to retrieve the type for. Must be
|
|
463
|
-
# a string or a symbol.
|
|
464
|
-
def type_for_attribute(attr_name, &block)
|
|
465
|
-
attr_name = attr_name.to_s
|
|
466
|
-
attr_name = attribute_aliases[attr_name] || attr_name
|
|
467
|
-
|
|
468
|
-
if block
|
|
469
|
-
attribute_types.fetch(attr_name, &block)
|
|
470
|
-
else
|
|
471
|
-
attribute_types[attr_name]
|
|
472
|
-
end
|
|
473
|
-
end
|
|
474
|
-
|
|
475
466
|
# Returns the column object for the named attribute.
|
|
476
467
|
# Returns an ActiveRecord::ConnectionAdapters::NullColumn if the
|
|
477
468
|
# named attribute does not exist.
|
|
@@ -499,11 +490,6 @@ module ActiveRecord
|
|
|
499
490
|
@column_defaults ||= _default_attributes.deep_dup.to_hash.freeze
|
|
500
491
|
end
|
|
501
492
|
|
|
502
|
-
def _default_attributes # :nodoc:
|
|
503
|
-
load_schema
|
|
504
|
-
@default_attributes ||= ActiveModel::AttributeSet.new({})
|
|
505
|
-
end
|
|
506
|
-
|
|
507
493
|
# Returns an array of column names as strings.
|
|
508
494
|
def column_names
|
|
509
495
|
@column_names ||= columns.map(&:name).freeze
|
|
@@ -531,7 +517,7 @@ module ActiveRecord
|
|
|
531
517
|
# when just after creating a table you want to populate it with some default
|
|
532
518
|
# values, e.g.:
|
|
533
519
|
#
|
|
534
|
-
# class CreateJobLevels < ActiveRecord::Migration[
|
|
520
|
+
# class CreateJobLevels < ActiveRecord::Migration[8.1]
|
|
535
521
|
# def up
|
|
536
522
|
# create_table :job_levels do |t|
|
|
537
523
|
# t.integer :id
|
|
@@ -551,18 +537,20 @@ module ActiveRecord
|
|
|
551
537
|
# end
|
|
552
538
|
# end
|
|
553
539
|
def reset_column_information
|
|
554
|
-
|
|
540
|
+
connection_pool.active_connection&.clear_cache!
|
|
555
541
|
([self] + descendants).each(&:undefine_attribute_methods)
|
|
556
|
-
|
|
542
|
+
schema_cache.clear_data_source_cache!(table_name)
|
|
557
543
|
|
|
558
544
|
reload_schema_from_cache
|
|
559
545
|
initialize_find_by_cache
|
|
560
546
|
end
|
|
561
547
|
|
|
562
|
-
|
|
548
|
+
# Load the model's schema information either from the schema cache
|
|
549
|
+
# or directly from the database.
|
|
550
|
+
def load_schema
|
|
563
551
|
return if schema_loaded?
|
|
564
552
|
@load_schema_monitor.synchronize do
|
|
565
|
-
return if
|
|
553
|
+
return if schema_loaded?
|
|
566
554
|
|
|
567
555
|
load_schema!
|
|
568
556
|
|
|
@@ -583,9 +571,7 @@ module ActiveRecord
|
|
|
583
571
|
@arel_table = nil
|
|
584
572
|
@column_names = nil
|
|
585
573
|
@symbol_column_to_string_name_hash = nil
|
|
586
|
-
@attribute_types = nil
|
|
587
574
|
@content_columns = nil
|
|
588
|
-
@default_attributes = nil
|
|
589
575
|
@column_defaults = nil
|
|
590
576
|
@attributes_builder = nil
|
|
591
577
|
@columns = nil
|
|
@@ -607,11 +593,12 @@ module ActiveRecord
|
|
|
607
593
|
child_class.reload_schema_from_cache(false)
|
|
608
594
|
child_class.class_eval do
|
|
609
595
|
@ignored_columns = nil
|
|
596
|
+
@only_columns = nil
|
|
610
597
|
end
|
|
611
598
|
end
|
|
612
599
|
|
|
613
600
|
def schema_loaded?
|
|
614
|
-
|
|
601
|
+
@schema_loaded
|
|
615
602
|
end
|
|
616
603
|
|
|
617
604
|
def load_schema!
|
|
@@ -619,20 +606,14 @@ module ActiveRecord
|
|
|
619
606
|
raise ActiveRecord::TableNotSpecified, "#{self} has no table configured. Set one with #{self}.table_name="
|
|
620
607
|
end
|
|
621
608
|
|
|
622
|
-
columns_hash =
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
type = _convert_type_from_options(type)
|
|
628
|
-
define_attribute(
|
|
629
|
-
name,
|
|
630
|
-
type,
|
|
631
|
-
default: column.default,
|
|
632
|
-
user_provided_default: false
|
|
633
|
-
)
|
|
634
|
-
alias_attribute :id_value, :id if name == "id"
|
|
609
|
+
columns_hash = schema_cache.columns_hash(table_name)
|
|
610
|
+
if only_columns.present?
|
|
611
|
+
columns_hash = columns_hash.slice(*only_columns)
|
|
612
|
+
elsif ignored_columns.present?
|
|
613
|
+
columns_hash = columns_hash.except(*ignored_columns)
|
|
635
614
|
end
|
|
615
|
+
@columns_hash = columns_hash.freeze
|
|
616
|
+
|
|
636
617
|
_default_attributes # Precompute to cache DB-dependent attribute types
|
|
637
618
|
end
|
|
638
619
|
|
|
@@ -659,12 +640,19 @@ module ActiveRecord
|
|
|
659
640
|
end
|
|
660
641
|
end
|
|
661
642
|
|
|
662
|
-
def
|
|
643
|
+
def type_for_column(connection, column)
|
|
644
|
+
# TODO: Remove the need for a connection after we release 8.1.
|
|
645
|
+
type = column.fetch_cast_type(connection)
|
|
646
|
+
|
|
663
647
|
if immutable_strings_by_default && type.respond_to?(:to_immutable_string)
|
|
664
|
-
type.to_immutable_string
|
|
665
|
-
else
|
|
666
|
-
type
|
|
648
|
+
type = type.to_immutable_string
|
|
667
649
|
end
|
|
650
|
+
|
|
651
|
+
type
|
|
652
|
+
end
|
|
653
|
+
|
|
654
|
+
def check_model_columns(columns_present)
|
|
655
|
+
raise ArgumentError, "You can not use both only_columns and ignored_columns in the same model." if columns_present
|
|
668
656
|
end
|
|
669
657
|
end
|
|
670
658
|
end
|
|
@@ -387,6 +387,8 @@ module ActiveRecord
|
|
|
387
387
|
generated_association_methods.module_eval <<-eoruby, __FILE__, __LINE__ + 1
|
|
388
388
|
silence_redefinition_of_method :#{association_name}_attributes=
|
|
389
389
|
def #{association_name}_attributes=(attributes)
|
|
390
|
+
association = association(:#{association_name})
|
|
391
|
+
deprecated_associations_api_guard(association, __method__)
|
|
390
392
|
assign_nested_attributes_for_#{type}_association(:#{association_name}, attributes)
|
|
391
393
|
end
|
|
392
394
|
eoruby
|
|
@@ -421,10 +423,15 @@ module ActiveRecord
|
|
|
421
423
|
# update_only is true, and a <tt>:_destroy</tt> key set to a truthy value,
|
|
422
424
|
# then the existing record will be marked for destruction.
|
|
423
425
|
def assign_nested_attributes_for_one_to_one_association(association_name, attributes)
|
|
424
|
-
options = nested_attributes_options[association_name]
|
|
425
426
|
if attributes.respond_to?(:permitted?)
|
|
426
427
|
attributes = attributes.to_h
|
|
427
428
|
end
|
|
429
|
+
|
|
430
|
+
unless attributes.is_a?(Hash)
|
|
431
|
+
raise ArgumentError, "Hash expected for `#{association_name}` attributes, got #{attributes.class.name}"
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
options = nested_attributes_options[association_name]
|
|
428
435
|
attributes = attributes.with_indifferent_access
|
|
429
436
|
existing_record = send(association_name)
|
|
430
437
|
|
|
@@ -486,7 +493,7 @@ module ActiveRecord
|
|
|
486
493
|
end
|
|
487
494
|
|
|
488
495
|
unless attributes_collection.is_a?(Hash) || attributes_collection.is_a?(Array)
|
|
489
|
-
raise ArgumentError, "Hash or Array expected for
|
|
496
|
+
raise ArgumentError, "Hash or Array expected for `#{association_name}` attributes, got #{attributes_collection.class.name}"
|
|
490
497
|
end
|
|
491
498
|
|
|
492
499
|
check_record_limit!(options[:limit], attributes_collection)
|
|
@@ -509,7 +516,7 @@ module ActiveRecord
|
|
|
509
516
|
attribute_ids.empty? ? [] : association.scope.where(association.klass.primary_key => attribute_ids)
|
|
510
517
|
end
|
|
511
518
|
|
|
512
|
-
attributes_collection.
|
|
519
|
+
records = attributes_collection.map do |attributes|
|
|
513
520
|
if attributes.respond_to?(:permitted?)
|
|
514
521
|
attributes = attributes.to_h
|
|
515
522
|
end
|
|
@@ -519,12 +526,12 @@ module ActiveRecord
|
|
|
519
526
|
unless reject_new_record?(association_name, attributes)
|
|
520
527
|
association.reader.build(attributes.except(*UNASSIGNABLE_KEYS))
|
|
521
528
|
end
|
|
522
|
-
elsif existing_record = find_record_by_id(existing_records, attributes["id"])
|
|
529
|
+
elsif existing_record = find_record_by_id(association.klass, existing_records, attributes["id"])
|
|
523
530
|
unless call_reject_if(association_name, attributes)
|
|
524
531
|
# Make sure we are operating on the actual object which is in the association's
|
|
525
532
|
# proxy_target array (either by finding it, or adding it if not found)
|
|
526
533
|
# Take into account that the proxy_target may have changed due to callbacks
|
|
527
|
-
target_record = find_record_by_id(association.target, attributes["id"])
|
|
534
|
+
target_record = find_record_by_id(association.klass, association.target, attributes["id"])
|
|
528
535
|
if target_record
|
|
529
536
|
existing_record = target_record
|
|
530
537
|
else
|
|
@@ -532,11 +539,14 @@ module ActiveRecord
|
|
|
532
539
|
end
|
|
533
540
|
|
|
534
541
|
assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy])
|
|
542
|
+
existing_record
|
|
535
543
|
end
|
|
536
544
|
else
|
|
537
545
|
raise_nested_attributes_record_not_found!(association_name, attributes["id"])
|
|
538
546
|
end
|
|
539
547
|
end
|
|
548
|
+
|
|
549
|
+
association.nested_attributes_target = records
|
|
540
550
|
end
|
|
541
551
|
|
|
542
552
|
# Takes in a limit and checks if the attributes_collection has too many
|
|
@@ -613,10 +623,8 @@ module ActiveRecord
|
|
|
613
623
|
model, "id", record_id)
|
|
614
624
|
end
|
|
615
625
|
|
|
616
|
-
def find_record_by_id(records, id)
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
if records.first.class.composite_primary_key?
|
|
626
|
+
def find_record_by_id(klass, records, id)
|
|
627
|
+
if klass.composite_primary_key?
|
|
620
628
|
id = Array(id).map(&:to_s)
|
|
621
629
|
records.find { |record| Array(record.id).map(&:to_s) == id }
|
|
622
630
|
else
|