activerecord 8.0.0.beta1 → 8.0.0.rc2
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 +102 -2
- data/lib/active_record/association_relation.rb +1 -0
- data/lib/active_record/associations/association.rb +9 -5
- data/lib/active_record/associations/has_many_through_association.rb +7 -1
- data/lib/active_record/associations.rb +28 -16
- data/lib/active_record/attribute_methods/primary_key.rb +2 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +2 -12
- data/lib/active_record/callbacks.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +26 -8
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -5
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +6 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +8 -2
- data/lib/active_record/connection_adapters/abstract_adapter.rb +0 -1
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +8 -4
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +1 -10
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +6 -12
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +11 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +12 -10
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +0 -2
- data/lib/active_record/connection_adapters.rb +0 -56
- data/lib/active_record/core.rb +43 -14
- data/lib/active_record/database_configurations/database_config.rb +4 -0
- data/lib/active_record/database_configurations/hash_config.rb +8 -0
- data/lib/active_record/enum.rb +9 -22
- data/lib/active_record/fixtures.rb +0 -1
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/locking/optimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +5 -11
- data/lib/active_record/marshalling.rb +4 -1
- data/lib/active_record/migration/command_recorder.rb +5 -5
- data/lib/active_record/migration.rb +0 -5
- data/lib/active_record/model_schema.rb +2 -3
- data/lib/active_record/query_cache.rb +0 -4
- data/lib/active_record/query_logs.rb +5 -11
- data/lib/active_record/querying.rb +2 -2
- data/lib/active_record/railtie.rb +2 -25
- data/lib/active_record/railties/databases.rake +2 -17
- data/lib/active_record/reflection.rb +14 -19
- data/lib/active_record/relation/calculations.rb +24 -28
- data/lib/active_record/relation/predicate_builder.rb +8 -0
- data/lib/active_record/relation/query_methods.rb +76 -38
- data/lib/active_record/relation.rb +8 -1
- data/lib/active_record/result.rb +10 -9
- data/lib/active_record/table_metadata.rb +1 -3
- data/lib/active_record/tasks/database_tasks.rb +26 -34
- data/lib/active_record/testing/query_assertions.rb +2 -2
- data/lib/active_record.rb +0 -45
- data/lib/arel/table.rb +3 -7
- data/lib/arel/visitors/sqlite.rb +25 -0
- metadata +9 -10
- data/lib/active_record/relation/record_fetch_warning.rb +0 -52
@@ -224,6 +224,10 @@ module ActiveRecord
|
|
224
224
|
options[:using_index]
|
225
225
|
end
|
226
226
|
|
227
|
+
def nulls_not_distinct
|
228
|
+
options[:nulls_not_distinct]
|
229
|
+
end
|
230
|
+
|
227
231
|
def export_name_on_schema_dump?
|
228
232
|
!ActiveRecord::SchemaDumper.unique_ignore_pattern.match?(name) if name
|
229
233
|
end
|
@@ -317,7 +321,7 @@ module ActiveRecord
|
|
317
321
|
|
318
322
|
# Adds a unique constraint.
|
319
323
|
#
|
320
|
-
# t.unique_constraint(:position, name: 'unique_position', deferrable: :deferred)
|
324
|
+
# t.unique_constraint(:position, name: 'unique_position', deferrable: :deferred, nulls_not_distinct: true)
|
321
325
|
#
|
322
326
|
# See {connection.add_unique_constraint}[rdoc-ref:SchemaStatements#add_unique_constraint]
|
323
327
|
def unique_constraint(*args)
|
@@ -356,15 +360,13 @@ module ActiveRecord
|
|
356
360
|
|
357
361
|
# = Active Record PostgreSQL Adapter Alter \Table
|
358
362
|
class AlterTable < ActiveRecord::ConnectionAdapters::AlterTable
|
359
|
-
attr_reader :constraint_validations, :exclusion_constraint_adds, :
|
363
|
+
attr_reader :constraint_validations, :exclusion_constraint_adds, :unique_constraint_adds
|
360
364
|
|
361
365
|
def initialize(td)
|
362
366
|
super
|
363
367
|
@constraint_validations = []
|
364
368
|
@exclusion_constraint_adds = []
|
365
|
-
@exclusion_constraint_drops = []
|
366
369
|
@unique_constraint_adds = []
|
367
|
-
@unique_constraint_drops = []
|
368
370
|
end
|
369
371
|
|
370
372
|
def validate_constraint(name)
|
@@ -375,17 +377,9 @@ module ActiveRecord
|
|
375
377
|
@exclusion_constraint_adds << @td.new_exclusion_constraint_definition(expression, options)
|
376
378
|
end
|
377
379
|
|
378
|
-
def drop_exclusion_constraint(constraint_name)
|
379
|
-
@exclusion_constraint_drops << constraint_name
|
380
|
-
end
|
381
|
-
|
382
380
|
def add_unique_constraint(column_name, options)
|
383
381
|
@unique_constraint_adds << @td.new_unique_constraint_definition(column_name, options)
|
384
382
|
end
|
385
|
-
|
386
|
-
def drop_unique_constraint(unique_constraint_name)
|
387
|
-
@unique_constraint_drops << unique_constraint_name
|
388
|
-
end
|
389
383
|
end
|
390
384
|
end
|
391
385
|
end
|
@@ -68,6 +68,7 @@ module ActiveRecord
|
|
68
68
|
"t.unique_constraint #{unique_constraint.column.inspect}"
|
69
69
|
]
|
70
70
|
|
71
|
+
parts << "nulls_not_distinct: #{unique_constraint.nulls_not_distinct.inspect}" if unique_constraint.nulls_not_distinct
|
71
72
|
parts << "deferrable: #{unique_constraint.deferrable.inspect}" if unique_constraint.deferrable
|
72
73
|
|
73
74
|
if unique_constraint.export_name_on_schema_dump?
|
@@ -91,7 +92,7 @@ module ActiveRecord
|
|
91
92
|
spec = { type: schema_type(column).inspect }.merge!(spec)
|
92
93
|
end
|
93
94
|
|
94
|
-
spec[:enum_type] =
|
95
|
+
spec[:enum_type] = column.sql_type.inspect if column.enum?
|
95
96
|
|
96
97
|
spec
|
97
98
|
end
|
@@ -299,6 +299,8 @@ module ActiveRecord
|
|
299
299
|
|
300
300
|
# Returns the sequence name for a table's primary key or some other specified key.
|
301
301
|
def default_sequence_name(table_name, pk = "id") # :nodoc:
|
302
|
+
return nil if pk.is_a?(Array)
|
303
|
+
|
302
304
|
result = serial_sequence(table_name, pk)
|
303
305
|
return nil unless result
|
304
306
|
Utils.extract_schema_qualified_name(result).to_s
|
@@ -696,7 +698,7 @@ module ActiveRecord
|
|
696
698
|
scope = quoted_scope(table_name)
|
697
699
|
|
698
700
|
unique_info = internal_exec_query(<<~SQL, "SCHEMA", allow_retry: true, materialize_transactions: false)
|
699
|
-
SELECT c.conname, c.conrelid, c.conkey, c.condeferrable, c.condeferred
|
701
|
+
SELECT c.conname, c.conrelid, c.conkey, c.condeferrable, c.condeferred, pg_get_constraintdef(c.oid) AS constraintdef
|
700
702
|
FROM pg_constraint c
|
701
703
|
JOIN pg_class t ON c.conrelid = t.oid
|
702
704
|
JOIN pg_namespace n ON n.oid = c.connamespace
|
@@ -709,10 +711,12 @@ module ActiveRecord
|
|
709
711
|
conkey = row["conkey"].delete("{}").split(",").map(&:to_i)
|
710
712
|
columns = column_names_from_column_numbers(row["conrelid"], conkey)
|
711
713
|
|
714
|
+
nulls_not_distinct = row["constraintdef"].start_with?("UNIQUE NULLS NOT DISTINCT")
|
712
715
|
deferrable = extract_constraint_deferrable(row["condeferrable"], row["condeferred"])
|
713
716
|
|
714
717
|
options = {
|
715
718
|
name: row["conname"],
|
719
|
+
nulls_not_distinct: nulls_not_distinct,
|
716
720
|
deferrable: deferrable
|
717
721
|
}
|
718
722
|
|
@@ -764,15 +768,12 @@ module ActiveRecord
|
|
764
768
|
def remove_exclusion_constraint(table_name, expression = nil, **options)
|
765
769
|
excl_name_to_delete = exclusion_constraint_for!(table_name, expression: expression, **options).name
|
766
770
|
|
767
|
-
|
768
|
-
at.drop_exclusion_constraint(excl_name_to_delete)
|
769
|
-
|
770
|
-
execute schema_creation.accept(at)
|
771
|
+
remove_constraint(table_name, excl_name_to_delete)
|
771
772
|
end
|
772
773
|
|
773
774
|
# Adds a new unique constraint to the table.
|
774
775
|
#
|
775
|
-
# add_unique_constraint :sections, [:position], deferrable: :deferred, name: "unique_position"
|
776
|
+
# add_unique_constraint :sections, [:position], deferrable: :deferred, name: "unique_position", nulls_not_distinct: true
|
776
777
|
#
|
777
778
|
# generates:
|
778
779
|
#
|
@@ -789,6 +790,9 @@ module ActiveRecord
|
|
789
790
|
# Specify whether or not the unique constraint should be deferrable. Valid values are +false+ or +:immediate+ or +:deferred+ to specify the default behavior. Defaults to +false+.
|
790
791
|
# [<tt>:using_index</tt>]
|
791
792
|
# To specify an existing unique index name. Defaults to +nil+.
|
793
|
+
# [<tt>:nulls_not_distinct</tt>]
|
794
|
+
# Create a unique constraint where NULLs are treated equally.
|
795
|
+
# Note: only supported by PostgreSQL version 15.0.0 and greater.
|
792
796
|
def add_unique_constraint(table_name, column_name = nil, **options)
|
793
797
|
options = unique_constraint_options(table_name, column_name, options)
|
794
798
|
at = create_alter_table(table_name)
|
@@ -819,10 +823,7 @@ module ActiveRecord
|
|
819
823
|
def remove_unique_constraint(table_name, column_name = nil, **options)
|
820
824
|
unique_name_to_delete = unique_constraint_for!(table_name, column: column_name, **options).name
|
821
825
|
|
822
|
-
|
823
|
-
at.drop_unique_constraint(unique_name_to_delete)
|
824
|
-
|
825
|
-
execute schema_creation.accept(at)
|
826
|
+
remove_constraint(table_name, unique_name_to_delete)
|
826
827
|
end
|
827
828
|
|
828
829
|
# Maps logical Rails types to PostgreSQL-specific data types.
|
@@ -575,10 +575,12 @@ module ActiveRecord
|
|
575
575
|
end
|
576
576
|
|
577
577
|
# Rename an existing enum type to something else.
|
578
|
-
def rename_enum(name, **options)
|
579
|
-
|
578
|
+
def rename_enum(name, new_name = nil, **options)
|
579
|
+
new_name ||= options.fetch(:to) do
|
580
|
+
raise ArgumentError, "rename_enum requires two from/to name positional arguments."
|
581
|
+
end
|
580
582
|
|
581
|
-
exec_query("ALTER TYPE #{quote_table_name(name)} RENAME TO #{
|
583
|
+
exec_query("ALTER TYPE #{quote_table_name(name)} RENAME TO #{quote_table_name(new_name)}").tap { reload_type_map }
|
582
584
|
end
|
583
585
|
|
584
586
|
# Add enum value to an existing enum type.
|
@@ -586,14 +588,14 @@ module ActiveRecord
|
|
586
588
|
before, after = options.values_at(:before, :after)
|
587
589
|
sql = +"ALTER TYPE #{quote_table_name(type_name)} ADD VALUE"
|
588
590
|
sql << " IF NOT EXISTS" if options[:if_not_exists]
|
589
|
-
sql << "
|
591
|
+
sql << " #{quote(value)}"
|
590
592
|
|
591
593
|
if before && after
|
592
594
|
raise ArgumentError, "Cannot have both :before and :after at the same time"
|
593
595
|
elsif before
|
594
|
-
sql << " BEFORE
|
596
|
+
sql << " BEFORE #{quote(before)}"
|
595
597
|
elsif after
|
596
|
-
sql << " AFTER
|
598
|
+
sql << " AFTER #{quote(after)}"
|
597
599
|
end
|
598
600
|
|
599
601
|
execute(sql).tap { reload_type_map }
|
@@ -608,7 +610,7 @@ module ActiveRecord
|
|
608
610
|
from = options.fetch(:from) { raise ArgumentError, ":from is required" }
|
609
611
|
to = options.fetch(:to) { raise ArgumentError, ":to is required" }
|
610
612
|
|
611
|
-
execute("ALTER TYPE #{quote_table_name(type_name)} RENAME VALUE
|
613
|
+
execute("ALTER TYPE #{quote_table_name(type_name)} RENAME VALUE #{quote(from)} TO #{quote(to)}").tap {
|
612
614
|
reload_type_map
|
613
615
|
}
|
614
616
|
end
|
@@ -671,8 +673,8 @@ module ActiveRecord
|
|
671
673
|
m.register_type "int4", Type::Integer.new(limit: 4)
|
672
674
|
m.register_type "int8", Type::Integer.new(limit: 8)
|
673
675
|
m.register_type "oid", OID::Oid.new
|
674
|
-
m.register_type "float4", Type::Float.new
|
675
|
-
m.
|
676
|
+
m.register_type "float4", Type::Float.new(limit: 24)
|
677
|
+
m.register_type "float8", Type::Float.new
|
676
678
|
m.register_type "text", Type::Text.new
|
677
679
|
register_class_with_limit m, "varchar", Type::String
|
678
680
|
m.alias_type "char", "varchar"
|
@@ -796,7 +798,7 @@ module ActiveRecord
|
|
796
798
|
|
797
799
|
case exception.result.try(:error_field, PG::PG_DIAG_SQLSTATE)
|
798
800
|
when nil
|
799
|
-
if exception.message.match?(/connection is closed/i)
|
801
|
+
if exception.message.match?(/connection is closed/i) || exception.message.match?(/no connection to the server/i)
|
800
802
|
ConnectionNotEstablished.new(exception, connection_pool: @pool)
|
801
803
|
elsif exception.is_a?(PG::ConnectionBad)
|
802
804
|
# libpq message style always ends with a newline; the pg gem's internal
|
@@ -68,7 +68,7 @@ module ActiveRecord
|
|
68
68
|
raise StandardError, "You need to enable the shared-cache mode in SQLite mode before attempting to change the transaction isolation level" unless shared_cache?
|
69
69
|
end
|
70
70
|
|
71
|
-
internal_execute("BEGIN #{mode} TRANSACTION", allow_retry: true, materialize_transactions: false)
|
71
|
+
internal_execute("BEGIN #{mode} TRANSACTION", "TRANSACTION", allow_retry: true, materialize_transactions: false)
|
72
72
|
if isolation
|
73
73
|
@previous_read_uncommitted = query_value("PRAGMA read_uncommitted")
|
74
74
|
internal_execute("PRAGMA read_uncommitted=ON", "TRANSACTION", allow_retry: true, materialize_transactions: false)
|
@@ -31,62 +31,6 @@ module ActiveRecord
|
|
31
31
|
class_name, path_to_adapter = @adapters[adapter_name.to_s]
|
32
32
|
|
33
33
|
unless class_name
|
34
|
-
# To provide better error messages for adapters expecting the pre-7.2 adapter registration API, we attempt
|
35
|
-
# to load the adapter file from the old location which was required by convention, and then raise an error
|
36
|
-
# describing how to upgrade the adapter to the new API.
|
37
|
-
legacy_adapter_path = "active_record/connection_adapters/#{adapter_name}_adapter"
|
38
|
-
legacy_adapter_connection_method_name = "#{adapter_name}_connection".to_sym
|
39
|
-
|
40
|
-
begin
|
41
|
-
require legacy_adapter_path
|
42
|
-
# If we reach here it means we found the found a file that may be the legacy adapter and should raise.
|
43
|
-
if ActiveRecord::ConnectionHandling.method_defined?(legacy_adapter_connection_method_name)
|
44
|
-
# If we find the connection method then we care certain it is a legacy adapter.
|
45
|
-
deprecation_message = <<~MSG.squish
|
46
|
-
Database configuration specifies '#{adapter_name}' adapter but that adapter has not been registered.
|
47
|
-
Rails 7.2 has changed the way Active Record database adapters are loaded. The adapter needs to be
|
48
|
-
updated to register itself rather than being loaded by convention.
|
49
|
-
Ensure that the adapter in the Gemfile is at the latest version. If it is, then the adapter may need to
|
50
|
-
be modified.
|
51
|
-
See:
|
52
|
-
https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters.html#method-c-register
|
53
|
-
MSG
|
54
|
-
|
55
|
-
exception_message = <<~MSG.squish
|
56
|
-
Database configuration specifies '#{adapter_name}' adapter but that adapter has not been registered.
|
57
|
-
Ensure that the adapter in the Gemfile is at the latest version. If it is, then the adapter may need to
|
58
|
-
be modified.
|
59
|
-
MSG
|
60
|
-
else
|
61
|
-
# If we do not find the connection method we are much less certain it is a legacy adapter. Even though the
|
62
|
-
# file exists in the location defined by convenntion, it does not necessarily mean that file is supposed
|
63
|
-
# to define the adapter the legacy way. So raise an error that explains both possibilities.
|
64
|
-
deprecation_message = <<~MSG.squish
|
65
|
-
Database configuration specifies nonexistent '#{adapter_name}' adapter.
|
66
|
-
Available adapters are: #{@adapters.keys.sort.join(", ")}.
|
67
|
-
Ensure that the adapter is spelled correctly in config/database.yml and that you've added the necessary
|
68
|
-
adapter gem to your Gemfile if it's not in the list of available adapters.
|
69
|
-
Rails 7.2 has changed the way Active Record database adapters are loaded. Ensure that the adapter in
|
70
|
-
the Gemfile is at the latest version. If it is up to date, the adapter may need to be modified.
|
71
|
-
See:
|
72
|
-
https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters.html#method-c-register
|
73
|
-
MSG
|
74
|
-
|
75
|
-
exception_message = <<~MSG.squish
|
76
|
-
Database configuration specifies nonexistent '#{adapter_name}' adapter.
|
77
|
-
Available adapters are: #{@adapters.keys.sort.join(", ")}.
|
78
|
-
Ensure that the adapter is spelled correctly in config/database.yml and that you've added the necessary
|
79
|
-
adapter gem to your Gemfile and that it is at its latest version. If it is up to date, the adapter may
|
80
|
-
need to be modified.
|
81
|
-
MSG
|
82
|
-
end
|
83
|
-
|
84
|
-
ActiveRecord.deprecator.warn(deprecation_message)
|
85
|
-
raise AdapterNotFound, exception_message
|
86
|
-
rescue LoadError => error
|
87
|
-
# The adapter was not found in the legacy location so fall through to the error handling for a missing adapter.
|
88
|
-
end
|
89
|
-
|
90
34
|
raise AdapterNotFound, <<~MSG.squish
|
91
35
|
Database configuration specifies nonexistent '#{adapter_name}' adapter.
|
92
36
|
Available adapters are: #{@adapters.keys.sort.join(", ")}.
|
data/lib/active_record/core.rb
CHANGED
@@ -103,7 +103,19 @@ module ActiveRecord
|
|
103
103
|
|
104
104
|
class_attribute :shard_selector, instance_accessor: false, default: nil
|
105
105
|
|
106
|
-
|
106
|
+
##
|
107
|
+
# :singleton-method:
|
108
|
+
#
|
109
|
+
# Specifies the attributes that will be included in the output of the
|
110
|
+
# #inspect method:
|
111
|
+
#
|
112
|
+
# Post.attributes_for_inspect = [:id, :title]
|
113
|
+
# Post.first.inspect #=> "#<Post id: 1, title: "Hello, World!">"
|
114
|
+
#
|
115
|
+
# When set to `:all` inspect will list all the record's attributes:
|
116
|
+
#
|
117
|
+
# Post.attributes_for_inspect = :all
|
118
|
+
# Post.first.inspect #=> "#<Post id: 1, title: "Hello, World!", published_at: "2023-10-23 14:28:11 +0000">"
|
107
119
|
class_attribute :attributes_for_inspect, instance_accessor: false, default: :all
|
108
120
|
|
109
121
|
def self.application_record_class? # :nodoc:
|
@@ -370,7 +382,7 @@ module ActiveRecord
|
|
370
382
|
end
|
371
383
|
|
372
384
|
def predicate_builder # :nodoc:
|
373
|
-
@predicate_builder ||= PredicateBuilder.new(
|
385
|
+
@predicate_builder ||= PredicateBuilder.new(TableMetadata.new(self, arel_table))
|
374
386
|
end
|
375
387
|
|
376
388
|
def type_caster # :nodoc:
|
@@ -415,10 +427,6 @@ module ActiveRecord
|
|
415
427
|
end
|
416
428
|
end
|
417
429
|
|
418
|
-
def table_metadata
|
419
|
-
TableMetadata.new(self, arel_table)
|
420
|
-
end
|
421
|
-
|
422
430
|
def cached_find_by(keys, values)
|
423
431
|
with_connection do |connection|
|
424
432
|
statement = cached_find_by_statement(connection, keys) { |params|
|
@@ -529,12 +537,7 @@ module ActiveRecord
|
|
529
537
|
|
530
538
|
##
|
531
539
|
def initialize_dup(other) # :nodoc:
|
532
|
-
@attributes =
|
533
|
-
if self.class.composite_primary_key?
|
534
|
-
@primary_key.each { |key| @attributes.reset(key) }
|
535
|
-
else
|
536
|
-
@attributes.reset(@primary_key)
|
537
|
-
end
|
540
|
+
@attributes = init_attributes(other)
|
538
541
|
|
539
542
|
_run_initialize_callbacks
|
540
543
|
|
@@ -546,6 +549,18 @@ module ActiveRecord
|
|
546
549
|
super
|
547
550
|
end
|
548
551
|
|
552
|
+
def init_attributes(_) # :nodoc:
|
553
|
+
attrs = @attributes.deep_dup
|
554
|
+
|
555
|
+
if self.class.composite_primary_key?
|
556
|
+
@primary_key.each { |key| attrs.reset(key) }
|
557
|
+
else
|
558
|
+
attrs.reset(@primary_key)
|
559
|
+
end
|
560
|
+
|
561
|
+
attrs
|
562
|
+
end
|
563
|
+
|
549
564
|
# Populate +coder+ with attributes about this record that should be
|
550
565
|
# serialized. The structure of +coder+ defined in this method is
|
551
566
|
# guaranteed to match the structure of +coder+ passed to the #init_with
|
@@ -725,12 +740,26 @@ module ActiveRecord
|
|
725
740
|
self.class.connection_handler
|
726
741
|
end
|
727
742
|
|
728
|
-
# Returns the attributes
|
743
|
+
# Returns the attributes of the record as a nicely formatted string.
|
744
|
+
#
|
745
|
+
# Post.first.inspect
|
746
|
+
# #=> "#<Post id: 1, title: "Hello, World!", published_at: "2023-10-23 14:28:11 +0000">"
|
747
|
+
#
|
748
|
+
# The attributes can be limited by setting <tt>.attributes_for_inspect</tt>.
|
749
|
+
#
|
750
|
+
# Post.attributes_for_inspect = [:id, :title]
|
751
|
+
# Post.first.inspect
|
752
|
+
# #=> "#<Post id: 1, title: "Hello, World!">"
|
729
753
|
def inspect
|
730
754
|
inspect_with_attributes(attributes_for_inspect)
|
731
755
|
end
|
732
756
|
|
733
|
-
# Returns
|
757
|
+
# Returns all attributes of the record as a nicely formatted string,
|
758
|
+
# ignoring <tt>.attributes_for_inspect</tt>.
|
759
|
+
#
|
760
|
+
# Post.first.full_inspect
|
761
|
+
# #=> "#<Post id: 1, title: "Hello, World!", published_at: "2023-10-23 14:28:11 +0000">"
|
762
|
+
#
|
734
763
|
def full_inspect
|
735
764
|
inspect_with_attributes(all_attributes_for_inspect)
|
736
765
|
end
|
@@ -130,6 +130,14 @@ module ActiveRecord
|
|
130
130
|
Base.configurations.primary?(name)
|
131
131
|
end
|
132
132
|
|
133
|
+
# Determines whether the db:prepare task should seed the database from db/seeds.rb.
|
134
|
+
#
|
135
|
+
# If the `seeds` key is present in the config, `seeds?` will return its value. Otherwise, it
|
136
|
+
# will return `true` for the primary database and `false` for all other configs.
|
137
|
+
def seeds?
|
138
|
+
configuration_hash.fetch(:seeds, primary?)
|
139
|
+
end
|
140
|
+
|
133
141
|
# Determines whether to dump the schema/structure files and the filename that
|
134
142
|
# should be used.
|
135
143
|
#
|
data/lib/active_record/enum.rb
CHANGED
@@ -213,34 +213,16 @@ module ActiveRecord
|
|
213
213
|
attr_reader :name, :mapping
|
214
214
|
end
|
215
215
|
|
216
|
-
def enum(name
|
217
|
-
|
218
|
-
|
219
|
-
return _enum(name, values, **options)
|
220
|
-
end
|
221
|
-
|
222
|
-
definitions = options.slice!(:_prefix, :_suffix, :_scopes, :_default, :_instance_methods)
|
223
|
-
options.transform_keys! { |key| :"#{key[1..-1]}" }
|
224
|
-
|
225
|
-
definitions.each { |name, values| _enum(name, values, **options) }
|
226
|
-
|
227
|
-
ActiveRecord.deprecator.warn(<<~MSG)
|
228
|
-
Defining enums with keyword arguments is deprecated and will be removed
|
229
|
-
in Rails 8.0. Positional arguments should be used instead:
|
230
|
-
|
231
|
-
#{definitions.map { |name, values| "enum :#{name}, #{values}" }.join("\n")}
|
232
|
-
MSG
|
216
|
+
def enum(name, values = nil, **options)
|
217
|
+
values, options = options, {} unless values
|
218
|
+
_enum(name, values, **options)
|
233
219
|
end
|
234
220
|
|
235
221
|
private
|
236
|
-
def inherited(base)
|
237
|
-
base.defined_enums = defined_enums.deep_dup
|
238
|
-
super
|
239
|
-
end
|
240
|
-
|
241
222
|
def _enum(name, values, prefix: nil, suffix: nil, scopes: true, instance_methods: true, validate: false, **options)
|
242
223
|
assert_valid_enum_definition_values(values)
|
243
224
|
assert_valid_enum_options(options)
|
225
|
+
|
244
226
|
# statuses = { }
|
245
227
|
enum_values = ActiveSupport::HashWithIndifferentAccess.new
|
246
228
|
name = name.to_s
|
@@ -304,6 +286,11 @@ module ActiveRecord
|
|
304
286
|
enum_values.freeze
|
305
287
|
end
|
306
288
|
|
289
|
+
def inherited(base)
|
290
|
+
base.defined_enums = defined_enums.deep_dup
|
291
|
+
super
|
292
|
+
end
|
293
|
+
|
307
294
|
class EnumMethods < Module # :nodoc:
|
308
295
|
def initialize(klass)
|
309
296
|
@klass = klass
|
@@ -9,7 +9,7 @@ module ActiveRecord
|
|
9
9
|
# it was opened, an ActiveRecord::StaleObjectError exception is thrown if that has occurred
|
10
10
|
# and the update is ignored.
|
11
11
|
#
|
12
|
-
# Check out
|
12
|
+
# Check out ActiveRecord::Locking::Pessimistic for an alternative.
|
13
13
|
#
|
14
14
|
# == Usage
|
15
15
|
#
|
@@ -126,18 +126,12 @@ module ActiveRecord
|
|
126
126
|
end
|
127
127
|
end
|
128
128
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
return frame if frame
|
134
|
-
end
|
135
|
-
nil
|
136
|
-
end
|
137
|
-
else
|
138
|
-
def query_source_location
|
139
|
-
backtrace_cleaner.clean(caller(1).lazy).first
|
129
|
+
def query_source_location
|
130
|
+
Thread.each_caller_location do |location|
|
131
|
+
frame = backtrace_cleaner.clean_frame(location)
|
132
|
+
return frame if frame
|
140
133
|
end
|
134
|
+
nil
|
141
135
|
end
|
142
136
|
|
143
137
|
def filter(name, value)
|
@@ -25,7 +25,10 @@ module ActiveRecord
|
|
25
25
|
payload = [attributes_for_database, new_record?]
|
26
26
|
|
27
27
|
cached_associations = self.class.reflect_on_all_associations.select do |reflection|
|
28
|
-
association_cached?(reflection.name)
|
28
|
+
if association_cached?(reflection.name)
|
29
|
+
association = association(reflection.name)
|
30
|
+
association.loaded? || association.target.present?
|
31
|
+
end
|
29
32
|
end
|
30
33
|
|
31
34
|
unless cached_associations.empty?
|
@@ -40,7 +40,7 @@ module ActiveRecord
|
|
40
40
|
# * remove_reference
|
41
41
|
# * remove_timestamps
|
42
42
|
# * rename_column
|
43
|
-
# * rename_enum
|
43
|
+
# * rename_enum
|
44
44
|
# * rename_enum_value (must supply a +:from+ and +:to+ option)
|
45
45
|
# * rename_index
|
46
46
|
# * rename_table
|
@@ -364,13 +364,13 @@ module ActiveRecord
|
|
364
364
|
end
|
365
365
|
|
366
366
|
def invert_rename_enum(args)
|
367
|
-
name,
|
367
|
+
name, new_name, = args
|
368
368
|
|
369
|
-
|
370
|
-
|
369
|
+
if new_name.is_a?(Hash) && new_name.key?(:to)
|
370
|
+
new_name = new_name[:to]
|
371
371
|
end
|
372
372
|
|
373
|
-
[:rename_enum, [
|
373
|
+
[:rename_enum, [new_name, name]]
|
374
374
|
end
|
375
375
|
|
376
376
|
def invert_rename_enum_value(args)
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "set"
|
4
3
|
require "active_support/core_ext/array/access"
|
5
4
|
require "active_support/core_ext/enumerable"
|
6
5
|
require "active_support/core_ext/module/attribute_accessors"
|
@@ -679,10 +678,6 @@ module ActiveRecord
|
|
679
678
|
paths = all_configs.flat_map { |config| config.migrations_paths || Migrator.migrations_paths }.uniq
|
680
679
|
@file_watcher.new([], paths.index_with(["rb"]), &block)
|
681
680
|
end
|
682
|
-
|
683
|
-
def connection
|
684
|
-
ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
685
|
-
end
|
686
681
|
end
|
687
682
|
|
688
683
|
class << self
|
@@ -276,15 +276,14 @@ module ActiveRecord
|
|
276
276
|
end
|
277
277
|
|
278
278
|
@table_name = value
|
279
|
-
@quoted_table_name = nil
|
280
279
|
@arel_table = nil
|
281
280
|
@sequence_name = nil unless @explicit_sequence_name
|
282
281
|
@predicate_builder = nil
|
283
282
|
end
|
284
283
|
|
285
|
-
# Returns a quoted version of the table name
|
284
|
+
# Returns a quoted version of the table name.
|
286
285
|
def quoted_table_name
|
287
|
-
|
286
|
+
adapter_class.quote_table_name(table_name)
|
288
287
|
end
|
289
288
|
|
290
289
|
# Computes the table name, (re)sets it internally, and returns it.
|
@@ -43,10 +43,6 @@ module ActiveRecord
|
|
43
43
|
pool.disable_query_cache!
|
44
44
|
pool.clear_query_cache
|
45
45
|
end
|
46
|
-
|
47
|
-
ActiveRecord::Base.connection_handler.each_connection_pool do |pool|
|
48
|
-
pool.release_connection if pool.active_connection? && !pool.lease_connection.transaction_open?
|
49
|
-
end
|
50
46
|
end
|
51
47
|
|
52
48
|
def self.install_executor_hooks(executor = ActiveSupport::Executor)
|
@@ -152,18 +152,12 @@ module ActiveRecord
|
|
152
152
|
self.cached_comment = nil
|
153
153
|
end
|
154
154
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
return frame if frame
|
160
|
-
end
|
161
|
-
nil
|
162
|
-
end
|
163
|
-
else
|
164
|
-
def query_source_location # :nodoc:
|
165
|
-
LogSubscriber.backtrace_cleaner.clean(caller_locations(1).each).first
|
155
|
+
def query_source_location # :nodoc:
|
156
|
+
Thread.each_caller_location do |location|
|
157
|
+
frame = LogSubscriber.backtrace_cleaner.clean_frame(location)
|
158
|
+
return frame if frame
|
166
159
|
end
|
160
|
+
nil
|
167
161
|
end
|
168
162
|
|
169
163
|
ActiveSupport::ExecutionContext.after_change { ActiveRecord::QueryLogs.clear_cache }
|
@@ -86,10 +86,10 @@ module ActiveRecord
|
|
86
86
|
|
87
87
|
message_bus.instrument("instantiation.active_record", payload) do
|
88
88
|
if result_set.includes_column?(inheritance_column)
|
89
|
-
result_set.map { |record| instantiate(record, column_types, &block) }
|
89
|
+
result_set.indexed_rows.map { |record| instantiate(record, column_types, &block) }
|
90
90
|
else
|
91
91
|
# Instantiate a homogeneous set
|
92
|
-
result_set.map { |record| instantiate_instance_of(self, record, column_types, &block) }
|
92
|
+
result_set.indexed_rows.map { |record| instantiate_instance_of(self, record, column_types, &block) }
|
93
93
|
end
|
94
94
|
end
|
95
95
|
end
|