activerecord 7.0.0 → 7.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ebfa716fe92ae11e586b89a89661980f107b3501dcbc64be179a191645046e2a
4
- data.tar.gz: 0eb8e39ca0252342714ad4791d5a17127697a7047b4ed2c7d48a867774f8470b
3
+ metadata.gz: e0de65b8a004bb74ee8951a2d34e5630f67568091f4c72bd99e28aaf8dd73097
4
+ data.tar.gz: 56d07fdf1ec276b9b88c7a13e79cfe4cfb3f3768dcbd1b5bf0f828bd2ba657d6
5
5
  SHA512:
6
- metadata.gz: 74365d846a7f543a82e61c3784aad30dd1de0e2a43e09ed4459a4b7b0fe9a14839a53122e12536c63d3bdcb638391390b83e6ffa4eb6a09f8713e1986674cda9
7
- data.tar.gz: a1379b0d243f97f6827df6ff2af3a7936164ad57ad60ded0aac71aeb45def6d7cee19571de89f8d93eeeaabfc6d193b9695879b8dac5c9f7d473e85617d15bea
6
+ metadata.gz: 2bf02198176f838235234fefd0658de10a37c51d704becaeccd1f8040ed4d79360a5128411c01af7226ca0c5806c5ed892c1fc55fc27cca55f48f5dc181d5dd5
7
+ data.tar.gz: e781dd6be129520aaeab76b1fea5bf98ce25793c623c2cde18cfd293fd2222c28e3d16ad4f8978688a74eaf683c2a6283358d7f815b8a924a0cc66f16c051c1e
data/CHANGELOG.md CHANGED
@@ -1,3 +1,96 @@
1
+ ## Rails 7.0.1 (January 06, 2022) ##
2
+
3
+ * Change `QueryMethods#in_order_of` to drop records not listed in values.
4
+
5
+ `in_order_of` now filters down to the values provided, to match the behavior of the `Enumerable` version.
6
+
7
+ *Kevin Newton*
8
+
9
+ * Allow named expression indexes to be revertible.
10
+
11
+ Previously, the following code would raise an error in a reversible migration executed while rolling back, due to the index name not being used in the index removal.
12
+
13
+ ```ruby
14
+ add_index(:settings, "(data->'property')", using: :gin, name: :index_settings_data_property)
15
+ ```
16
+
17
+ Fixes #43331.
18
+
19
+ *Oliver Günther*
20
+
21
+ * Better error messages when association name is invalid in the argument of `ActiveRecord::QueryMethods::WhereChain#missing`.
22
+
23
+ *ykpythemind*
24
+
25
+ * Fix ordered migrations for single db in multi db environment.
26
+
27
+ *Himanshu*
28
+
29
+ * Extract `on update CURRENT_TIMESTAMP` for mysql2 adapter.
30
+
31
+ *Kazuhiro Masuda*
32
+
33
+ * Fix incorrect argument in PostgreSQL structure dump tasks.
34
+
35
+ Updating the `--no-comment` argument added in Rails 7 to the correct `--no-comments` argument.
36
+
37
+ *Alex Dent*
38
+
39
+ * Fix schema dumping column default SQL values for sqlite3.
40
+
41
+ *fatkodima*
42
+
43
+ * Correctly parse complex check constraint expressions for PostgreSQL.
44
+
45
+ *fatkodima*
46
+
47
+ * Fix `timestamptz` attributes on PostgreSQL handle blank inputs.
48
+
49
+ *Alex Ghiculescu*
50
+
51
+ * Fix migration compatibility to create SQLite references/belongs_to column as integer when migration version is 6.0.
52
+
53
+ Reference/belongs_to in migrations with version 6.0 were creating columns as
54
+ bigint instead of integer for the SQLite Adapter.
55
+
56
+ *Marcelo Lauxen*
57
+
58
+ * Fix joining through a polymorphic association.
59
+
60
+ *Alexandre Ruban*
61
+
62
+ * Fix `QueryMethods#in_order_of` to handle empty order list.
63
+
64
+ ```ruby
65
+ Post.in_order_of(:id, []).to_a
66
+ ```
67
+
68
+ Also more explicitly set the column as secondary order, so that any other
69
+ value is still ordered.
70
+
71
+ *Jean Boussier*
72
+
73
+ * Fix `rails dbconsole` for 3-tier config.
74
+
75
+ *Eileen M. Uchitelle*
76
+
77
+ * Fix quoting of column aliases generated by calculation methods.
78
+
79
+ Since the alias is derived from the table name, we can't assume the result
80
+ is a valid identifier.
81
+
82
+ ```ruby
83
+ class Test < ActiveRecord::Base
84
+ self.table_name = '1abc'
85
+ end
86
+ Test.group(:id).count
87
+ # syntax error at or near "1" (ActiveRecord::StatementInvalid)
88
+ # LINE 1: SELECT COUNT(*) AS count_all, "1abc"."id" AS 1abc_id FROM "1...
89
+ ```
90
+
91
+ *Jean Boussier*
92
+
93
+
1
94
  ## Rails 7.0.0 (December 15, 2021) ##
2
95
 
3
96
  * Better handle SQL queries with invalid encoding.
@@ -20,6 +113,7 @@
20
113
 
21
114
  *Eileen M. Uchitelle*
22
115
 
116
+
23
117
  ## Rails 7.0.0.rc3 (December 14, 2021) ##
24
118
 
25
119
  * No changes.
@@ -29,6 +123,7 @@
29
123
 
30
124
  * No changes.
31
125
 
126
+
32
127
  ## Rails 7.0.0.rc1 (December 06, 2021) ##
33
128
 
34
129
  * Remove deprecated `ActiveRecord::DatabaseConfigurations::DatabaseConfig#spec_name`.
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2004-2021 David Heinemeier Hansson
1
+ Copyright (c) 2004-2022 David Heinemeier Hansson
2
2
 
3
3
  Arel originally copyright (c) 2007-2016 Nick Kallen, Bryan Helmkamp, Emilio Tagua, Aaron Patterson
4
4
 
@@ -594,19 +594,27 @@ module ActiveRecord
594
594
  # you can also define callbacks that get triggered when you add an object to or remove an
595
595
  # object from an association collection.
596
596
  #
597
- # class Project
598
- # has_and_belongs_to_many :developers, after_add: :evaluate_velocity
597
+ # class Firm < ActiveRecord::Base
598
+ # has_many :clients,
599
+ # dependent: :destroy,
600
+ # after_add: :congratulate_client,
601
+ # after_remove: :log_after_remove
599
602
  #
600
- # def evaluate_velocity(developer)
601
- # ...
603
+ # def congratulate_client(record)
604
+ # # ...
605
+ # end
606
+ #
607
+ # def log_after_remove(record)
608
+ # # ...
602
609
  # end
603
- # end
604
610
  #
605
611
  # It's possible to stack callbacks by passing them as an array. Example:
606
612
  #
607
- # class Project
608
- # has_and_belongs_to_many :developers,
609
- # after_add: [:evaluate_velocity, Proc.new { |p, d| p.shipping_date = Time.now}]
613
+ # class Firm < ActiveRecord::Base
614
+ # has_many :clients,
615
+ # dependent: :destroy,
616
+ # after_add: [:congratulate_client, -> (firm, record) { firm.log << "after_adding#{record.id}" }],
617
+ # after_remove: :log_after_remove
610
618
  # end
611
619
  #
612
620
  # Possible callbacks are: +before_add+, +after_add+, +before_remove+ and +after_remove+.
@@ -617,6 +625,18 @@ module ActiveRecord
617
625
  # Similarly, if any of the +before_remove+ callbacks throw an exception, the object
618
626
  # will not be removed from the collection.
619
627
  #
628
+ # Note: To trigger remove callbacks, you must use +destroy+ / +destroy_all+ methods. For example:
629
+ #
630
+ # * <tt>firm.clients.destroy(client)</tt>
631
+ # * <tt>firm.clients.destroy(*clients)</tt>
632
+ # * <tt>firm.clients.destroy_all</tt>
633
+ #
634
+ # +delete+ / +delete_all+ methods like the following do *not* trigger remove callbacks:
635
+ #
636
+ # * <tt>firm.clients.delete(client)</tt>
637
+ # * <tt>firm.clients.delete(*clients)</tt>
638
+ # * <tt>firm.clients.delete_all</tt>
639
+ #
620
640
  # == Association extensions
621
641
  #
622
642
  # The proxy objects that control the access to associations can be extended through anonymous
@@ -1438,7 +1438,7 @@ module ActiveRecord
1438
1438
 
1439
1439
  checks = []
1440
1440
 
1441
- if !options.key?(:name) && column_name.is_a?(String) && /\W/.match?(column_name)
1441
+ if !options.key?(:name) && expression_column_name?(column_name)
1442
1442
  options[:name] = index_name(table_name, column_name)
1443
1443
  column_names = []
1444
1444
  else
@@ -1447,7 +1447,7 @@ module ActiveRecord
1447
1447
 
1448
1448
  checks << lambda { |i| i.name == options[:name].to_s } if options.key?(:name)
1449
1449
 
1450
- if column_names.present?
1450
+ if column_names.present? && !(options.key?(:name) && expression_column_name?(column_names))
1451
1451
  checks << lambda { |i| index_name(table_name, i.columns) == index_name(table_name, column_names) }
1452
1452
  end
1453
1453
 
@@ -1515,7 +1515,7 @@ module ActiveRecord
1515
1515
  end
1516
1516
 
1517
1517
  def index_column_names(column_names)
1518
- if column_names.is_a?(String) && /\W/.match?(column_names)
1518
+ if expression_column_name?(column_names)
1519
1519
  column_names
1520
1520
  else
1521
1521
  Array(column_names)
@@ -1523,13 +1523,18 @@ module ActiveRecord
1523
1523
  end
1524
1524
 
1525
1525
  def index_name_options(column_names)
1526
- if column_names.is_a?(String) && /\W/.match?(column_names)
1526
+ if expression_column_name?(column_names)
1527
1527
  column_names = column_names.scan(/\w+/).join("_")
1528
1528
  end
1529
1529
 
1530
1530
  { column: column_names }
1531
1531
  end
1532
1532
 
1533
+ # Try to identify whether the given column name is an expression
1534
+ def expression_column_name?(column_name)
1535
+ column_name.is_a?(String) && /\W/.match?(column_name)
1536
+ end
1537
+
1533
1538
  def strip_table_name_prefix_and_suffix(table_name)
1534
1539
  prefix = Base.table_name_prefix
1535
1540
  suffix = Base.table_name_suffix
@@ -197,7 +197,7 @@ module ActiveRecord
197
197
 
198
198
  # Executes the SQL statement in the context of this connection.
199
199
  def execute(sql, name = nil, async: false)
200
- raw_execute(sql, name, async)
200
+ raw_execute(sql, name, async: async)
201
201
  end
202
202
 
203
203
  # Mysql2Adapter doesn't have to free a result after using it, but we use this method
@@ -163,6 +163,7 @@ module ActiveRecord
163
163
  default, default_function = field[:Default], nil
164
164
 
165
165
  if type_metadata.type == :datetime && /\ACURRENT_TIMESTAMP(?:\([0-6]?\))?\z/i.match?(default)
166
+ default = "#{default} ON UPDATE #{default}" if /on update CURRENT_TIMESTAMP/i.match?(field[:Extra])
166
167
  default, default_function = nil, default
167
168
  elsif type_metadata.extra == "DEFAULT_GENERATED"
168
169
  default = +"(#{default})" unless default.start_with?("(")
@@ -10,6 +10,8 @@ module ActiveRecord
10
10
  end
11
11
 
12
12
  def cast_value(value)
13
+ return if value.blank?
14
+
13
15
  time = super
14
16
  return time if time.is_a?(ActiveSupport::TimeWithZone)
15
17
 
@@ -525,7 +525,7 @@ module ActiveRecord
525
525
  scope = quoted_scope(table_name)
526
526
 
527
527
  check_info = exec_query(<<-SQL, "SCHEMA")
528
- SELECT conname, pg_get_constraintdef(c.oid) AS constraintdef, c.convalidated AS valid
528
+ SELECT conname, pg_get_constraintdef(c.oid, true) AS constraintdef, c.convalidated AS valid
529
529
  FROM pg_constraint c
530
530
  JOIN pg_class t ON c.conrelid = t.oid
531
531
  WHERE c.contype = 'c'
@@ -537,7 +537,7 @@ module ActiveRecord
537
537
  name: row["conname"],
538
538
  validate: row["valid"]
539
539
  }
540
- expression = row["constraintdef"][/CHECK \({2}(.+)\){2}/, 1]
540
+ expression = row["constraintdef"][/CHECK \((.+)\)/m, 1]
541
541
 
542
542
  CheckConstraintDefinition.new(table_name, expression, options)
543
543
  end
@@ -45,6 +45,19 @@ module ActiveRecord
45
45
  0
46
46
  end
47
47
 
48
+ def quote_default_expression(value, column) # :nodoc:
49
+ if value.is_a?(Proc)
50
+ value = value.call
51
+ if value.match?(/\A\w+\(.*\)\z/)
52
+ "(#{value})"
53
+ else
54
+ value
55
+ end
56
+ else
57
+ super
58
+ end
59
+ end
60
+
48
61
  def type_cast(value) # :nodoc:
49
62
  case value
50
63
  when BigDecimal
@@ -127,20 +127,20 @@ module ActiveRecord
127
127
  end
128
128
 
129
129
  def new_column_from_field(table_name, field)
130
- default = \
131
- case field["dflt_value"]
132
- when /^null$/i
133
- nil
134
- when /^'(.*)'$/m
135
- $1.gsub("''", "'")
136
- when /^"(.*)"$/m
137
- $1.gsub('""', '"')
138
- else
139
- field["dflt_value"]
140
- end
130
+ default = field["dflt_value"]
141
131
 
142
132
  type_metadata = fetch_type_metadata(field["type"])
143
- Column.new(field["name"], default, type_metadata, field["notnull"].to_i == 0, collation: field["collation"])
133
+ default_value = extract_value_from_default(default)
134
+ default_function = extract_default_function(default_value, default)
135
+
136
+ Column.new(
137
+ field["name"],
138
+ default_value,
139
+ type_metadata,
140
+ field["notnull"].to_i == 0,
141
+ default_function,
142
+ collation: field["collation"]
143
+ )
144
144
  end
145
145
 
146
146
  def data_source_sql(name = nil, type: nil)
@@ -389,6 +389,34 @@ module ActiveRecord
389
389
  end
390
390
  alias column_definitions table_structure
391
391
 
392
+ def extract_value_from_default(default)
393
+ case default
394
+ when /^null$/i
395
+ nil
396
+ # Quoted types
397
+ when /^'(.*)'$/m
398
+ $1.gsub("''", "'")
399
+ # Quoted types
400
+ when /^"(.*)"$/m
401
+ $1.gsub('""', '"')
402
+ # Numeric types
403
+ when /\A-?\d+(\.\d*)?\z/
404
+ $&
405
+ else
406
+ # Anything else is blank or some function
407
+ # and we can't know the value of that, so return nil.
408
+ nil
409
+ end
410
+ end
411
+
412
+ def extract_default_function(default_value, default)
413
+ default if has_default_function?(default_value, default)
414
+ end
415
+
416
+ def has_default_function?(default_value, default)
417
+ !default_value && %r{\w+\(.*\)|CURRENT_TIME|CURRENT_DATE|CURRENT_TIMESTAMP}.match?(default)
418
+ end
419
+
392
420
  # See: https://www.sqlite.org/lang_altertable.html
393
421
  # SQLite has an additional restriction on the ALTER TABLE statement
394
422
  def invalid_alter_table_type?(type, options)
@@ -1,35 +1,35 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Automatically expand encrypted arguments to support querying both encrypted and unencrypted data
4
- #
5
- # Active Record Encryption supports querying the db using deterministic attributes. For example:
6
- #
7
- # Contact.find_by(email_address: "jorge@hey.com")
8
- #
9
- # The value "jorge@hey.com" will get encrypted automatically to perform the query. But there is
10
- # a problem while the data is being encrypted. This won't work. During that time, you need these
11
- # queries to be:
12
- #
13
- # Contact.find_by(email_address: [ "jorge@hey.com", "<encrypted jorge@hey.com>" ])
14
- #
15
- # This patches ActiveRecord to support this automatically. It addresses both:
16
- #
17
- # * ActiveRecord::Base: Used in +Contact.find_by_email_address(...)+
18
- # * ActiveRecord::Relation: Used in +Contact.internal.find_by_email_address(...)+
19
- #
20
- # +ActiveRecord::Base+ relies on +ActiveRecord::Relation+ (+ActiveRecord::QueryMethods+) but it does
21
- # some prepared statements caching. That's why we need to intercept +ActiveRecord::Base+ as soon
22
- # as it's invoked (so that the proper prepared statement is cached).
23
- #
24
- # When modifying this file run performance tests in +test/performance/extended_deterministic_queries_performance_test.rb+ to
25
- # make sure performance overhead is acceptable.
26
- #
27
- # We will extend this to support previous "encryption context" versions in future iterations
28
- #
29
- # @TODO Experimental. Support for every kind of query is pending
30
- # @TODO It should not patch anything if not needed (no previous schemes or no support for previous encryption schemes)
31
3
  module ActiveRecord
32
4
  module Encryption
5
+ # Automatically expand encrypted arguments to support querying both encrypted and unencrypted data
6
+ #
7
+ # Active Record Encryption supports querying the db using deterministic attributes. For example:
8
+ #
9
+ # Contact.find_by(email_address: "jorge@hey.com")
10
+ #
11
+ # The value "jorge@hey.com" will get encrypted automatically to perform the query. But there is
12
+ # a problem while the data is being encrypted. This won't work. During that time, you need these
13
+ # queries to be:
14
+ #
15
+ # Contact.find_by(email_address: [ "jorge@hey.com", "<encrypted jorge@hey.com>" ])
16
+ #
17
+ # This patches ActiveRecord to support this automatically. It addresses both:
18
+ #
19
+ # * ActiveRecord::Base: Used in +Contact.find_by_email_address(...)+
20
+ # * ActiveRecord::Relation: Used in +Contact.internal.find_by_email_address(...)+
21
+ #
22
+ # +ActiveRecord::Base+ relies on +ActiveRecord::Relation+ (+ActiveRecord::QueryMethods+) but it does
23
+ # some prepared statements caching. That's why we need to intercept +ActiveRecord::Base+ as soon
24
+ # as it's invoked (so that the proper prepared statement is cached).
25
+ #
26
+ # When modifying this file run performance tests in +test/performance/extended_deterministic_queries_performance_test.rb+ to
27
+ # make sure performance overhead is acceptable.
28
+ #
29
+ # We will extend this to support previous "encryption context" versions in future iterations
30
+ #
31
+ # @TODO Experimental. Support for every kind of query is pending
32
+ # @TODO It should not patch anything if not needed (no previous schemes or no support for previous encryption schemes)
33
33
  module ExtendedDeterministicQueries
34
34
  def self.install_support
35
35
  ActiveRecord::Relation.prepend(RelationQueries)
@@ -9,7 +9,7 @@ module ActiveRecord
9
9
  module VERSION
10
10
  MAJOR = 7
11
11
  MINOR = 0
12
- TINY = 0
12
+ TINY = 1
13
13
  PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
@@ -92,6 +92,22 @@ module ActiveRecord
92
92
  end
93
93
  end
94
94
 
95
+ module SQLite3
96
+ module TableDefinition
97
+ def references(*args, **options)
98
+ args.each do |ref_name|
99
+ ReferenceDefinition.new(ref_name, type: :integer, **options).add_to(self)
100
+ end
101
+ end
102
+ alias :belongs_to :references
103
+
104
+ def column(name, type, index: nil, **options)
105
+ options[:precision] ||= nil
106
+ super
107
+ end
108
+ end
109
+ end
110
+
95
111
  module TableDefinition
96
112
  def references(*args, **options)
97
113
  args.each do |ref_name|
@@ -131,8 +147,13 @@ module ActiveRecord
131
147
  end
132
148
 
133
149
  def add_reference(table_name, ref_name, **options)
134
- ReferenceDefinition.new(ref_name, **options)
135
- .add_to(connection.update_table_definition(table_name, self))
150
+ if connection.adapter_name == "SQLite"
151
+ reference_definition = ReferenceDefinition.new(ref_name, type: :integer, **options)
152
+ else
153
+ reference_definition = ReferenceDefinition.new(ref_name, **options)
154
+ end
155
+
156
+ reference_definition.add_to(connection.update_table_definition(table_name, self))
136
157
  end
137
158
  alias :add_belongs_to :add_reference
138
159
 
@@ -140,6 +161,7 @@ module ActiveRecord
140
161
  def compatible_table_definition(t)
141
162
  class << t
142
163
  prepend TableDefinition
164
+ prepend SQLite3::TableDefinition
143
165
  end
144
166
  t
145
167
  end
@@ -1001,7 +1001,7 @@ module ActiveRecord
1001
1001
  # Determines the version number of the next migration.
1002
1002
  def next_migration_number(number)
1003
1003
  if ActiveRecord.timestamped_migrations
1004
- [Time.now.utc.strftime("%Y%m%d%H%M%S").to_i, ("%.14d" % number).to_i].max
1004
+ [Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % number].max
1005
1005
  else
1006
1006
  SchemaMigration.normalize_migration_number(number)
1007
1007
  end
@@ -1031,7 +1031,7 @@ module ActiveRecord
1031
1031
  end
1032
1032
 
1033
1033
  def join_scopes(table, predicate_builder, klass = self.klass, record = nil) # :nodoc:
1034
- scopes = @previous_reflection.join_scopes(table, predicate_builder, record) + super
1034
+ scopes = @previous_reflection.join_scopes(table, predicate_builder, klass, record) + super
1035
1035
  scopes << build_scope(table, predicate_builder, klass).instance_exec(record, &source_type_scope)
1036
1036
  end
1037
1037
 
@@ -155,7 +155,7 @@ module ActiveRecord
155
155
  end
156
156
 
157
157
  # Use #pluck as a shortcut to select one or more attributes without
158
- # loading a bunch of records just to grab the attributes you want.
158
+ # loading an entire record object per row.
159
159
  #
160
160
  # Person.pluck(:name)
161
161
  #
@@ -345,12 +345,13 @@ module ActiveRecord
345
345
  column = aggregate_column(column_name)
346
346
  column_alias = column_alias_for("#{operation} #{column_name.to_s.downcase}")
347
347
  select_value = operation_over_aggregate_column(column, operation, distinct)
348
- select_value.as(column_alias)
348
+ select_value.as(connection.quote_column_name(column_alias))
349
349
 
350
350
  select_values = [select_value]
351
351
  select_values += self.select_values unless having_clause.empty?
352
352
 
353
353
  select_values.concat group_columns.map { |aliaz, field|
354
+ aliaz = connection.quote_column_name(aliaz)
354
355
  if field.respond_to?(:as)
355
356
  field.as(aliaz)
356
357
  else
@@ -97,6 +97,9 @@ module ActiveRecord
97
97
  def missing(*associations)
98
98
  associations.each do |association|
99
99
  reflection = @scope.klass._reflect_on_association(association)
100
+ unless reflection
101
+ raise ArgumentError.new("An association named `:#{association}` does not exist on the model `#{@scope.name}`.")
102
+ end
100
103
  @scope.left_outer_joins!(association)
101
104
  @scope.where!(reflection.table_name => { reflection.association_primary_key => nil })
102
105
  end
@@ -424,18 +427,23 @@ module ActiveRecord
424
427
  # adapter this will either use a CASE statement or a built-in function.
425
428
  #
426
429
  # User.in_order_of(:id, [1, 5, 3])
427
- # # SELECT "users".* FROM "users" ORDER BY FIELD("users"."id", 1, 5, 3)
430
+ # # SELECT "users".* FROM "users"
431
+ # # ORDER BY FIELD("users"."id", 1, 5, 3)
432
+ # # WHERE "users"."id" IN (1, 5, 3)
428
433
  #
429
434
  def in_order_of(column, values)
430
435
  klass.disallow_raw_sql!([column], permit: connection.column_name_with_order_matcher)
436
+ return spawn.none! if values.empty?
431
437
 
432
438
  references = column_references([column])
433
439
  self.references_values |= references unless references.empty?
434
440
 
435
441
  values = values.map { |value| type_caster.type_cast_for_database(column, value) }
436
- column = order_column(column.to_s) if column.is_a?(Symbol)
442
+ arel_column = column.is_a?(Symbol) ? order_column(column.to_s) : column
437
443
 
438
- spawn.order!(connection.field_ordered_value(column, values))
444
+ spawn
445
+ .order!(connection.field_ordered_value(arel_column, values))
446
+ .where!(arel_column.in(values))
439
447
  end
440
448
 
441
449
  # Replaces any existing order defined on the relation with the specified order.
@@ -646,6 +646,21 @@ module ActiveRecord
646
646
  # Schedule the query to be performed from a background thread pool.
647
647
  #
648
648
  # Post.where(published: true).load_async # => #<ActiveRecord::Relation>
649
+ #
650
+ # When the +Relation+ is iterated, if the background query wasn't executed yet,
651
+ # it will be performed by the foreground thread.
652
+ #
653
+ # Note that {config.active_record.async_query_executor}[https://guides.rubyonrails.org/configuring.html#config-active-record-async-query-executor] must be configured
654
+ # for queries to actually be executed concurrently. Otherwise it defaults to
655
+ # executing them in the foreground.
656
+ #
657
+ # +load_async+ will also fallback to executing in the foreground in the test environment when transactional
658
+ # fixtures are enabled.
659
+ #
660
+ # If the query was actually executed in the background, the Active Record logs will show
661
+ # it by prefixing the log line with <tt>ASYNC</tt>:
662
+ #
663
+ # ASYNC Post Load (0.0ms) (db time 2ms) SELECT "posts".* FROM "posts" LIMIT 100
649
664
  def load_async
650
665
  return load if !connection.async_enabled?
651
666
 
@@ -257,8 +257,12 @@ module ActiveRecord
257
257
  scope = ENV["SCOPE"]
258
258
  verbose_was, Migration.verbose = Migration.verbose, verbose?
259
259
 
260
- Base.connection.migration_context.migrate(target_version || version) do |migration|
261
- scope.blank? || scope == migration.scope
260
+ Base.connection.migration_context.migrate(target_version) do |migration|
261
+ if version.blank?
262
+ scope.blank? || scope == migration.scope
263
+ else
264
+ migration.version == version
265
+ end
262
266
  end.tap do |migrations_ran|
263
267
  Migration.write("No migrations ran. (using #{scope} scope)") if scope.present? && migrations_ran.empty?
264
268
  end
@@ -58,7 +58,7 @@ module ActiveRecord
58
58
  end
59
59
 
60
60
  args = ["--schema-only", "--no-privileges", "--no-owner"]
61
- args << "--no-comment" if connection.database_version >= 110_000
61
+ args << "--no-comments" if connection.database_version >= 110_000
62
62
  args.concat(["--file", filename])
63
63
 
64
64
  args.concat(Array(extra_flags)) if extra_flags
data/lib/active_record.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # Copyright (c) 2004-2021 David Heinemeier Hansson
4
+ # Copyright (c) 2004-2022 David Heinemeier Hansson
5
5
  #
6
6
  # Permission is hereby granted, free of charge, to any person obtaining
7
7
  # a copy of this software and associated documentation files (the
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.0.0
4
+ version: 7.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-15 00:00:00.000000000 Z
11
+ date: 2022-01-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 7.0.0
19
+ version: 7.0.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 7.0.0
26
+ version: 7.0.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activemodel
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 7.0.0
33
+ version: 7.0.1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 7.0.0
40
+ version: 7.0.1
41
41
  description: Databases on Rails. Build a persistent domain model by mapping database
42
42
  tables to Ruby classes. Strong conventions for associations, validations, aggregations,
43
43
  migrations, and testing come baked-in.
@@ -434,10 +434,10 @@ licenses:
434
434
  - MIT
435
435
  metadata:
436
436
  bug_tracker_uri: https://github.com/rails/rails/issues
437
- changelog_uri: https://github.com/rails/rails/blob/v7.0.0/activerecord/CHANGELOG.md
438
- documentation_uri: https://api.rubyonrails.org/v7.0.0/
437
+ changelog_uri: https://github.com/rails/rails/blob/v7.0.1/activerecord/CHANGELOG.md
438
+ documentation_uri: https://api.rubyonrails.org/v7.0.1/
439
439
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
440
- source_code_uri: https://github.com/rails/rails/tree/v7.0.0/activerecord
440
+ source_code_uri: https://github.com/rails/rails/tree/v7.0.1/activerecord
441
441
  rubygems_mfa_required: 'true'
442
442
  post_install_message:
443
443
  rdoc_options: