activerecord 7.0.0.alpha2 → 7.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +539 -11
- data/lib/active_record/associations/association.rb +2 -8
- data/lib/active_record/associations/builder/collection_association.rb +9 -2
- data/lib/active_record/associations/collection_association.rb +10 -2
- data/lib/active_record/associations/join_dependency.rb +6 -2
- data/lib/active_record/associations/preloader/association.rb +68 -48
- data/lib/active_record/associations/preloader/batch.rb +3 -6
- data/lib/active_record/associations/preloader/through_association.rb +19 -9
- data/lib/active_record/associations/preloader.rb +14 -24
- data/lib/active_record/associations/through_association.rb +2 -2
- data/lib/active_record/associations.rb +16 -3
- data/lib/active_record/asynchronous_queries_tracker.rb +3 -0
- data/lib/active_record/attribute_methods/dirty.rb +9 -1
- data/lib/active_record/attribute_methods.rb +7 -5
- data/lib/active_record/autosave_association.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +6 -26
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +18 -5
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +0 -17
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/quoting.rb +33 -70
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +4 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +9 -2
- data/lib/active_record/connection_adapters/abstract/transaction.rb +12 -19
- data/lib/active_record/connection_adapters/abstract_adapter.rb +37 -8
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/column.rb +4 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +4 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +23 -24
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +1 -1
- data/lib/active_record/connection_adapters/pool_config.rb +7 -5
- data/lib/active_record/connection_adapters/postgresql/column.rb +17 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +44 -44
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +21 -1
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +18 -1
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +15 -4
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +48 -5
- data/lib/active_record/connection_adapters/schema_cache.rb +3 -1
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +4 -2
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +15 -16
- data/lib/active_record/connection_handling.rb +31 -19
- data/lib/active_record/core.rb +13 -24
- data/lib/active_record/database_configurations/connection_url_resolver.rb +2 -1
- data/lib/active_record/database_configurations/database_config.rb +0 -9
- data/lib/active_record/database_configurations/hash_config.rb +40 -8
- data/lib/active_record/database_configurations.rb +2 -27
- data/lib/active_record/delegated_type.rb +19 -0
- data/lib/active_record/encryption/encryptable_record.rb +1 -1
- data/lib/active_record/encryption/encrypted_attribute_type.rb +1 -1
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +1 -2
- data/lib/active_record/encryption/message_serializer.rb +11 -1
- data/lib/active_record/encryption/scheme.rb +1 -1
- data/lib/active_record/enum.rb +8 -1
- data/lib/active_record/errors.rb +1 -1
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/fixture_set/table_row.rb +1 -1
- data/lib/active_record/fixtures.rb +1 -9
- data/lib/active_record/future_result.rb +2 -2
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/insert_all.rb +52 -15
- data/lib/active_record/integration.rb +3 -2
- data/lib/active_record/legacy_yaml_adapter.rb +2 -39
- data/lib/active_record/locking/pessimistic.rb +9 -3
- data/lib/active_record/log_subscriber.rb +8 -1
- data/lib/active_record/middleware/shard_selector.rb +60 -0
- data/lib/active_record/migration.rb +2 -2
- data/lib/active_record/model_schema.rb +1 -28
- data/lib/active_record/nested_attributes.rb +11 -10
- data/lib/active_record/no_touching.rb +1 -1
- data/lib/active_record/persistence.rb +99 -21
- data/lib/active_record/query_logs.rb +18 -83
- data/lib/active_record/railtie.rb +11 -1
- data/lib/active_record/railties/databases.rake +4 -91
- data/lib/active_record/reflection.rb +22 -6
- data/lib/active_record/relation/calculations.rb +1 -10
- data/lib/active_record/relation/finder_methods.rb +0 -13
- data/lib/active_record/relation/query_methods.rb +5 -14
- data/lib/active_record/relation/record_fetch_warning.rb +5 -7
- data/lib/active_record/relation/where_clause.rb +2 -15
- data/lib/active_record/relation.rb +11 -15
- data/lib/active_record/result.rb +0 -5
- data/lib/active_record/runtime_registry.rb +10 -12
- data/lib/active_record/schema_dumper.rb +7 -0
- data/lib/active_record/schema_migration.rb +4 -0
- data/lib/active_record/scoping.rb +34 -22
- data/lib/active_record/suppressor.rb +11 -15
- data/lib/active_record/tasks/database_tasks.rb +18 -44
- data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -1
- data/lib/active_record/validations/uniqueness.rb +1 -1
- data/lib/active_record.rb +41 -33
- data/lib/arel/crud.rb +12 -2
- data/lib/arel/delete_manager.rb +16 -0
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/nodes/delete_statement.rb +5 -1
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/function.rb +1 -0
- data/lib/arel/nodes/update_statement.rb +5 -1
- data/lib/arel/nodes.rb +1 -0
- data/lib/arel/predications.rb +10 -2
- data/lib/arel/update_manager.rb +16 -0
- data/lib/arel/visitors/mysql.rb +2 -1
- data/lib/arel/visitors/to_sql.rb +15 -0
- data/lib/arel.rb +1 -0
- data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
- data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
- metadata +18 -12
@@ -332,7 +332,7 @@ db_namespace = namespace :db do
|
|
332
332
|
|
333
333
|
desc "Retrieves the current schema version number"
|
334
334
|
task version: :load_config do
|
335
|
-
puts "Current version: #{ActiveRecord::Base.connection.
|
335
|
+
puts "Current version: #{ActiveRecord::Base.connection.schema_version}"
|
336
336
|
end
|
337
337
|
|
338
338
|
# desc "Raises an error if there are pending migrations"
|
@@ -469,14 +469,6 @@ db_namespace = namespace :db do
|
|
469
469
|
ActiveRecord::Tasks::DatabaseTasks.load_schema_current(ActiveRecord.schema_format, ENV["SCHEMA"])
|
470
470
|
end
|
471
471
|
|
472
|
-
task load_if_ruby: ["db:create", :environment] do
|
473
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
474
|
-
Using `bin/rails db:schema:load_if_ruby` is deprecated and will be removed in Rails 7.0.
|
475
|
-
Configure the format using `config.active_record.schema_format = :ruby` to use `schema.rb` and run `bin/rails db:schema:load` instead.
|
476
|
-
MSG
|
477
|
-
db_namespace["schema:load"].invoke if ActiveRecord.schema_format == :ruby
|
478
|
-
end
|
479
|
-
|
480
472
|
namespace :dump do
|
481
473
|
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
|
482
474
|
desc "Creates a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`) for #{name} database"
|
@@ -495,7 +487,7 @@ db_namespace = namespace :db do
|
|
495
487
|
task name => :load_config do
|
496
488
|
original_db_config = ActiveRecord::Base.connection_db_config
|
497
489
|
db_config = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env, name: name)
|
498
|
-
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config
|
490
|
+
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config)
|
499
491
|
ensure
|
500
492
|
ActiveRecord::Base.establish_connection(original_db_config) if original_db_config
|
501
493
|
end
|
@@ -533,63 +525,6 @@ db_namespace = namespace :db do
|
|
533
525
|
end
|
534
526
|
end
|
535
527
|
|
536
|
-
namespace :structure do
|
537
|
-
desc "Dumps the database structure to db/structure.sql. Specify another file with SCHEMA=db/my_structure.sql"
|
538
|
-
task dump: :load_config do
|
539
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
540
|
-
Using `bin/rails db:structure:dump` is deprecated and will be removed in Rails 7.0.
|
541
|
-
Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:dump` instead.
|
542
|
-
MSG
|
543
|
-
|
544
|
-
db_namespace["schema:dump"].invoke
|
545
|
-
db_namespace["structure:dump"].reenable
|
546
|
-
end
|
547
|
-
|
548
|
-
desc "Recreates the databases from the structure.sql file"
|
549
|
-
task load: [:load_config, :check_protected_environments] do
|
550
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
551
|
-
Using `bin/rails db:structure:load` is deprecated and will be removed in Rails 7.0.
|
552
|
-
Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:load` instead.
|
553
|
-
MSG
|
554
|
-
db_namespace["schema:load"].invoke
|
555
|
-
end
|
556
|
-
|
557
|
-
task load_if_sql: ["db:create", :environment] do
|
558
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
559
|
-
Using `bin/rails db:structure:load_if_sql` is deprecated and will be removed in Rails 7.0.
|
560
|
-
Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:load` instead.
|
561
|
-
MSG
|
562
|
-
db_namespace["schema:load"].invoke if ActiveRecord.schema_format == :sql
|
563
|
-
end
|
564
|
-
|
565
|
-
namespace :dump do
|
566
|
-
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
|
567
|
-
desc "Dumps the #{name} database structure to db/structure.sql. Specify another file with SCHEMA=db/my_structure.sql"
|
568
|
-
task name => :load_config do
|
569
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
570
|
-
Using `bin/rails db:structure:dump:#{name}` is deprecated and will be removed in Rails 7.0.
|
571
|
-
Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:dump:#{name}` instead.
|
572
|
-
MSG
|
573
|
-
db_namespace["schema:dump:#{name}"].invoke
|
574
|
-
db_namespace["structure:dump:#{name}"].reenable
|
575
|
-
end
|
576
|
-
end
|
577
|
-
end
|
578
|
-
|
579
|
-
namespace :load do
|
580
|
-
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
|
581
|
-
desc "Recreates the #{name} database from the structure.sql file"
|
582
|
-
task name => :load_config do
|
583
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
584
|
-
Using `bin/rails db:structure:load:#{name}` is deprecated and will be removed in Rails 7.0.
|
585
|
-
Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:load:#{name}` instead.
|
586
|
-
MSG
|
587
|
-
db_namespace["schema:load:#{name}"].invoke
|
588
|
-
end
|
589
|
-
end
|
590
|
-
end
|
591
|
-
end
|
592
|
-
|
593
528
|
namespace :encryption do
|
594
529
|
desc "Generate a set of keys for configuring Active Record encryption in a given environment"
|
595
530
|
task :init do
|
@@ -615,8 +550,7 @@ db_namespace = namespace :db do
|
|
615
550
|
should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
|
616
551
|
ActiveRecord::Schema.verbose = false
|
617
552
|
ActiveRecord::Base.configurations.configs_for(env_name: "test").each do |db_config|
|
618
|
-
|
619
|
-
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ActiveRecord.schema_format, filename)
|
553
|
+
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config)
|
620
554
|
end
|
621
555
|
ensure
|
622
556
|
if should_reconnect
|
@@ -624,15 +558,6 @@ db_namespace = namespace :db do
|
|
624
558
|
end
|
625
559
|
end
|
626
560
|
|
627
|
-
# desc "Recreate the test database from an existent structure.sql file"
|
628
|
-
task load_structure: %w(db:test:purge) do
|
629
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
630
|
-
Using `bin/rails db:test:load_structure` is deprecated and will be removed in Rails 7.0.
|
631
|
-
Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:test:load_schema` instead.
|
632
|
-
MSG
|
633
|
-
db_namespace["test:load_schema"].invoke
|
634
|
-
end
|
635
|
-
|
636
561
|
# desc "Empty the test database"
|
637
562
|
task purge: %w(load_config check_protected_environments) do
|
638
563
|
ActiveRecord::Base.configurations.configs_for(env_name: "test").each do |db_config|
|
@@ -660,9 +585,8 @@ db_namespace = namespace :db do
|
|
660
585
|
task name => "db:test:purge:#{name}" do
|
661
586
|
should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
|
662
587
|
ActiveRecord::Schema.verbose = false
|
663
|
-
filename = ActiveRecord::Tasks::DatabaseTasks.dump_filename(name)
|
664
588
|
db_config = ActiveRecord::Base.configurations.configs_for(env_name: "test", name: name)
|
665
|
-
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config
|
589
|
+
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config)
|
666
590
|
ensure
|
667
591
|
if should_reconnect
|
668
592
|
ActiveRecord::Base.establish_connection(ActiveRecord::Tasks::DatabaseTasks.env.to_sym)
|
@@ -670,17 +594,6 @@ db_namespace = namespace :db do
|
|
670
594
|
end
|
671
595
|
end
|
672
596
|
|
673
|
-
# desc "Recreate the #{name} test database from an existent structure.sql file"
|
674
|
-
namespace :load_structure do
|
675
|
-
task name => "db:test:purge:#{name}" do
|
676
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
677
|
-
Using `bin/rails db:test:load_structure:#{name}` is deprecated and will be removed in Rails 7.0.
|
678
|
-
Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:test:load_structure:#{name}` instead.
|
679
|
-
MSG
|
680
|
-
db_namespace["test:load_schema:#{name}"].invoke
|
681
|
-
end
|
682
|
-
end
|
683
|
-
|
684
597
|
# desc "Empty the #{name} test database"
|
685
598
|
namespace :purge do
|
686
599
|
task name => %w(load_config check_protected_environments) do
|
@@ -10,6 +10,7 @@ module ActiveRecord
|
|
10
10
|
included do
|
11
11
|
class_attribute :_reflections, instance_writer: false, default: {}
|
12
12
|
class_attribute :aggregate_reflections, instance_writer: false, default: {}
|
13
|
+
class_attribute :automatic_scope_inversing, instance_writer: false, default: false
|
13
14
|
end
|
14
15
|
|
15
16
|
class << self
|
@@ -234,6 +235,9 @@ module ActiveRecord
|
|
234
235
|
if has_inverse? && inverse_of.nil?
|
235
236
|
raise InverseOfAssociationNotFoundError.new(self)
|
236
237
|
end
|
238
|
+
if has_inverse? && inverse_of == self
|
239
|
+
raise InverseOfAssociationRecursiveError.new(self)
|
240
|
+
end
|
237
241
|
end
|
238
242
|
end
|
239
243
|
|
@@ -631,9 +635,10 @@ module ActiveRecord
|
|
631
635
|
# with the current reflection's klass name.
|
632
636
|
def valid_inverse_reflection?(reflection)
|
633
637
|
reflection &&
|
638
|
+
reflection != self &&
|
634
639
|
foreign_key == reflection.foreign_key &&
|
635
640
|
klass <= reflection.active_record &&
|
636
|
-
can_find_inverse_of_automatically?(reflection)
|
641
|
+
can_find_inverse_of_automatically?(reflection, true)
|
637
642
|
end
|
638
643
|
|
639
644
|
# Checks to see if the reflection doesn't have any options that prevent
|
@@ -642,14 +647,25 @@ module ActiveRecord
|
|
642
647
|
# have <tt>has_many</tt>, <tt>has_one</tt>, <tt>belongs_to</tt> associations.
|
643
648
|
# Third, we must not have options such as <tt>:foreign_key</tt>
|
644
649
|
# which prevent us from correctly guessing the inverse association.
|
645
|
-
|
646
|
-
# Anything with a scope can additionally ruin our attempt at finding an
|
647
|
-
# inverse, so we exclude reflections with scopes.
|
648
|
-
def can_find_inverse_of_automatically?(reflection)
|
650
|
+
def can_find_inverse_of_automatically?(reflection, inverse_reflection = false)
|
649
651
|
reflection.options[:inverse_of] != false &&
|
650
652
|
!reflection.options[:through] &&
|
651
653
|
!reflection.options[:foreign_key] &&
|
654
|
+
scope_allows_automatic_inverse_of?(reflection, inverse_reflection)
|
655
|
+
end
|
656
|
+
|
657
|
+
# Scopes on the potential inverse reflection prevent automatic
|
658
|
+
# <tt>inverse_of</tt>, since the scope could exclude the owner record
|
659
|
+
# we would inverse from. Scopes on the reflection itself allow for
|
660
|
+
# automatic <tt>inverse_of</tt> as long as
|
661
|
+
# <tt>config.active_record.automatic_scope_inversing<tt> is set to
|
662
|
+
# +true+ (the default for new applications).
|
663
|
+
def scope_allows_automatic_inverse_of?(reflection, inverse_reflection)
|
664
|
+
if inverse_reflection
|
652
665
|
!reflection.scope
|
666
|
+
else
|
667
|
+
!reflection.scope || reflection.klass.automatic_scope_inversing
|
668
|
+
end
|
653
669
|
end
|
654
670
|
|
655
671
|
def derive_class_name
|
@@ -736,7 +752,7 @@ module ActiveRecord
|
|
736
752
|
end
|
737
753
|
|
738
754
|
private
|
739
|
-
def can_find_inverse_of_automatically?(
|
755
|
+
def can_find_inverse_of_automatically?(*)
|
740
756
|
!polymorphic? && super
|
741
757
|
end
|
742
758
|
end
|
@@ -31,7 +31,7 @@ module ActiveRecord
|
|
31
31
|
#
|
32
32
|
# Article.group(:status, :category).count
|
33
33
|
# # => {["draft", "business"]=>10, ["draft", "technology"]=>4,
|
34
|
-
#
|
34
|
+
# # ["published", "business"]=>0, ["published", "technology"]=>2}
|
35
35
|
#
|
36
36
|
# If #count is used with {Relation#select}[rdoc-ref:QueryMethods#select], it will count the selected columns:
|
37
37
|
#
|
@@ -329,15 +329,6 @@ module ActiveRecord
|
|
329
329
|
group_fields = group_values
|
330
330
|
group_fields = group_fields.uniq if group_fields.size > 1
|
331
331
|
|
332
|
-
unless group_fields == group_values
|
333
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
334
|
-
`#{operation}` with group by duplicated fields does no longer affect to result in Rails 7.0.
|
335
|
-
To migrate to Rails 7.0's behavior, use `uniq!(:group)` to deduplicate group fields
|
336
|
-
(`#{klass.name&.tableize || klass.table_name}.uniq!(:group).#{operation}(#{column_name.inspect})`).
|
337
|
-
MSG
|
338
|
-
group_fields = group_values
|
339
|
-
end
|
340
|
-
|
341
332
|
if group_fields.size == 1 && group_fields.first.respond_to?(:to_sym)
|
342
333
|
association = klass._reflect_on_association(group_fields.first)
|
343
334
|
associated = association && association.belongs_to? # only count belongs_to associations
|
@@ -140,8 +140,6 @@ module ActiveRecord
|
|
140
140
|
# Person.first(3) # returns the first three objects fetched by SELECT * FROM people ORDER BY people.id LIMIT 3
|
141
141
|
#
|
142
142
|
def first(limit = nil)
|
143
|
-
check_reorder_deprecation unless loaded?
|
144
|
-
|
145
143
|
if limit
|
146
144
|
find_nth_with_limit(0, limit)
|
147
145
|
else
|
@@ -390,17 +388,6 @@ module ActiveRecord
|
|
390
388
|
end
|
391
389
|
|
392
390
|
private
|
393
|
-
def check_reorder_deprecation
|
394
|
-
if !order_values.empty? && order_values.all?(&:blank?)
|
395
|
-
blank_value = order_values.first
|
396
|
-
ActiveSupport::Deprecation.warn(<<~MSG.squish)
|
397
|
-
`.reorder(#{blank_value.inspect})` with `.first` / `.first!` no longer
|
398
|
-
takes non-deterministic result in Rails 7.0.
|
399
|
-
To continue taking non-deterministic result, use `.take` / `.take!` instead.
|
400
|
-
MSG
|
401
|
-
end
|
402
|
-
end
|
403
|
-
|
404
391
|
def construct_relation_for_exists(conditions)
|
405
392
|
conditions = sanitize_forbidden_attributes(conditions)
|
406
393
|
|
@@ -432,6 +432,7 @@ module ActiveRecord
|
|
432
432
|
references = column_references([column])
|
433
433
|
self.references_values |= references unless references.empty?
|
434
434
|
|
435
|
+
values = values.map { |value| type_caster.type_cast_for_database(column, value) }
|
435
436
|
column = order_column(column.to_s) if column.is_a?(Symbol)
|
436
437
|
|
437
438
|
spawn.order!(connection.field_ordered_value(column, values))
|
@@ -448,14 +449,14 @@ module ActiveRecord
|
|
448
449
|
# generates a query with 'ORDER BY id ASC, name ASC'.
|
449
450
|
def reorder(*args)
|
450
451
|
check_if_method_has_arguments!(__callee__, args) do
|
451
|
-
sanitize_order_arguments(args)
|
452
|
+
sanitize_order_arguments(args)
|
452
453
|
end
|
453
454
|
spawn.reorder!(*args)
|
454
455
|
end
|
455
456
|
|
456
457
|
# Same as #reorder but operates on relation in-place instead of copying.
|
457
458
|
def reorder!(*args) # :nodoc:
|
458
|
-
preprocess_order_args(args)
|
459
|
+
preprocess_order_args(args)
|
459
460
|
args.uniq!
|
460
461
|
self.reordering_value = true
|
461
462
|
self.order_values = args
|
@@ -1339,14 +1340,6 @@ module ActiveRecord
|
|
1339
1340
|
unless annotate_values.empty?
|
1340
1341
|
annotates = annotate_values
|
1341
1342
|
annotates = annotates.uniq if annotates.size > 1
|
1342
|
-
unless annotates == annotate_values
|
1343
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
1344
|
-
Duplicated query annotations are no longer shown in queries in Rails 7.0.
|
1345
|
-
To migrate to Rails 7.0's behavior, use `uniq!(:annotate)` to deduplicate query annotations
|
1346
|
-
(`#{klass.name&.tableize || klass.table_name}.uniq!(:annotate)`).
|
1347
|
-
MSG
|
1348
|
-
annotates = annotate_values
|
1349
|
-
end
|
1350
1343
|
arel.comment(*annotates)
|
1351
1344
|
end
|
1352
1345
|
|
@@ -1606,8 +1599,6 @@ module ActiveRecord
|
|
1606
1599
|
order_args.map! do |arg|
|
1607
1600
|
klass.sanitize_sql_for_order(arg)
|
1608
1601
|
end
|
1609
|
-
order_args.flatten!
|
1610
|
-
order_args.compact_blank!
|
1611
1602
|
end
|
1612
1603
|
|
1613
1604
|
def column_references(order_args)
|
@@ -1676,9 +1667,9 @@ module ActiveRecord
|
|
1676
1667
|
def check_if_method_has_arguments!(method_name, args, message = nil)
|
1677
1668
|
if args.blank?
|
1678
1669
|
raise ArgumentError, message || "The method .#{method_name}() must contain arguments."
|
1679
|
-
elsif block_given?
|
1680
|
-
yield args
|
1681
1670
|
else
|
1671
|
+
yield args if block_given?
|
1672
|
+
|
1682
1673
|
args.flatten!
|
1683
1674
|
args.compact_blank!
|
1684
1675
|
end
|
@@ -31,17 +31,15 @@ module ActiveRecord
|
|
31
31
|
end
|
32
32
|
# :startdoc:
|
33
33
|
|
34
|
-
|
35
|
-
extend
|
34
|
+
module QueryRegistry # :nodoc:
|
35
|
+
extend self
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
def initialize
|
40
|
-
@queries = []
|
37
|
+
def queries
|
38
|
+
ActiveSupport::IsolatedExecutionState[:active_record_query_registry] ||= []
|
41
39
|
end
|
42
40
|
|
43
41
|
def reset
|
44
|
-
|
42
|
+
queries.clear
|
45
43
|
end
|
46
44
|
end
|
47
45
|
end
|
@@ -163,21 +163,8 @@ module ActiveRecord
|
|
163
163
|
attr = extract_attribute(node) || begin
|
164
164
|
node.left if equality_node?(node) && node.left.is_a?(Arel::Predications)
|
165
165
|
end
|
166
|
-
|
167
|
-
|
168
|
-
ref = referenced_columns[attr]
|
169
|
-
next false unless ref
|
170
|
-
|
171
|
-
if equality_node?(node) && equality_node?(ref) || node == ref
|
172
|
-
true
|
173
|
-
else
|
174
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
175
|
-
Merging (#{node.to_sql}) and (#{ref.to_sql}) no longer maintain
|
176
|
-
both conditions, and will be replaced by the latter in Rails 7.0.
|
177
|
-
To migrate to Rails 7.0's behavior, use `relation.merge(other, rewhere: true)`.
|
178
|
-
MSG
|
179
|
-
false
|
180
|
-
end
|
166
|
+
|
167
|
+
attr && referenced_columns[attr]
|
181
168
|
end
|
182
169
|
end
|
183
170
|
|
@@ -11,7 +11,7 @@ module ActiveRecord
|
|
11
11
|
:reverse_order, :distinct, :create_with, :skip_query_cache]
|
12
12
|
|
13
13
|
CLAUSE_METHODS = [:where, :having, :from]
|
14
|
-
INVALID_METHODS_FOR_DELETE_ALL = [:distinct
|
14
|
+
INVALID_METHODS_FOR_DELETE_ALL = [:distinct]
|
15
15
|
|
16
16
|
VALUE_METHODS = MULTI_VALUE_METHODS + SINGLE_VALUE_METHODS + CLAUSE_METHODS
|
17
17
|
|
@@ -33,7 +33,6 @@ module ActiveRecord
|
|
33
33
|
@delegate_to_klass = false
|
34
34
|
@future_result = nil
|
35
35
|
@records = nil
|
36
|
-
@limited_count = nil
|
37
36
|
end
|
38
37
|
|
39
38
|
def initialize_copy(other)
|
@@ -41,11 +40,6 @@ module ActiveRecord
|
|
41
40
|
reset
|
42
41
|
end
|
43
42
|
|
44
|
-
def arel_attribute(name) # :nodoc:
|
45
|
-
table[name]
|
46
|
-
end
|
47
|
-
deprecate :arel_attribute
|
48
|
-
|
49
43
|
def bind_attribute(name, value) # :nodoc:
|
50
44
|
if reflection = klass._reflect_on_association(name)
|
51
45
|
name = reflection.foreign_key
|
@@ -295,14 +289,14 @@ module ActiveRecord
|
|
295
289
|
# Returns true if there is exactly one record.
|
296
290
|
def one?
|
297
291
|
return super if block_given?
|
298
|
-
return records.one? if
|
292
|
+
return records.one? if loaded?
|
299
293
|
limited_count == 1
|
300
294
|
end
|
301
295
|
|
302
296
|
# Returns true if there is more than one record.
|
303
297
|
def many?
|
304
298
|
return super if block_given?
|
305
|
-
return records.many? if
|
299
|
+
return records.many? if loaded?
|
306
300
|
limited_count > 1
|
307
301
|
end
|
308
302
|
|
@@ -394,7 +388,7 @@ module ActiveRecord
|
|
394
388
|
end
|
395
389
|
|
396
390
|
if timestamp
|
397
|
-
"#{size}-#{timestamp.utc.
|
391
|
+
"#{size}-#{timestamp.utc.to_formatted_s(cache_timestamp_format)}"
|
398
392
|
else
|
399
393
|
"#{size}"
|
400
394
|
end
|
@@ -485,8 +479,9 @@ module ActiveRecord
|
|
485
479
|
arel = eager_loading? ? apply_join_dependency.arel : build_arel
|
486
480
|
arel.source.left = table
|
487
481
|
|
488
|
-
|
489
|
-
|
482
|
+
group_values_arel_columns = arel_columns(group_values.uniq)
|
483
|
+
having_clause_ast = having_clause.ast unless having_clause.empty?
|
484
|
+
stmt = arel.compile_update(values, table[primary_key], having_clause_ast, group_values_arel_columns)
|
490
485
|
klass.connection.update(stmt, "#{klass} Update All").tap { reset }
|
491
486
|
end
|
492
487
|
|
@@ -615,7 +610,9 @@ module ActiveRecord
|
|
615
610
|
arel = eager_loading? ? apply_join_dependency.arel : build_arel
|
616
611
|
arel.source.left = table
|
617
612
|
|
618
|
-
|
613
|
+
group_values_arel_columns = arel_columns(group_values.uniq)
|
614
|
+
having_clause_ast = having_clause.ast unless having_clause.empty?
|
615
|
+
stmt = arel.compile_delete(table[primary_key], having_clause_ast, group_values_arel_columns)
|
619
616
|
|
620
617
|
klass.connection.delete(stmt, "#{klass} Delete All").tap { reset }
|
621
618
|
end
|
@@ -701,7 +698,6 @@ module ActiveRecord
|
|
701
698
|
@offsets = @take = nil
|
702
699
|
@cache_keys = nil
|
703
700
|
@records = nil
|
704
|
-
@limited_count = nil
|
705
701
|
self
|
706
702
|
end
|
707
703
|
|
@@ -976,7 +972,7 @@ module ActiveRecord
|
|
976
972
|
end
|
977
973
|
|
978
974
|
def limited_count
|
979
|
-
|
975
|
+
limit_value ? count : limit(2).count
|
980
976
|
end
|
981
977
|
end
|
982
978
|
end
|
data/lib/active_record/result.rb
CHANGED
@@ -1,22 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/per_thread_registry"
|
4
|
-
|
5
3
|
module ActiveRecord
|
6
4
|
# This is a thread locals registry for Active Record. For example:
|
7
5
|
#
|
8
|
-
# ActiveRecord::RuntimeRegistry.
|
9
|
-
#
|
10
|
-
# returns the connection handler local to the current thread.
|
6
|
+
# ActiveRecord::RuntimeRegistry.sql_runtime
|
11
7
|
#
|
12
|
-
#
|
13
|
-
|
14
|
-
|
15
|
-
extend ActiveSupport::PerThreadRegistry
|
8
|
+
# returns the connection handler local to the current unit of execution (either thread of fiber).
|
9
|
+
module RuntimeRegistry # :nodoc:
|
10
|
+
extend self
|
16
11
|
|
17
|
-
|
12
|
+
def sql_runtime
|
13
|
+
ActiveSupport::IsolatedExecutionState[:active_record_sql_runtime]
|
14
|
+
end
|
18
15
|
|
19
|
-
def
|
20
|
-
|
16
|
+
def sql_runtime=(runtime)
|
17
|
+
ActiveSupport::IsolatedExecutionState[:active_record_sql_runtime] = runtime
|
18
|
+
end
|
21
19
|
end
|
22
20
|
end
|
@@ -47,6 +47,7 @@ module ActiveRecord
|
|
47
47
|
def dump(stream)
|
48
48
|
header(stream)
|
49
49
|
extensions(stream)
|
50
|
+
types(stream)
|
50
51
|
tables(stream)
|
51
52
|
trailer(stream)
|
52
53
|
stream
|
@@ -99,6 +100,10 @@ HEADER
|
|
99
100
|
def extensions(stream)
|
100
101
|
end
|
101
102
|
|
103
|
+
# (enum) types are only supported by PostgreSQL
|
104
|
+
def types(stream)
|
105
|
+
end
|
106
|
+
|
102
107
|
def tables(stream)
|
103
108
|
sorted_tables = @connection.tables.sort
|
104
109
|
|
@@ -154,6 +159,7 @@ HEADER
|
|
154
159
|
columns.each do |column|
|
155
160
|
raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type)
|
156
161
|
next if column.name == pk
|
162
|
+
|
157
163
|
type, colspec = column_spec(column)
|
158
164
|
if type.is_a?(Symbol)
|
159
165
|
tbl.print " t.#{type} #{column.name.inspect}"
|
@@ -259,6 +265,7 @@ HEADER
|
|
259
265
|
|
260
266
|
parts << "on_update: #{foreign_key.on_update.inspect}" if foreign_key.on_update
|
261
267
|
parts << "on_delete: #{foreign_key.on_delete.inspect}" if foreign_key.on_delete
|
268
|
+
parts << "deferrable: #{foreign_key.deferrable.inspect}" if foreign_key.deferrable
|
262
269
|
|
263
270
|
" #{parts.join(', ')}"
|
264
271
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/
|
3
|
+
require "active_support/core_ext/module/delegation"
|
4
4
|
|
5
5
|
module ActiveRecord
|
6
6
|
module Scoping
|
@@ -57,8 +57,8 @@ module ActiveRecord
|
|
57
57
|
end
|
58
58
|
|
59
59
|
# This class stores the +:current_scope+ and +:ignore_default_scope+ values
|
60
|
-
# for different classes. The registry is stored as a thread
|
61
|
-
#
|
60
|
+
# for different classes. The registry is stored as either a thread or fiber
|
61
|
+
# local depending on the application configuration.
|
62
62
|
#
|
63
63
|
# This class allows you to store and get the scope values on different
|
64
64
|
# classes and different types of scopes. For example, if you are attempting
|
@@ -66,22 +66,22 @@ module ActiveRecord
|
|
66
66
|
# following code:
|
67
67
|
#
|
68
68
|
# registry = ActiveRecord::Scoping::ScopeRegistry
|
69
|
-
# registry.
|
69
|
+
# registry.set_current_scope(Board, some_new_scope)
|
70
70
|
#
|
71
71
|
# Now when you run:
|
72
72
|
#
|
73
|
-
# registry.
|
73
|
+
# registry.current_scope(Board)
|
74
74
|
#
|
75
|
-
# You will obtain whatever was defined in +some_new_scope+.
|
76
|
-
# and #set_value_for methods are delegated to the current ScopeRegistry
|
77
|
-
# object, so the above example code can also be called as:
|
78
|
-
#
|
79
|
-
# ActiveRecord::Scoping::ScopeRegistry.set_value_for(:current_scope,
|
80
|
-
# Board, some_new_scope)
|
75
|
+
# You will obtain whatever was defined in +some_new_scope+.
|
81
76
|
class ScopeRegistry # :nodoc:
|
82
|
-
|
77
|
+
class << self
|
78
|
+
delegate :current_scope, :set_current_scope, :ignore_default_scope, :set_ignore_default_scope,
|
79
|
+
:global_current_scope, :set_global_current_scope, to: :instance
|
83
80
|
|
84
|
-
|
81
|
+
def instance
|
82
|
+
ActiveSupport::IsolatedExecutionState[:active_record_scope_registry] ||= new
|
83
|
+
end
|
84
|
+
end
|
85
85
|
|
86
86
|
def initialize
|
87
87
|
@current_scope = {}
|
@@ -89,16 +89,28 @@ module ActiveRecord
|
|
89
89
|
@global_current_scope = {}
|
90
90
|
end
|
91
91
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
value_for(@#{type}, model, skip_inherited_scope)
|
96
|
-
end
|
92
|
+
def current_scope(model, skip_inherited_scope = false)
|
93
|
+
value_for(@current_scope, model, skip_inherited_scope)
|
94
|
+
end
|
97
95
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
96
|
+
def set_current_scope(model, value)
|
97
|
+
set_value_for(@current_scope, model, value)
|
98
|
+
end
|
99
|
+
|
100
|
+
def ignore_default_scope(model, skip_inherited_scope = false)
|
101
|
+
value_for(@ignore_default_scope, model, skip_inherited_scope)
|
102
|
+
end
|
103
|
+
|
104
|
+
def set_ignore_default_scope(model, value)
|
105
|
+
set_value_for(@ignore_default_scope, model, value)
|
106
|
+
end
|
107
|
+
|
108
|
+
def global_current_scope(model, skip_inherited_scope = false)
|
109
|
+
value_for(@global_current_scope, model, skip_inherited_scope)
|
110
|
+
end
|
111
|
+
|
112
|
+
def set_global_current_scope(model, value)
|
113
|
+
set_value_for(@global_current_scope, model, value)
|
102
114
|
end
|
103
115
|
|
104
116
|
private
|