activerecord 7.1.5.1 → 8.0.2
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 +369 -2484
- data/README.rdoc +15 -15
- data/examples/performance.rb +2 -2
- data/lib/active_record/association_relation.rb +2 -1
- 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 +21 -8
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
- data/lib/active_record/associations/builder/association.rb +7 -6
- data/lib/active_record/associations/builder/belongs_to.rb +1 -0
- 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/collection_association.rb +17 -9
- data/lib/active_record/associations/collection_proxy.rb +14 -1
- data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
- data/lib/active_record/associations/errors.rb +265 -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/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +4 -3
- data/lib/active_record/associations/preloader/branch.rb +7 -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 +92 -295
- 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/read.rb +1 -13
- data/lib/active_record/attribute_methods/serialization.rb +4 -24
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +9 -18
- data/lib/active_record/attribute_methods.rb +71 -75
- data/lib/active_record/attributes.rb +63 -49
- data/lib/active_record/autosave_association.rb +92 -57
- data/lib/active_record/base.rb +2 -3
- data/lib/active_record/callbacks.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +48 -122
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +0 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +286 -77
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +119 -55
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +197 -76
- data/lib/active_record/connection_adapters/abstract/quoting.rb +66 -92
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -5
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +12 -3
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +48 -12
- data/lib/active_record/connection_adapters/abstract/transaction.rb +140 -67
- data/lib/active_record/connection_adapters/abstract_adapter.rb +85 -90
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +71 -52
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +9 -1
- data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -57
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +2 -8
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +56 -45
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +92 -101
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +13 -31
- data/lib/active_record/connection_adapters/pool_config.rb +14 -13
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +86 -41
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- 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/uuid.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +58 -58
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +1 -11
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +36 -20
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +3 -2
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +75 -28
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +73 -113
- data/lib/active_record/connection_adapters/schema_cache.rb +124 -131
- data/lib/active_record/connection_adapters/sqlite3/column.rb +14 -1
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +81 -97
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +57 -46
- 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 +29 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +35 -3
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +183 -87
- data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +39 -69
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +19 -65
- data/lib/active_record/connection_adapters.rb +65 -0
- data/lib/active_record/connection_handling.rb +74 -37
- data/lib/active_record/core.rb +132 -51
- data/lib/active_record/counter_cache.rb +19 -10
- data/lib/active_record/database_configurations/connection_url_resolver.rb +9 -2
- data/lib/active_record/database_configurations/database_config.rb +23 -4
- data/lib/active_record/database_configurations/hash_config.rb +46 -34
- data/lib/active_record/database_configurations/url_config.rb +20 -1
- data/lib/active_record/database_configurations.rb +1 -1
- data/lib/active_record/delegated_type.rb +41 -17
- data/lib/active_record/dynamic_matchers.rb +2 -2
- data/lib/active_record/encryption/config.rb +3 -1
- data/lib/active_record/encryption/encryptable_record.rb +7 -7
- data/lib/active_record/encryption/encrypted_attribute_type.rb +33 -4
- data/lib/active_record/encryption/encryptor.rb +28 -6
- 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 +8 -1
- data/lib/active_record/enum.rb +20 -16
- data/lib/active_record/errors.rb +54 -20
- data/lib/active_record/explain.rb +13 -24
- data/lib/active_record/fixtures.rb +37 -33
- data/lib/active_record/future_result.rb +21 -13
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +4 -2
- data/lib/active_record/insert_all.rb +19 -16
- data/lib/active_record/integration.rb +4 -1
- data/lib/active_record/internal_metadata.rb +48 -34
- data/lib/active_record/locking/optimistic.rb +8 -7
- data/lib/active_record/log_subscriber.rb +5 -32
- data/lib/active_record/message_pack.rb +1 -1
- data/lib/active_record/migration/command_recorder.rb +33 -14
- data/lib/active_record/migration/compatibility.rb +8 -3
- 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 +104 -98
- data/lib/active_record/model_schema.rb +32 -70
- data/lib/active_record/nested_attributes.rb +15 -9
- data/lib/active_record/normalization.rb +3 -7
- data/lib/active_record/persistence.rb +127 -451
- data/lib/active_record/query_cache.rb +19 -8
- data/lib/active_record/query_logs.rb +104 -37
- data/lib/active_record/query_logs_formatter.rb +17 -28
- data/lib/active_record/querying.rb +24 -12
- data/lib/active_record/railtie.rb +26 -68
- data/lib/active_record/railties/controller_runtime.rb +13 -4
- data/lib/active_record/railties/databases.rake +43 -61
- data/lib/active_record/reflection.rb +112 -53
- data/lib/active_record/relation/batches/batch_enumerator.rb +19 -5
- data/lib/active_record/relation/batches.rb +138 -72
- data/lib/active_record/relation/calculations.rb +122 -82
- data/lib/active_record/relation/delegation.rb +30 -22
- data/lib/active_record/relation/finder_methods.rb +32 -18
- 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 +10 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -1
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
- data/lib/active_record/relation/predicate_builder.rb +16 -3
- data/lib/active_record/relation/query_attribute.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +317 -101
- data/lib/active_record/relation/spawn_methods.rb +3 -19
- data/lib/active_record/relation/where_clause.rb +7 -19
- data/lib/active_record/relation.rb +561 -119
- data/lib/active_record/result.rb +95 -46
- data/lib/active_record/runtime_registry.rb +39 -0
- data/lib/active_record/sanitization.rb +31 -25
- data/lib/active_record/schema.rb +8 -6
- data/lib/active_record/schema_dumper.rb +53 -20
- data/lib/active_record/schema_migration.rb +31 -14
- data/lib/active_record/scoping/named.rb +6 -2
- data/lib/active_record/signed_id.rb +24 -4
- data/lib/active_record/statement_cache.rb +19 -19
- data/lib/active_record/store.rb +7 -3
- data/lib/active_record/table_metadata.rb +2 -13
- data/lib/active_record/tasks/database_tasks.rb +87 -58
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -3
- data/lib/active_record/tasks/postgresql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/sqlite_database_tasks.rb +4 -3
- data/lib/active_record/test_fixtures.rb +98 -89
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +2 -2
- data/lib/active_record/token_for.rb +22 -12
- data/lib/active_record/touch_later.rb +1 -1
- data/lib/active_record/transaction.rb +132 -0
- data/lib/active_record/transactions.rb +72 -17
- data/lib/active_record/translation.rb +0 -2
- data/lib/active_record/type/serialized.rb +1 -3
- data/lib/active_record/type_caster/connection.rb +4 -4
- data/lib/active_record/validations/associated.rb +9 -3
- data/lib/active_record/validations/uniqueness.rb +23 -18
- data/lib/active_record/validations.rb +4 -1
- data/lib/active_record.rb +138 -57
- data/lib/arel/alias_predication.rb +1 -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/nodes/binary.rb +1 -7
- data/lib/arel/nodes/bound_sql_literal.rb +9 -5
- data/lib/arel/nodes/{and.rb → nary.rb} +5 -2
- data/lib/arel/nodes/node.rb +5 -4
- data/lib/arel/nodes/sql_literal.rb +8 -1
- data/lib/arel/nodes.rb +2 -2
- data/lib/arel/predications.rb +1 -1
- data/lib/arel/select_manager.rb +1 -1
- data/lib/arel/table.rb +3 -7
- data/lib/arel/tree_manager.rb +3 -2
- data/lib/arel/update_manager.rb +2 -1
- data/lib/arel/visitors/dot.rb +1 -0
- data/lib/arel/visitors/mysql.rb +9 -4
- data/lib/arel/visitors/postgresql.rb +1 -12
- data/lib/arel/visitors/sqlite.rb +25 -0
- data/lib/arel/visitors/to_sql.rb +29 -16
- data/lib/arel.rb +7 -3
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
- metadata +18 -16
- data/lib/active_record/relation/record_fetch_warning.rb +0 -49
@@ -146,6 +146,11 @@ module ActiveRecord
|
|
146
146
|
# your own model for something else, you can set +inheritance_column+:
|
147
147
|
#
|
148
148
|
# self.inheritance_column = 'zoink'
|
149
|
+
#
|
150
|
+
# If you wish to disable single-table inheritance altogether you can set
|
151
|
+
# +inheritance_column+ to +nil+
|
152
|
+
#
|
153
|
+
# self.inheritance_column = nil
|
149
154
|
|
150
155
|
##
|
151
156
|
# :singleton-method: inheritance_column=
|
@@ -271,15 +276,14 @@ module ActiveRecord
|
|
271
276
|
end
|
272
277
|
|
273
278
|
@table_name = value
|
274
|
-
@quoted_table_name = nil
|
275
279
|
@arel_table = nil
|
276
|
-
@sequence_name = nil unless
|
280
|
+
@sequence_name = nil unless @explicit_sequence_name
|
277
281
|
@predicate_builder = nil
|
278
282
|
end
|
279
283
|
|
280
|
-
# Returns a quoted version of the table name
|
284
|
+
# Returns a quoted version of the table name.
|
281
285
|
def quoted_table_name
|
282
|
-
|
286
|
+
adapter_class.quote_table_name(table_name)
|
283
287
|
end
|
284
288
|
|
285
289
|
# Computes the table name, (re)sets it internally, and returns it.
|
@@ -374,7 +378,7 @@ module ActiveRecord
|
|
374
378
|
|
375
379
|
def reset_sequence_name # :nodoc:
|
376
380
|
@explicit_sequence_name = false
|
377
|
-
@sequence_name =
|
381
|
+
@sequence_name = with_connection { |c| c.default_sequence_name(table_name, primary_key) }
|
378
382
|
end
|
379
383
|
|
380
384
|
# Sets the name of the sequence to use when generating ids to the given
|
@@ -399,39 +403,37 @@ module ActiveRecord
|
|
399
403
|
# Determines if the primary key values should be selected from their
|
400
404
|
# corresponding sequence before the insert statement.
|
401
405
|
def prefetch_primary_key?
|
402
|
-
|
406
|
+
with_connection { |c| c.prefetch_primary_key?(table_name) }
|
403
407
|
end
|
404
408
|
|
405
409
|
# Returns the next value that will be used as the primary key on
|
406
410
|
# an insert statement.
|
407
411
|
def next_sequence_value
|
408
|
-
|
412
|
+
with_connection { |c| c.next_sequence_value(sequence_name) }
|
409
413
|
end
|
410
414
|
|
411
415
|
# Indicates whether the table associated with this class exists
|
412
416
|
def table_exists?
|
413
|
-
|
417
|
+
schema_cache.data_source_exists?(table_name)
|
414
418
|
end
|
415
419
|
|
416
420
|
def attributes_builder # :nodoc:
|
417
|
-
|
421
|
+
@attributes_builder ||= begin
|
418
422
|
defaults = _default_attributes.except(*(column_names - [primary_key]))
|
419
|
-
|
423
|
+
ActiveModel::AttributeSet::Builder.new(attribute_types, defaults)
|
420
424
|
end
|
421
|
-
@attributes_builder
|
422
425
|
end
|
423
426
|
|
424
427
|
def columns_hash # :nodoc:
|
425
|
-
load_schema
|
428
|
+
load_schema unless @columns_hash
|
426
429
|
@columns_hash
|
427
430
|
end
|
428
431
|
|
429
432
|
def columns
|
430
|
-
load_schema
|
431
433
|
@columns ||= columns_hash.values.freeze
|
432
434
|
end
|
433
435
|
|
434
|
-
def _returning_columns_for_insert # :nodoc:
|
436
|
+
def _returning_columns_for_insert(connection) # :nodoc:
|
435
437
|
@_returning_columns_for_insert ||= begin
|
436
438
|
auto_populated_columns = columns.filter_map do |c|
|
437
439
|
c.name if connection.return_value_after_insert?(c)
|
@@ -441,37 +443,10 @@ module ActiveRecord
|
|
441
443
|
end
|
442
444
|
end
|
443
445
|
|
444
|
-
def attribute_types # :nodoc:
|
445
|
-
load_schema
|
446
|
-
@attribute_types ||= Hash.new(Type.default_value)
|
447
|
-
end
|
448
|
-
|
449
446
|
def yaml_encoder # :nodoc:
|
450
447
|
@yaml_encoder ||= ActiveModel::AttributeSet::YAMLEncoder.new(attribute_types)
|
451
448
|
end
|
452
449
|
|
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
450
|
# Returns the column object for the named attribute.
|
476
451
|
# Returns an ActiveRecord::ConnectionAdapters::NullColumn if the
|
477
452
|
# named attribute does not exist.
|
@@ -499,11 +474,6 @@ module ActiveRecord
|
|
499
474
|
@column_defaults ||= _default_attributes.deep_dup.to_hash.freeze
|
500
475
|
end
|
501
476
|
|
502
|
-
def _default_attributes # :nodoc:
|
503
|
-
load_schema
|
504
|
-
@default_attributes ||= ActiveModel::AttributeSet.new({})
|
505
|
-
end
|
506
|
-
|
507
477
|
# Returns an array of column names as strings.
|
508
478
|
def column_names
|
509
479
|
@column_names ||= columns.map(&:name).freeze
|
@@ -531,7 +501,7 @@ module ActiveRecord
|
|
531
501
|
# when just after creating a table you want to populate it with some default
|
532
502
|
# values, e.g.:
|
533
503
|
#
|
534
|
-
# class CreateJobLevels < ActiveRecord::Migration[
|
504
|
+
# class CreateJobLevels < ActiveRecord::Migration[8.0]
|
535
505
|
# def up
|
536
506
|
# create_table :job_levels do |t|
|
537
507
|
# t.integer :id
|
@@ -551,18 +521,20 @@ module ActiveRecord
|
|
551
521
|
# end
|
552
522
|
# end
|
553
523
|
def reset_column_information
|
554
|
-
|
524
|
+
connection_pool.active_connection&.clear_cache!
|
555
525
|
([self] + descendants).each(&:undefine_attribute_methods)
|
556
|
-
|
526
|
+
schema_cache.clear_data_source_cache!(table_name)
|
557
527
|
|
558
528
|
reload_schema_from_cache
|
559
529
|
initialize_find_by_cache
|
560
530
|
end
|
561
531
|
|
562
|
-
|
532
|
+
# Load the model's schema information either from the schema cache
|
533
|
+
# or directly from the database.
|
534
|
+
def load_schema
|
563
535
|
return if schema_loaded?
|
564
536
|
@load_schema_monitor.synchronize do
|
565
|
-
return if
|
537
|
+
return if schema_loaded?
|
566
538
|
|
567
539
|
load_schema!
|
568
540
|
|
@@ -583,9 +555,7 @@ module ActiveRecord
|
|
583
555
|
@arel_table = nil
|
584
556
|
@column_names = nil
|
585
557
|
@symbol_column_to_string_name_hash = nil
|
586
|
-
@attribute_types = nil
|
587
558
|
@content_columns = nil
|
588
|
-
@default_attributes = nil
|
589
559
|
@column_defaults = nil
|
590
560
|
@attributes_builder = nil
|
591
561
|
@columns = nil
|
@@ -611,7 +581,7 @@ module ActiveRecord
|
|
611
581
|
end
|
612
582
|
|
613
583
|
def schema_loaded?
|
614
|
-
|
584
|
+
@schema_loaded
|
615
585
|
end
|
616
586
|
|
617
587
|
def load_schema!
|
@@ -619,20 +589,10 @@ module ActiveRecord
|
|
619
589
|
raise ActiveRecord::TableNotSpecified, "#{self} has no table configured. Set one with #{self}.table_name="
|
620
590
|
end
|
621
591
|
|
622
|
-
columns_hash =
|
592
|
+
columns_hash = schema_cache.columns_hash(table_name)
|
623
593
|
columns_hash = columns_hash.except(*ignored_columns) unless ignored_columns.empty?
|
624
594
|
@columns_hash = columns_hash.freeze
|
625
|
-
|
626
|
-
type = connection.lookup_cast_type_from_column(column)
|
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"
|
635
|
-
end
|
595
|
+
|
636
596
|
_default_attributes # Precompute to cache DB-dependent attribute types
|
637
597
|
end
|
638
598
|
|
@@ -659,12 +619,14 @@ module ActiveRecord
|
|
659
619
|
end
|
660
620
|
end
|
661
621
|
|
662
|
-
def
|
622
|
+
def type_for_column(connection, column)
|
623
|
+
type = connection.lookup_cast_type_from_column(column)
|
624
|
+
|
663
625
|
if immutable_strings_by_default && type.respond_to?(:to_immutable_string)
|
664
|
-
type.to_immutable_string
|
665
|
-
else
|
666
|
-
type
|
626
|
+
type = type.to_immutable_string
|
667
627
|
end
|
628
|
+
|
629
|
+
type
|
668
630
|
end
|
669
631
|
end
|
670
632
|
end
|
@@ -421,10 +421,15 @@ module ActiveRecord
|
|
421
421
|
# update_only is true, and a <tt>:_destroy</tt> key set to a truthy value,
|
422
422
|
# then the existing record will be marked for destruction.
|
423
423
|
def assign_nested_attributes_for_one_to_one_association(association_name, attributes)
|
424
|
-
options = nested_attributes_options[association_name]
|
425
424
|
if attributes.respond_to?(:permitted?)
|
426
425
|
attributes = attributes.to_h
|
427
426
|
end
|
427
|
+
|
428
|
+
unless attributes.is_a?(Hash)
|
429
|
+
raise ArgumentError, "Hash expected for `#{association_name}` attributes, got #{attributes.class.name}"
|
430
|
+
end
|
431
|
+
|
432
|
+
options = nested_attributes_options[association_name]
|
428
433
|
attributes = attributes.with_indifferent_access
|
429
434
|
existing_record = send(association_name)
|
430
435
|
|
@@ -486,7 +491,7 @@ module ActiveRecord
|
|
486
491
|
end
|
487
492
|
|
488
493
|
unless attributes_collection.is_a?(Hash) || attributes_collection.is_a?(Array)
|
489
|
-
raise ArgumentError, "Hash or Array expected for
|
494
|
+
raise ArgumentError, "Hash or Array expected for `#{association_name}` attributes, got #{attributes_collection.class.name}"
|
490
495
|
end
|
491
496
|
|
492
497
|
check_record_limit!(options[:limit], attributes_collection)
|
@@ -509,7 +514,7 @@ module ActiveRecord
|
|
509
514
|
attribute_ids.empty? ? [] : association.scope.where(association.klass.primary_key => attribute_ids)
|
510
515
|
end
|
511
516
|
|
512
|
-
attributes_collection.
|
517
|
+
records = attributes_collection.map do |attributes|
|
513
518
|
if attributes.respond_to?(:permitted?)
|
514
519
|
attributes = attributes.to_h
|
515
520
|
end
|
@@ -519,12 +524,12 @@ module ActiveRecord
|
|
519
524
|
unless reject_new_record?(association_name, attributes)
|
520
525
|
association.reader.build(attributes.except(*UNASSIGNABLE_KEYS))
|
521
526
|
end
|
522
|
-
elsif existing_record = find_record_by_id(existing_records, attributes["id"])
|
527
|
+
elsif existing_record = find_record_by_id(association.klass, existing_records, attributes["id"])
|
523
528
|
unless call_reject_if(association_name, attributes)
|
524
529
|
# Make sure we are operating on the actual object which is in the association's
|
525
530
|
# proxy_target array (either by finding it, or adding it if not found)
|
526
531
|
# Take into account that the proxy_target may have changed due to callbacks
|
527
|
-
target_record = find_record_by_id(association.target, attributes["id"])
|
532
|
+
target_record = find_record_by_id(association.klass, association.target, attributes["id"])
|
528
533
|
if target_record
|
529
534
|
existing_record = target_record
|
530
535
|
else
|
@@ -532,11 +537,14 @@ module ActiveRecord
|
|
532
537
|
end
|
533
538
|
|
534
539
|
assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy])
|
540
|
+
existing_record
|
535
541
|
end
|
536
542
|
else
|
537
543
|
raise_nested_attributes_record_not_found!(association_name, attributes["id"])
|
538
544
|
end
|
539
545
|
end
|
546
|
+
|
547
|
+
association.nested_attributes_target = records
|
540
548
|
end
|
541
549
|
|
542
550
|
# Takes in a limit and checks if the attributes_collection has too many
|
@@ -613,10 +621,8 @@ module ActiveRecord
|
|
613
621
|
model, "id", record_id)
|
614
622
|
end
|
615
623
|
|
616
|
-
def find_record_by_id(records, id)
|
617
|
-
|
618
|
-
|
619
|
-
if records.first.class.composite_primary_key?
|
624
|
+
def find_record_by_id(klass, records, id)
|
625
|
+
if klass.composite_primary_key?
|
620
626
|
id = Array(id).map(&:to_s)
|
621
627
|
records.find { |record| Array(record.id).map(&:to_s) == id }
|
622
628
|
else
|
@@ -86,10 +86,8 @@ module ActiveRecord # :nodoc:
|
|
86
86
|
#
|
87
87
|
# User.normalize_value_for(:phone, "+1 (555) 867-5309") # => "5558675309"
|
88
88
|
def normalizes(*names, with:, apply_to_nil: false)
|
89
|
-
names
|
90
|
-
|
91
|
-
NormalizedValueType.new(cast_type: cast_type, normalizer: with, normalize_nil: apply_to_nil)
|
92
|
-
end
|
89
|
+
decorate_attributes(names) do |name, cast_type|
|
90
|
+
NormalizedValueType.new(cast_type: cast_type, normalizer: with, normalize_nil: apply_to_nil)
|
93
91
|
end
|
94
92
|
|
95
93
|
self.normalized_attributes += names.map(&:to_sym)
|
@@ -154,9 +152,7 @@ module ActiveRecord # :nodoc:
|
|
154
152
|
[self.class, cast_type, normalizer, normalize_nil?].hash
|
155
153
|
end
|
156
154
|
|
157
|
-
|
158
|
-
Kernel.instance_method(:inspect).bind_call(self)
|
159
|
-
end
|
155
|
+
define_method(:inspect, Kernel.instance_method(:inspect))
|
160
156
|
|
161
157
|
private
|
162
158
|
def normalize(value)
|